Security

Security

Veloz closes the common XSS holes by default, in the browser and in server rendering.

Text is never HTML

Strings in JSX are inserted as text nodes in the browser and escaped (& < > " ') on the server. User input can't create elements.

tsx
const name = '<img src=x onerror=alert(1)>';
<p>Hello, {name}</p>; // shows the text, runs nothing

innerHTML is sanitized

innerHTML always goes through sanitize(): an allowlist of tags and attributes, no on* handlers, no srcdoc, unsafe URLs replaced with about:blank, and rel="noopener noreferrer" on links. With Trusted Types available, the output is wrapped in a veloz-sanitize policy.

tsx
import { sanitize } from '@velozjs/dom';

<article innerHTML={markdownHtml} />;           // sanitized automatically
sanitize(html, { allowedTags: new Set(['b', 'i']) }); // stricter, by hand

On the server, innerHTML isn't printed; the client sets it during hydration.

URLs can't run script

href, src, action, formaction, srcset, poster, xlink:href and other URL attributes are checked with one shared function, on the client, in the sanitizer and in SSR. It removes the characters browsers ignore when reading a URL scheme first, so tricks like java\tscript: are caught.

  • javascript: and vbscript: are always blocked.
  • data: is allowed only for raster images (png, gif, jpeg, webp, avif, bmp) in src, poster and srcset.
  • A rejected value removes the attribute instead of leaving an older one in place.

Attribute names are validated

Names with spaces, quotes, = or > are rejected, so spreading props from data you don't control can't inject markup. SSR also validates tag names.

Handlers are functions

String handlers like onclick="..." are rejected. Handlers are stored off the DOM and never printed by SSR.

CSP

No eval, new Function, document.write or inline scripts. Runtime styles use a constructable stylesheet. Server CSS escapes </style, and the data script of renderToStringAsync escapes <, > and & and accepts a nonce.

What stays your job

  • URL checks block script execution, not open redirects: validate destinations that come from users.
  • Don't put untrusted input into css or style without validating it; it can't run script, but it can change the page.

Found a vulnerability? Report it privately through GitHub security advisories.