{"id":"CVE-2026-8445","aliases":["GHSA-3rcm-vjrc-p45j"],"title":"JustHTML has a Sanitizer Bypass (in Markdown)","summary":"JustHTML has a Sanitizer Bypass (in Markdown)","severity":"medium","vendor":"justhtml","product":"justhtml","ecosystem":"pip","affected":["justhtml < 1.12.0"],"patched":["justhtml 1.12.0"],"published":"2026-03-18","updated":"2026-08-24","source":"OSV","sourceUrl":"https://osv.dev/vulnerability/GHSA-3rcm-vjrc-p45j","references":[{"url":"https://github.com/EmilStenstrom/justhtml/security/advisories/GHSA-3rcm-vjrc-p45j"},{"url":"https://github.com/EmilStenstrom/justhtml"}],"tags":["osv","pip"],"epss":0.00381,"epssPercentile":0.31978,"ingestedAt":"2026-08-24T19:25:43.962Z","slug":"CVE-2026-8445","body":"## Overview\n\n## Summary\n\n`to_markdown()` does not sufficiently escape text content that looks like HTML. As a result, untrusted input that is safe in `to_html()` can become raw HTML in Markdown output.\n\nThis is not specific to tokenizer raw-text states like `<title>`, `<noscript>`, or `<plaintext>`, although those states can trigger the behavior. The root cause is broader: Markdown text serialization leaves angle brackets unescaped in text nodes.\n\n## Details\n\nWhen converting a parsed document to Markdown, text nodes are escaped for a small set of Markdown metacharacters, but HTML-significant characters such as `<` and `>` are preserved. That means content parsed as text, including entity-decoded text or text produced by RCDATA/RAWTEXT-style parsing, can be emitted into Markdown as raw HTML.\n\nExamples of affected input include:\n\n- Text produced from entity-decoded input such as `&lt;script&gt;...&lt;/script&gt;`\n- Text inside elements like `<title>`, `<textarea>`, `<noscript>` (when parsed as raw text), and `<plaintext>`\n\nThis is distinct from actual `<script>` or `<style>` elements in the DOM. Those are already dropped by default in `to_markdown()` unless `html_passthrough=True`.\n\n## Proof of Concept\n\n### General case\n\n```python\nfrom justhtml import JustHTML\n\ndoc = JustHTML(\"<p>&lt;img src=x onerror=alert(1)&gt;</p>\", fragment=True)\n\nprint(doc.to_html())\nprint()\nprint(doc.to_markdown())\n\n## Affected packages\n\n- `justhtml < 1.12.0`\n\n## Remediation\n\nUpgrade to a patched release:\n\n- `justhtml 1.12.0`","depth":"sunlit","depthScore":28,"depthScoreParts":{"impact":27.5,"likelihood":0.1,"exploitation":0,"ransomware":0},"changes":[]}