HTML-Antworten & XSS-Schutz
Das html-Tagged-Template escapet standardmäßig jede Interpolation — eine
HTML-Antwort zu bauen ist also sicher, ohne darüber nachzudenken.
completeHtml sendet sie mit dem richtigen 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> `);});Ist name gleich <script>alert(1)</script>, lautet die Ausgabe
Hello, <script>alert(1)</script>! — wirkungslos.
Die Bausteine
Abschnitt betitelt „Die Bausteine“| Export | Zweck |
|---|---|
escapeHtml(s) | Escapet & < > " ' und das Backtick. |
html`…` | Tagged Template; escapet Interpolationen, liefert SafeHtml. |
SafeHtml | Brand für bereits sicheres HTML; wird verbatim eingesetzt. |
rawHtml(s) | Umschließt einen String, den du bereits sicher gemacht hast. |
completeHtml(status, body, headers?) | text/html; charset=utf-8 + X-Content-Type-Options: nosniff. |
Interpolationsregeln für html`…`: ein SafeHtml-Wert wird verbatim
eingesetzt (Fragmente verschachteln also), Arrays werden Element für
Element gerendert, null/undefined werden zum leeren String, alles andere
wird zu einem String gecastet und escapet.
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
Abschnitt betitelt „Untrusted Markup“Escaping neutralisiert Markup — es macht von Angreifern verfasstes HTML
nicht sicher, um es als HTML zu rendern. Musst du Rich-HTML annehmen
(Kommentare, Wiki-Markup), sanitisiere es mit einer dedizierten,
kampferprobten Bibliothek wie
sanitize-html oder
DOMPurify, bevor du das Ergebnis in rawHtml verpackst. Ein konservativer,
eingebauter Sanitizer wird separat verfolgt.
Wie weiter
Abschnitt betitelt „Wie weiter“- Fehlerbehandlung — sichere Fehlerseiten.
- Security-Header — CSP, nosniff und Co.
- Statische Dateien — das Directory-Listing escapet Dateinamen genauso.
