CVE-2026-21873
Python vulnerability analysis and mitigation

Overview

CVE-2026-21873 is a zero-click Cross-Site Scripting (XSS) vulnerability in NiceGUI, a Python-based UI framework, affecting all applications that use the ui.sub_pages component. The flaw exists in versions 2.22.0 through 3.4.1 and was disclosed on January 8, 2026, with a patch released the same day in version 3.5.0. The CNA (GitHub) assigned a CVSS v3.1 score of 7.2 (High), while NVD assessed it at 6.1 (Medium) (Github Advisory, NVD).

Technical details

The root cause (CWE-79) is insufficient sanitization of the URL fragment identifier before it is passed to a dynamically constructed JavaScript string. When a pushstate event fires, the handleStateEvent function emits a sub_pages_open event containing the current path. The SubPagesRouter._handle_open method processes this path and ultimately calls _scroll_to_fragment, which interpolates the attacker-controlled fragment directly into a run_javascript call: document.querySelector('#{fragment}, a[name="{fragment}"]')?.scrollIntoView(...). An attacker can break out of the CSS selector string by embedding a single quote and JavaScript payload in the fragment (e.g., #x');alert(document.domain)//). Because browsers allow cross-origin pages to set an iframe's src including the fragment, this attack requires no privileges and no user interaction beyond visiting the attacker's page (Github Advisory).

Impact

Successful exploitation allows an attacker to execute arbitrary JavaScript in the context of any NiceGUI application using ui.sub_pages, scoped to the privileges of the currently authenticated user. This can lead to session token theft, phishing, unauthorized UI state manipulation, and data exfiltration up to the level of the highest-privileged user of the application. Availability is not impacted, but confidentiality and integrity are both affected at a low-to-moderate level depending on the application's sensitivity (Github Advisory, NVD).

Exploitability

A proof-of-concept exploit is publicly available in the GitHub Security Advisory and was demonstrated against the live nicegui.io domain at the time of disclosure. The EPSS score is approximately 0.009% (1st percentile), indicating low current exploitation probability. There is no evidence of in-the-wild exploitation or threat actor attribution, and the vulnerability is not listed in the CISA KEV catalog (Github Advisory).

Exploitation steps

  1. Identify target: Locate a publicly accessible NiceGUI application (versions 2.22.0–3.4.1) that uses ui.sub_pages and does not set X-Frame-Options: DENY or Content-Security-Policy: frame-ancestors 'none'.
  2. Craft malicious page: Create an attacker-controlled HTML page containing an iframe element targeting the vulnerable NiceGUI application.
  3. Inject payload via fragment: Set the iframe src to the target URL with a crafted fragment that breaks out of the JavaScript CSS selector string, e.g., https://target.example.com#x');alert(document.domain)//. The PoC function from the advisory is:
function triggerXSS() {
  if (!myiframe.src.includes("#")) {
    myiframe.src = "https://target.example.com#x');alert(document.domain)//";
  }
}
  1. Trigger execution: When a victim visits the attacker's page, the iframe loads the target NiceGUI app. The browser fires a pushstate/popstate event, causing handleStateEvent to emit sub_pages_open with the attacker-controlled fragment.
  2. XSS executes: The _scroll_to_fragment method interpolates the unsanitized fragment into run_javascript, executing the injected script in the context of the target NiceGUI application — with no click required from the victim (Github Advisory).

Indicators of compromise

  • Network: Unexpected cross-origin iframe loads of the NiceGUI application from unknown third-party domains; outbound requests from the victim's browser to attacker-controlled endpoints (e.g., for cookie/token exfiltration) originating from the NiceGUI app's origin.
  • Logs: Server-side access logs showing requests to NiceGUI pages with URL fragments containing JavaScript-like strings (e.g., fragments with ');, alert(, document.cookie, or // patterns).
  • Browser/Client-Side: JavaScript errors or unexpected alert() dialogs in the NiceGUI application context; WebSocket messages containing unusual sub_pages_open event payloads with special characters in the path argument.
  • Application: Unexpected run_javascript calls logged server-side with fragment values containing quote characters or JavaScript syntax (Github Advisory).

Mitigation and workarounds

The primary remediation is to upgrade NiceGUI to version 3.5.0 or later, which patches the unsafe fragment interpolation in _scroll_to_fragment (NiceGUI v3.5.0). For organizations unable to upgrade immediately, two workarounds are available: (1) avoid using ui.sub_pages entirely, or (2) block iframe embedding by adding the following FastAPI middleware to set X-Frame-Options: DENY:

@app.middleware('http')
async def iframe_blocking_middleware(request, call_next):
    response = await call_next(request)
    response.headers['X-Frame-Options'] = 'DENY'
    return response

Upgrading to 3.5.0 is strongly preferred, as it also addresses two additional XSS vulnerabilities (GHSA-m7j5-rq9j-6jj9 and GHSA-7grm-h62g-5m97) disclosed simultaneously (Github Advisory).

Community reactions

The vulnerability was reported by researcher evnchn and reviewed by NiceGUI maintainer falkoschindler, with the advisory and patch released simultaneously on January 8, 2026. A technical blog post titled "Zero-click XSS in all NiceGUI apps which uses ui.sub_pages" was published at infinitsec.net shortly after disclosure. The advisory was noted on Bluesky and tracked by multiple vulnerability aggregators (VulDB, Vulners, CIRCL). Community reaction highlighted concern that ui.sub_pages is actively promoted as the modern SPA approach in NiceGUI, broadening the attack surface (Github Advisory).

Additional resources


SourceThis report was generated using AI

Related Python vulnerabilities:

CVE ID

Severity

Score

Technologies

Component name

CISA KEV exploit

Has fix

Published date

CVE-2026-84452HIGH8.6
  • Python logoPython
  • winml-cli
NoYesSep 02, 2026
CVE-2026-84381HIGH8.1
  • Python logoPython
  • httpcore2
NoYesSep 02, 2026
CVE-2026-84382HIGH7.5
  • Python logoPython
  • httpx2
NoYesSep 02, 2026
CVE-2026-84380MEDIUM5.6
  • Python logoPython
  • python-httpx2
NoYesSep 02, 2026
CVE-2026-53720MEDIUM5.1
  • Python logoPython
  • pymonocypher
NoYesSep 03, 2026

Free Vulnerability Assessment

Benchmark your Cloud Security Posture

Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.

Request assessment

Get a personalized demo

Ready to see Wiz in action?

"Best User Experience I have ever seen, provides full visibility to cloud workloads."
David EstlickCISO
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
Adam FletcherChief Security Officer
"We know that if Wiz identifies something as critical, it actually is."
Greg PoniatowskiHead of Threat and Vulnerability Management