Follow-up to the HTML/XSS utilities (#352). A conservative, allowlist-based sanitizeHtml(input, options?): SafeHtml for untrusted rich-text, with zero external dependencies (runs on Bun/Node/Deno, no DOM).
Design (ready)
- Own submodule
src/http/sanitizer/: Tokenizer.ts (WHATWG-subset state machine, entity-decoding during tokenization to defeat jav	ascript:, rawtext mode for script/style, <-before-non-letter → text), Entities.ts (numeric clamping + curated named table; decode-once/re-escape-on-output invariant), Sanitizer.ts.
- Category D (drop tag + content): script, style, iframe, object, embed, svg, math, template, … (svg/math dropped by default — mXSS posture). Category U (unwrap, keep children): everything else not allowlisted.
- Attribute allowlist (
on* and style always removed); URL-attribute protocol check after entity-decode + control/whitespace strip against http/https/mailto.
- Output re-serialized from the parsed representation (never raw input slices); tag repair + EOF auto-close;
maxInputLength cap → RangeError.
- Returns
SafeHtml so it composes with the html tagged template.
Notes
- ~800–1000 LOC + tests. Honest residual-risk note required in JSDoc + docs (hand-rolled vs battle-tested DOMPurify/sanitize-html).
- Docs: separate
http/sanitizer page (EN+DE); the http/html-xss page links to it (replacing its "use a dedicated lib" paragraph).
- Full design captured in the accepted implementation plan.
Follow-up to the HTML/XSS utilities (#352). A conservative, allowlist-based
sanitizeHtml(input, options?): SafeHtmlfor untrusted rich-text, with zero external dependencies (runs on Bun/Node/Deno, no DOM).Design (ready)
src/http/sanitizer/:Tokenizer.ts(WHATWG-subset state machine, entity-decoding during tokenization to defeatjav	ascript:, rawtext mode for script/style,<-before-non-letter → text),Entities.ts(numeric clamping + curated named table; decode-once/re-escape-on-output invariant),Sanitizer.ts.on*andstylealways removed); URL-attribute protocol check after entity-decode + control/whitespace strip againsthttp/https/mailto.maxInputLengthcap →RangeError.SafeHtmlso it composes with thehtmltagged template.Notes
http/sanitizerpage (EN+DE); thehttp/html-xsspage links to it (replacing its "use a dedicated lib" paragraph).