How to Handle Untrusted HTML Safely
Treat imported markup as code, define an allowlist, isolate rendering, and avoid trusting a sanitized string forever.
The short version
HTML from a user, model, clipboard, or URL is untrusted until your application enforces a policy.
Start with a threat model
Untrusted HTML can contain scripts, event handlers, dangerous URLs, form submissions, embedded documents, and CSS that obscures the surrounding interface. The risk depends on where and how the markup is rendered.
Escaping is correct when the goal is to display source code. Sanitization is required when the goal is to render a permitted subset of HTML.
Use an allowlist and defense in depth
A sanitizer is security infrastructure. Use a maintained library, keep it updated, and test known payload classes. Regular expressions are not an HTML parser.
- Allow only the elements and attributes the product needs.
- Remove inline event handlers and unsafe URL schemes.
- Sanitize on the server at the trust boundary.
- Apply a restrictive Content Security Policy.
- Use an iframe or Shadow DOM when isolation matches the use case.
Revisit the policy when features change
A page sanitized under an older policy may become unsafe if the renderer later enables new attributes, custom elements, or URL handling. Store provenance when possible and re-sanitize when the trust boundary changes.
HTML Docs separates imported shell structure from editable regions and renders in an isolated surface, but product-specific policies still need to decide which behaviors are allowed.