Skip to content

Security

Rvx itself never evaluates code from strings, but as with any other framework, there are many ways to introduce severe security vulnerabilities into rvx based applications by directly using untrusted input in the wrong places.

Interpolation

Interpolation in rendered content is always safe to use.

// This is always safe to use:
<h1>Hello {untrusted}!</h1>;

// Using interpolation in content is equivalent to the following code:
const text = document.createTextNode("");
text.textContent = String(untrusted);
// This is always safe to use:
e("h1").append("Hello ", untrusted, "!");

// Using interpolation in content is equivalent to the following code:
const text = document.createTextNode("");
text.textContent = String(untrusted);

Interpolation in attribute values is safe to use as long as the same is true for HTML itself. E.g. an image alt attribute is fine, but href is not.

// The safety of this depends on the attribute ("alt" in this case):
<img alt={untrusted} />;

// Using interpolation in attribute values is equivalent to the following code:
image.setAttribute("alt", String(untrusted));
// The safety of this depends on the attribute ("alt" in this case):
e("img").set("alt", untrusted);

// Using interpolation in attribute values is equivalent to the following code:
image.setAttribute("alt", String(untrusted));

Common Mistakes

The examples below show some common mistakes and how they could be exploited.

// Setting "innerHTML" to untrusted input:
<div prop:innerHTML={untrusted} />;
<div prop:innerHTML="<img src=x onerror=alert(location.origin)>" />;

// Setting any event attributes to untrusted input:
<div onclick={untrusted} />;
<div onclick="alert(location.origin)" />;

// Using untrusted input as attribute name:
<div {...{ [untrusted]: someValue }} />
<div onclick="alert(location.origin)" />;

// Setting any url attribute to untrusted input:
<a href={untrusted}>Click me!</a>
<a href="javascript:alert(location.origin)">Click me!</a>
// Setting "innerHTML" to untrusted input:
e("div").prop("innerHTML", untrusted);
e("div").prop("innerHTML", "<img src=x onerror=alert(location.origin)>");

// Setting any event attributes to untrusted input:
e("div").set("onclick", untrusted);
e("div").set("onclick", "alert(location.origin)");

// Using untrusted input as attribute name:
e("div").set(untrusted, someValue);
e("div").set("onclick", "alert(location.origin)");

// Setting any url attribute to untrusted input:
e("a").set("href", untrusted).append("Click me!");
e("a").set("href", "javascript:alert(location.origin)").append("Click me!");

Note, that this is only a small fraction of things that can go wrong.