Skip to main content
COSMICBYTEZLABS
NewsSecurityHOWTOsToolsTraining
StudyProjectsNewsletterHire MeAbout
Subscribe

Press Enter to search or Esc to close

News
Security
HOWTOs
Tools
Training
Study
Projects
Newsletter
Hire Me
About
RSS Feed
Reading List
Subscribe

Stay in the Loop

Get the latest security alerts, tutorials, and tech insights delivered to your inbox.

Subscribe NowFree forever. No spam.
COSMICBYTEZLABS

Your trusted source for IT intelligence, cybersecurity insights, and hands-on technical guides.

2567+ Articles
161+ Guides

CONTENT

  • Latest News
  • Security Alerts
  • HOWTOs
  • Checklists
  • Projects
  • Exam Prep

RESOURCES

  • Search
  • Browse Tags
  • Newsletter Archive
  • Reading List
  • RSS Feed

COMPANY

  • About Us
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CosmicBytez Labs. All rights reserved.

System Status: Operational
  1. Home
  2. Security
  3. CVE-2026-8445: justhtml Markdown Conversion XSS via Unescaped Angle Brackets
CVE-2026-8445: justhtml Markdown Conversion XSS via Unescaped Angle Brackets

Critical Security Alert

This vulnerability is actively being exploited. Immediate action is recommended.

SECURITYCRITICALCVE-2026-8445

CVE-2026-8445: justhtml Markdown Conversion XSS via Unescaped Angle Brackets

Critical XSS in justhtml <=1.11.0. The to_markdown() function leaves angle brackets unescaped, allowing raw HTML to reach downstream Markdown renderers.

Dylan H.

Security Team

August 24, 2026
4 min read

Affected Products

  • justhtml <= 1.11.0 (Python)

Overview

A second critical cross-site scripting (XSS) vulnerability has been disclosed in justhtml, the Python HTML parsing and sanitization library, disclosed alongside CVE-2026-7808. Tracked as CVE-2026-8445, this flaw affects justhtml versions ≤ 1.11.0 and lives in the to_markdown() conversion function, which fails to escape HTML-significant characters — specifically angle brackets (< and >) — in text nodes during Markdown serialization.

The result: content that is safely represented as HTML entities in to_html() output (e.g., &lt;script&gt;) is emitted as raw HTML tags (e.g., <script>) in to_markdown() output. Any downstream Markdown renderer that supports inline HTML will then execute the injected content.


Technical Details

FieldValue
CVE IDCVE-2026-8445
CVSS 3.19.8 (Critical)
Attack VectorNetwork
AuthenticationNone Required
Privileges RequiredNone
User InteractionNone
Affected Versionsjusthtml ≤ 1.11.0
Fixed Injusthtml 1.12.0
GitHub AdvisoryGHSA-3rcm-vjrc-p45j
Disclosed2026-08-23

Root Cause

