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, <script>alert(1)</script>! — inert.
The pieces
Section titled “The pieces”| Export | What it does |
|---|---|
escapeHtml(s) | Escape & < > " ' and the backtick. |
html`…` | Tagged template; escapes interpolations, returns SafeHtml. |
SafeHtml | Brand 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><a></li><li><b></li></ul>Untrusted markup
Section titled “Untrusted markup”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.
Where to next
Section titled “Where to next”- Error handling — safe error pages.
- Security headers — CSP, nosniff, and friends.
- Static files — the directory listing escapes filenames the same way.
