{"schema_version":"1.9.0","id":"GHSA-mhpg-c27v-6mxr","published":"2026-01-08T20:16:41Z","modified":"2026-07-07T17:57:37.927767983Z","aliases":["CVE-2026-21873","PYSEC-2026-1702"],"summary":"NiceGUI apps which use `ui.sub_pages` vulnerable to zero-click XSS","details":"### Summary\n\nAn unsafe implementation in the `pushstate` event listener used by `ui.sub_pages` allows an attacker to manipulate the fragment identifier of the URL, which _they can do despite being cross-site, using an iframe_. \n\n### Details\n\nThe problem is traced as follows:\n\n1. On `pushstate`, `handleStateEvent` is executed. \n\nhttps://github.com/zauberzeug/nicegui/blob/59fa9424c470f1b12c5d368985fa36e21fda706b/nicegui/elements/sub_pages.js#L38-L39\n\n2. `handleStateEvent` emits `sub_pages_open` event. \n\nhttps://github.com/zauberzeug/nicegui/blob/59fa9424c470f1b12c5d368985fa36e21fda706b/nicegui/elements/sub_pages.js#L22-L25 \n\n3. `SubPagesRouter` (used by `ui.sub_pages`), lisnening on `sub_pages_open`, `_handle_open` runs. \n\nhttps://github.com/zauberzeug/nicegui/blob/59fa9424c470f1b12c5d368985fa36e21fda706b/nicegui/sub_pages_router.py#L18-L22\n\n4. `_handle_open` finds any `SubPages` and runs `_show()` on them\n\nhttps://github.com/zauberzeug/nicegui/blob/59fa9424c470f1b12c5d368985fa36e21fda706b/nicegui/sub_pages_router.py#L63-L71\n\n5. If the if-logic is followed or debug prints are added, it can be found that it calls `self._handle_scrolling(match, behavior='smooth')` directly\n\nhttps://github.com/zauberzeug/nicegui/blob/59fa9424c470f1b12c5d368985fa36e21fda706b/nicegui/elements/sub_pages.py#L76-L100\n\n6. **CULPRIT** `_handle_scrolling` runs `_scroll_to_fragment` as there is a fragment, which runs vulnerable JS if the `fragment` (attacker-controlled) escapes out of the quotes. \n\nhttps://github.com/zauberzeug/nicegui/blob/59fa9424c470f1b12c5d368985fa36e21fda706b/nicegui/elements/sub_pages.py#L206-L217\n\n### PoC\n\nJust visiting this page (no click required), consistently triggers XSS in https://nicegui.io domain. \n\n```html\n\n
\n \n \n \n\n```\n\n