Prompt and context
A SaaS product is adding user-authored rich text to comments, a knowledge base, and templates. The team wants the browser-native HTML Sanitizer API to reduce custom filtering rules, but the API is unavailable in some major browsers. Decide whether to adopt it and explain the security, experience, compatibility, and operating trade-offs.
What the interviewer evaluates
- Whether you define the threat model, allowed content, and server trust boundary first.
- Whether you distinguish
setHTML(), custom Sanitizer configurations,setHTMLUnsafe(), and Trusted Types. - Whether browser coverage, fallback implementation, content consistency, and migration cost are quantified.
- Whether staged metrics validate XSS risk, editing success, performance, and rollback readiness.
Clarifying questions to ask
Confirm whether rich text needs links, images, tables, embeds, styles, or custom attributes; whether content is rendered server-side, exported to email, indexed for search, or reused on other clients. Confirm supported browsers, existing sanitizers, compliance needs, attack surface, and acceptable feature degradation.
30-second answer
I would use a native-first, server-validated, capability-tiered fallback instead of replacing the existing sanitizer at once. Native setHTML() follows a safe sanitization path, but coverage is limited, so unsupported browsers use an audited equivalent policy. Start with a low-complexity surface such as comments and measure dangerous-payload blocking, content fidelity, edit success, latency, and browser distribution. The server still sanitizes and encodes at output boundaries; Trusted Types adds a constraint around injection sinks.
Step-by-step deep dive
1. Define user value and threat model
The user value is reliable formatted content; the primary risk is sending untrusted HTML to the DOM or another rendering sink. Define allowed elements, attributes, URL schemes, and media sources before deciding which capabilities justify maintenance cost.
2. Separate native API capabilities
Element.setHTML() and Document.parseHTML() use safe sanitization defaults; a custom configuration can tighten the allowlist. setHTMLUnsafe() is for cases that need special structure, but requires strict configuration and review. The specification requires safe methods to remove script-capable markup, so the API is not a permit for arbitrary HTML.
3. Evaluate coverage and fallback
MDN labels the HTML Sanitizer API as Limited availability. Feature-detect the native path and choose a server or audited-library path when unsupported. Share allowlists, test fixtures, and version records across both paths. A fallback should drop high-risk capabilities rather than loosen policy for visual parity.
4. Design a cross-client content contract
Store the original input and a normalized safe representation, defining which representation serves editing, preview, email, search, and export. Revalidate at every server output boundary. Client-side sanitization reduces DOM injection risk; it does not replace server authorization, storage, or rendering policy.
5. Design a gradual rollout and metrics
Enable one content type for a small tenant cohort and compare native and fallback findings. Track dangerous-payload blocking, unwanted-removal appeals, edit-submit success, first-render and input latency, browser coverage, policy-version consistency, and security events.
6. Handle Trusted Types and operations
Enable Trusted Types reporting or enforcement for high-risk sinks, requiring policy functions to return validated types. Establish rule-change approval, malicious-fixture regression, content reprocessing, and emergency rollback. Do not let a browser update silently change the security policy.
High-quality sample answer
I would put content capability, threat model, and runtime environment in three decision tables. The HTML Sanitizer API is useful for structured client-side cleaning before untrusted HTML enters the DOM; setHTML() has safe defaults and the WHATWG specification reduces the chance of script-capable markup being retained, but MDN still marks coverage as limited. The product plan is native-first with a mature-library or server-policy fallback, sharing allowed elements, attributes, schemes, and fixtures. The server stores original and safe representations and validates separately for pages, email, search, and export; client cleaning does not provide authorization or complete XSS protection. Roll out comments first and measure blocking, fidelity, submission success, performance, browser distribution, and security events. Use setHTMLUnsafe() only for a justified structure requirement with strict configuration, Trusted Types, and review. Replay historical malicious fixtures after policy updates and immediately roll back on regression.
Common mistakes
- Assuming a native browser API removes the need for server-side sanitization.
- Testing only the demo and ignoring unsupported browsers and fallback consistency.
- Relaxing
setHTMLUnsafe()configuration to preserve arbitrary embeds. - Replacing fidelity, unwanted-removal, and security metrics with one filter-success number.
- Treating Trusted Types as a sanitizer, or a sanitizer as authorization.
Follow-up questions and responses
Why not switch every surface to the native API immediately?
Coverage, content capability, and legacy-data migration remain uncertain. A reversible rollout with a fallback validates real browser and content distributions first.
What if native and server policies differ?
Share versioned allowlists and malicious fixtures, with the server as the final boundary. Record policy versions and samples when the client finds a difference; never silently loosen the rule.
When is Trusted Types enforcement worth enabling?
After major sinks are inventoried, policy functions and third-party components are migrated, and report-only mode shows low false positives, enable enforcement in stages.