{"id":"CVE-2026-25516","aliases":["GHSA-v82v-c5x8-w282","PYSEC-2026-2231"],"title":"NiceGUI's XSS vulnerability in ui.markdown() allows arbitrary JavaScript execution through unsanitized HTML content","summary":"NiceGUI's XSS vulnerability in ui.markdown() allows arbitrary JavaScript execution through unsanitized HTML content","severity":"medium","cvss":6.1,"cvssVector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N","vendor":"nicegui","product":"nicegui","ecosystem":"pip","affected":["nicegui < 3.7.0"],"patched":["nicegui 3.7.0"],"published":"2026-02-05","updated":"2026-07-13","source":"OSV","sourceUrl":"https://osv.dev/vulnerability/GHSA-v82v-c5x8-w282","references":[{"url":"https://github.com/zauberzeug/nicegui/security/advisories/GHSA-v82v-c5x8-w282"},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-25516"},{"url":"https://github.com/zauberzeug/nicegui/commit/f1f7533577875af7d23f161ed3627f73584cb561"},{"url":"https://github.com/zauberzeug/nicegui"}],"tags":["osv","pip"],"epss":0.0025,"epssPercentile":0.16691,"ingestedAt":"2026-07-13T18:58:03.354Z","slug":"CVE-2026-25516","body":"## Overview\n\n## Description\n\nThe `ui.markdown()` component uses the `markdown2` library to convert markdown content to HTML, which is then rendered via `innerHTML`. By default, `markdown2` allows raw HTML to pass through unchanged. This means that if an application renders user-controlled content through `ui.markdown()`, an attacker can inject malicious HTML containing JavaScript event handlers.\n\nUnlike other NiceGUI components that render HTML (`ui.html()`, `ui.chat_message()`, `ui.interactive_image()`), the `ui.markdown()` component does not provide or require a `sanitize` parameter, leaving applications vulnerable to XSS attacks.\n\n## Proof of Concept\n\n```python\nfrom nicegui import ui\n\n# User-controlled input containing malicious payload\nuser_input = 'Hello! <img src=x onerror=\"alert(\\'XSS\\')\">'\n\nui.markdown(user_input)  # XSS executes when page loads\n\nui.run()\n```\n\nWhen this page loads, the JavaScript in the `onerror` handler executes, potentially allowing an attacker to:\n- Steal session cookies or authentication tokens\n- Perform actions on behalf of the user\n- Redirect users to malicious sites\n- Modify page content\n\n## Impact\n\nApplications that render user-provided content through `ui.markdown()` are vulnerable to stored or reflected XSS attacks. This is particularly concerning for:\n- Chat applications displaying user messages\n- CMS or documentation systems with user-editable content\n- Any application that displays markdown from untrusted sources\n\n## Remediation\n\nA release has been published in version 3.7.0.\n\n### For Users (Immediate Workaround)\n\nUntil a fix is released, **do not pass untrusted content directly to `ui.markdown()`**. Instead, use one of these approaches:\n\n**Option 1: Convert and sanitize manually using `ui.html()`**\n\n```python\nimport markdown2\nfrom html_sanitizer import Sanitizer\n\nsanitizer = Sanitizer()\n\ndef safe_markdown(content: str) -> None:\n    \"\"\"Render markdown with HTML sanitization.\"\"\"\n    html = markdown2.markdown(content)\n    ui.html(sanitizer.sanitize(html), sanitize=False)\n\n# Usage\nsafe_markdown(user_input)\n```\n\n**Option 2: Escape HTML before markdown conversion (if raw HTML not needed)**\n\n```python\nimport html\n\n# Escape HTML entities - prevents any HTML from being interpreted\nui.markdown(html.escape(user_input))\n```\n\n### Proposed Fix\n\nAdd a `sanitize` parameter to `ui.markdown()` consistent with other HTML-rendering components, and/or add an `escape_html` parameter.\n\n## Affected packages\n\n- `nicegui < 3.7.0`\n\n## Remediation\n\nUpgrade to a patched release:\n\n- `nicegui 3.7.0`","depth":"sunlit","depthScore":34,"depthScoreParts":{"impact":33.6,"likelihood":0.1,"exploitation":0,"ransomware":0},"changes":[]}