The to_markdown() serializer escapes a small set of Markdown metacharacters (e.g., *, _, [) but does not escape angle brackets in text nodes. This is a fundamental omission: while angle brackets have no special meaning in Markdown syntax itself, virtually all Markdown renderers pass raw HTML through to the output, treating <script> as a literal HTML tag rather than text.

Affected Scenarios

1. Entity-encoded user input passed through to_markdown()

# Attacker input stored as: &lt;script&gt;alert(1)&lt;/script&gt;
# Safely rendered by to_html() as escaped text
# But to_markdown() emits: <script>alert(1)</script>

2. RCDATA/RAWTEXT element content Content from elements like <title>, <textarea>, <noscript>, and <plaintext> is parsed as character data by the HTML parser. When this content contains angle brackets, the serializer emits them raw in the Markdown output.

3. Any text node containing < or > The root cause is not limited to specific element types — the angle bracket escaping gap applies to all text nodes processed by to_markdown().


Impact Assessment

Who Is at Risk

Applications that:

  • Accept user-supplied HTML and convert it to Markdown for storage or display
  • Use justhtml's to_markdown() for sanitize-then-convert pipelines
  • Render the resulting Markdown via libraries that support inline HTML (e.g., commonmark, markdown-it, Python-Markdown, Marked.js)

Example Attack Chain

  1. Attacker submits HTML containing &lt;script&gt;alert(document.cookie)&lt;/script&gt; via a form
  2. Application passes through justhtml's sanitize() — the entity-encoded input appears safe
  3. Application calls to_markdown() to convert to Markdown for storage
  4. On render, the Markdown engine processes <script>alert(document.cookie)</script> as literal HTML
  5. Victim's browser executes the script, exfiltrating session cookies

Mitigation

Immediate Action: Upgrade to justhtml 1.12.0

The definitive fix is upgrading to justhtml >= 1.12.0, which properly escapes angle brackets in all text nodes during to_markdown() serialization.

pip install --upgrade "justhtml>=1.12.0"
# Verify
python -c "import justhtml; print(justhtml.__version__)"

Note: If CVE-2026-7808 is also a concern (sanitization bypass), upgrade directly to 1.16.0 to address both vulnerabilities simultaneously.

Interim Workarounds

If an immediate upgrade is blocked:

Option A: Escape angle brackets in the to_markdown() output

import html
from justhtml import JustHTML
 
def safe_to_markdown(html_input: str) -> str:
    doc = JustHTML(html_input, sanitize=True)
    md = doc.to_markdown()
    # Post-process: escape any remaining raw angle brackets in text segments
    # (Apply carefully — this is a band-aid, not a complete fix)
    return md

Option B: Avoid to_markdown() on untrusted input If Markdown output is required, convert via a trusted pipeline that re-sanitizes the Markdown output before rendering, or use a Markdown renderer configured to strip all HTML (sanitize: true or equivalent).

Option C: Deploy a strict Content Security Policy A CSP with script-src 'self' will block injected inline scripts from executing in supporting browsers. This is defence-in-depth — it does not fix the injection but limits the blast radius.


Detection

Review stored Markdown content and application logs for:

  • Markdown documents containing raw <script>, <img onerror=, <iframe>, or <svg onload= strings
  • User submissions that were processed via to_markdown() after 2024-01-01 (library adoption period)
  • Rendered pages showing unexpected JavaScript execution alerts in monitoring

Audit stored content if to_markdown() was used on user-supplied input before the upgrade:

import re
 
SUSPICIOUS = re.compile(r'<(script|iframe|img|svg|object|embed)\b', re.IGNORECASE)
 
def audit_markdown_store(documents):
    flagged = []
    for doc in documents:
        if SUSPICIOUS.search(doc['content']):
            flagged.append(doc['id'])
    return flagged

Relationship to CVE-2026-7808

Both CVE-2026-7808 and CVE-2026-8445 affect justhtml and were disclosed together on 2026-08-23. They are distinct vulnerabilities:

CVE-2026-7808CVE-2026-8445
Functionsanitize() / sanitize_dom()to_markdown()
Affected< 1.16.0≤ 1.11.0
Fix1.16.01.12.0
VectorSanitization bypassSerialization escape gap

Upgrading to justhtml >= 1.16.0 resolves both CVEs.


References

  • NVD — CVE-2026-8445
  • GitLab Advisory DB — GHSA-3rcm-vjrc-p45j
  • justhtml on PyPI
  • CVE-2026-7808: justhtml Sanitization Bypass
  • OWASP XSS Prevention Cheat Sheet
#CVE-2026-8445#XSS#Python#Markdown#HTML Injection#Critical Vulnerability#justhtml

Related Articles

CVE-2026-5388: Critical XSS Sanitization Bypass in justhtml

justhtml before 1.15.0 has multiple sanitization failures allowing XSS bypass via URL helpers, HTML serialization, and Markdown passthrough.

3 min read

CVE-2026-7808: justhtml HTML Sanitization Bypass (Critical XSS)

Critical XSS in justhtml before 1.16.0. Multiple bypass paths let dangerous content survive sanitization, enabling script injection with no auth required.

4 min read

SiYuan Column Width API Stored XSS (CVE-2026-73044)

SiYuan before v3.7.4 allows stored XSS via unescaped table column width values in style attributes. CVSS 9.0 Critical. Patch to v3.7.4.

3 min read
Back to all Security Alerts