Defense in depth
- DOM-only renderer (primary defense). The preview is built exclusively from
document.createElement and text nodes, then committed with replaceChildren. No innerHTML / outerHTML / insertAdjacentHTML / document.write ever touch user input — so no Markdown string is parsed as markup. This structurally removes the main XSS sink and defeats mutation-XSS.
- Allowlisted URLs. Link
href and image src are resolved and accepted only for http, https, mailto, relative, and anchor targets. javascript:, vbscript:, data: (for links), control characters, and HTML-entity-smuggled schemes are rejected.
- Image
src hardening. data: is permitted for images only when the mediatype is a raster image (png/jpeg/gif/webp/bmp) — never text/html or image/svg+xml (SVG can carry script). Rejected images render a visible, inert "blocked" chip.
- Secondary escaping. Even though content is inserted as text, raw angle brackets and ampersands are additionally escaped in the HTML export path so copied output is safe to paste anywhere.
- No script execution surface. No
on* attributes are ever emitted; no element types outside a fixed safe allowlist are created; the Content-Security-Policy ships with default-src 'none', no unsafe-eval, and connect-src 'none' (zero network).
- Outbound links defanged. External links render with
rel="noopener noreferrer nofollow" and target="_blank" to block reverse-tabnabbing and referrer leakage.
Adversarial inputs — verified neutralized
These run live in your browser on dialog open: each malicious string is passed through the exact renderer used for the preview, and the output is asserted to contain no executable sink. Load the payloads into the editor yourself from the button below.