raw()
Marks a string as trusted: every check is turned off for it.
Signature#
raw(value: string): RawStringUsage#
Use it for HTML from a trusted source (a Markdown renderer, a sanitizer, your own templates), never for user input:
import { raw } from "@vincle/core";
<div>{raw(await renderMarkdown(post.body))}</div>;<div>{raw(DOMPurify.sanitize(userInput))}</div>;
// ❌ XSS if userInput contains <script>alert(1)</script><div>{raw(userInput)}</div>;// ✅ Vincle escapes by default<div>{userInput}</div>;In an attribute#
In an attribute, raw() is a trusted value, not markup: it is emitted as
written, a URL included (no scheme check), except ", so it can never end its
attribute. The escaped " decodes back before CSS, JS or the DOM reads it, so
the value still means what it says.
<a href={raw("javascript:go()")}>x</a>; // href="javascript:go()"<a title={raw('" onmouseover="alert(1)')}>x</a>; // title="" onmouseover="…"A sanitizer's output is markup: it belongs in content, not in an attribute.
dangerouslySetInnerHTML#
The same promise as raw(), for React compatibility:
<div dangerouslySetInnerHTML={{ __html: "<b>bold</b>" }} />rawUrl(): a narrower trust boundary#
rawUrl() is a separate function for URLs. It skips only the scheme check: the
value is still escaped, so unlike raw() it cannot end its attribute, and in
content position it is text like any other.
import { rawUrl } from "@vincle/core";
<a href={rawUrl("phpstorm://open?file=src/app.ts")}>open in the IDE</a>;raw() vs rawUrl()#
| Function | In content | In attribute | Grep target |
|---|---|---|---|
raw() |
Emitted as verbatim markup | Escaped as a value, trust for scheme | raw( |
rawUrl() |
N/A (type error) | Trust for scheme only, still escaped | rawUrl( |
A RawString is markup — it bypasses escaping entirely. A RawUrl is a
URL — it bypasses only the scheme filter. The distinction is enforced at
both the type level (RawString and RawUrl are nominally distinct) and
runtime (instanceof checks treat them differently). An audit should list
every raw() call and verify the value originates from a trusted source
(sanitizer output, template engine, hardcoded markup), never from user input.
See also#
- Security model: full XSS defence model
- VNode:
RawStringin the type union