跳转到内容
简体中文

HTML responses & XSS prevention

此内容尚不支持你的语言。

The html tagged template escapes every interpolation by default, so building an HTML response is safe without thinking about it. completeHtml sends it with the right content-type.

import { completeHtml, html, Status } from 'actor-ts/http';
get((req) => {
const name = req.query.name ?? 'world'; // untrusted
return completeHtml(Status.OK, html`
<h1>Hello, ${name}!</h1>
`);
});

If name is <script>alert(1)</script>, the output is Hello, &lt;script&gt;alert(1)&lt;/script&gt;! — inert.

ExportWhat it does
escapeHtml(s)Escape & < > " ' and the backtick.
html`…`Tagged template; escapes interpolations, returns SafeHtml.
SafeHtmlBrand for already-safe HTML; interpolated verbatim.
rawHtml(s)Wrap a string you have already made safe.
completeHtml(status, body, headers?)text/html; charset=utf-8 + X-Content-Type-Options: nosniff.

Interpolation rules for html`…`: a SafeHtml value is inserted verbatim (so fragments nest), arrays are rendered item-by-item, null/undefined become the empty string, and everything else is coerced to a string and escaped.

const items = ['<a>', '<b>'];
const list = html`<ul>${items.map((i) => html`<li>${i}</li>`)}</ul>`;
// <ul><li>&lt;a&gt;</li><li>&lt;b&gt;</li></ul>

Escaping neutralises markup — it does not make attacker-authored HTML safe to render as HTML. If you must accept rich HTML (comments, wiki markup), sanitise it with a dedicated, battle-tested library such as sanitize-html or DOMPurify before wrapping the result in rawHtml. A conservative built-in sanitizer is tracked separately.