Rule
Rich text output must be sanitized server-side before storage and before rendering.
Why
A rich text field that stores raw HTML is an open door to stored XSS attacks.
Must
- Sanitize HTML with a strict allowlist of elements and attributes on the server.
- Never sanitize only on the client.
- Strip script, iframe, form, and on* attributes unconditionally.
- Use a well-maintained library such as DOMPurify (server-side equivalent) for sanitization.
- Escape HTML entities in Markdown-rendered output before injection into the DOM.
Should
- Store both the raw Markdown and the sanitized HTML as separate fields.
- Re-sanitize existing content when the allowlist policy changes.
Anti-patterns
- Rendering stored HTML with innerHTML without sanitization.
- Relying on the editor to produce safe output.
Test Cases
- <script> tag in input is removed from stored content.
- onerror attribute on img is stripped.
Telemetry
- content_sanitization_strips_detected
- rich_text_save_rejected