fix(frontend): render raw HTML in package READMEs (sanitized)#602
Conversation
markdown-it was configured with `html: false`, which escapes all raw HTML in README source. Tags like <details>/<summary> rendered as literal visible text on package pages (e.g. mops.one/googlemail-client) instead of as elements, even though GitHub renders them via its sanitized allowlist. Enable `html: true` and sanitize the rendered output with DOMPurify (GitHub-equivalent: allow a safe tag allowlist incl. <details>/<summary>, strip <script>/event-handlers/javascript: URLs). README rendering is client-side at view time, so this fixes every already-published package page on next load — no republish needed. Also: - the inline comment claimed "Enable HTML tags in source" while the value was `false`; corrected to match behavior. - removed a dead duplicate `mdit.render(markdown)` whose result was discarded (parsed twice per render). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Cursor AI review👍 APPROVE — looks safe to merge
VerdictDecision: APPROVE Generated for commit 9efd2d5 |
Package authors could embed malicious HTML/JS in AsciiDoc documentation. Apply DOMPurify.sanitize() to doc.convert() output, consistent with how markdown-to-html.ts already sanitizes markdown. Adds @types/dompurify dev dependency for TypeScript support. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Added a follow-up commit: sanitize Asciidoctor output in PackageDocs to prevent XSS.
Also added another commit: restrict DOMPurify allowlist to safe Markdown output tags — the bare |
Default DOMPurify config permits <form>, <input>, <button>, and <style>, allowing README authors to embed phishing forms or page-breaking CSS. Restrict to an explicit structural allowlist matching GitHub's sanitizer posture. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Problem
Package README pages show raw HTML tags as literal visible text. For example, mops.one/googlemail-client@0.1.3 renders a
<details>/<summary>collapsible block as the plain strings<details>and<summary>rather than a working disclosure widget. GitHub renders the same README correctly.Root cause
frontend/logic/markdown-to-html.tsconfigures markdown-it withhtml: false, which escapes all raw HTML in README source. The inline comment even read// Enable HTML tags in source— the opposite of whatfalsedoes. GitHub, by contrast, permits a sanitized allowlist of tags (including<details>/<summary>), which is why authors write them.Fix
Enable
html: trueand sanitize the rendered output with DOMPurify — the standard, GitHub-equivalent approach:<details>/<summary>, and keepsclassso starry-night syntax highlighting is preserved).<script>, inline event handlers, andjavascript:URLs — so enabling raw HTML does not open an XSS hole, which matters since READMEs are arbitrary third-party author content.Two incidental cleanups in the same file:
mdit.render(markdown)call whose result was discarded (the source was parsed twice per render).Impact / retroactivity
README → HTML conversion happens client-side at view time (
PackageReadme.sveltecallsmarkdownToHtml(readme, …)on each render), from the stored Markdown source. So this fix repairs every already-published package page on the next load — no republish, version bump, or re-upload required.Validation
svelte-check --threshold error→ 0 errors (pre-existing warnings unchanged).3.4.11) to match the repo's dependency convention. Lockfile gains only the single dependency.🤖 Generated with Claude Code