GHSA-78QV-3MPX-9CQQ
Vulnerability from github – Published: 2026-02-24 19:56 – Updated: 2026-02-24 19:56Summary
Several NiceGUI APIs that execute methods on client-side elements (Element.run_method(), AgGrid.run_grid_method(), EChart.run_chart_method(), and others) use an eval() fallback in the JavaScript-side runMethod() function. When user-controlled input is passed as the method name, an attacker can inject arbitrary JavaScript that executes in the victim's browser.
Additionally, Element.run_method() and Element.get_computed_prop() used string interpolation instead of json.dumps() for the method/property name, allowing quote injection to break out of the intended string context.
Attack Vector
An attacker crafts a malicious URL with a payload as a query parameter. If the application passes this parameter as a method name to any of the affected APIs, the payload is sent to the client via WebSocket and executed via eval().
Example: /?method=alert(document.cookie) combined with application code like:
element.run_method(user_provided_method_name)
Impact
- Cookie/token theft
- DOM manipulation (phishing, fake login forms)
- Actions performed as the victim user
Affected Methods
Element.run_method()Element.get_computed_prop()AgGrid.run_grid_method()AgGrid.run_row_method()EChart.run_chart_method()JsonEditor.run_editor_method()Xterm.run_terminal_method()Leaflet.run_map_method()Leaflet.run_layer_method()LeafletLayer.run_method()
Fix
- Use
json.dumps()for proper escaping of method/property names inrun_method()andget_computed_prop() - Remove the
eval()fallback fromrunMethod()innicegui.js— method names that are not found on the element now raise an error instead of being evaluated as arbitrary JavaScript
Migration
Code that previously passed JavaScript functions as method names needs to use ui.run_javascript() instead:
# Before:
row = await grid.run_grid_method('g => g.getDisplayedRowAtIndex(0).data')
# After:
row = await ui.run_javascript(f'return getElement({grid.id}).api.getDisplayedRowAtIndex(0).data')
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 3.7.1"
},
"package": {
"ecosystem": "PyPI",
"name": "nicegui"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "3.8.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-27156"
],
"database_specific": {
"cwe_ids": [
"CWE-79"
],
"github_reviewed": true,
"github_reviewed_at": "2026-02-24T19:56:18Z",
"nvd_published_at": "2026-02-24T18:29:33Z",
"severity": "HIGH"
},
"details": "### Summary\n\nSeveral NiceGUI APIs that execute methods on client-side elements (`Element.run_method()`, `AgGrid.run_grid_method()`, `EChart.run_chart_method()`, and others) use an `eval()` fallback in the JavaScript-side `runMethod()` function. When user-controlled input is passed as the method name, an attacker can inject arbitrary JavaScript that executes in the victim\u0027s browser.\n\nAdditionally, `Element.run_method()` and `Element.get_computed_prop()` used string interpolation instead of `json.dumps()` for the method/property name, allowing quote injection to break out of the intended string context.\n\n### Attack Vector\n\nAn attacker crafts a malicious URL with a payload as a query parameter. If the application passes this parameter as a method name to any of the affected APIs, the payload is sent to the client via WebSocket and executed via `eval()`.\n\n**Example:** `/?method=alert(document.cookie)` combined with application code like:\n```python\nelement.run_method(user_provided_method_name)\n```\n\n### Impact\n\n- Cookie/token theft\n- DOM manipulation (phishing, fake login forms)\n- Actions performed as the victim user\n\n### Affected Methods\n\n1. `Element.run_method()`\n2. `Element.get_computed_prop()`\n3. `AgGrid.run_grid_method()`\n4. `AgGrid.run_row_method()`\n5. `EChart.run_chart_method()`\n6. `JsonEditor.run_editor_method()`\n7. `Xterm.run_terminal_method()`\n8. `Leaflet.run_map_method()`\n9. `Leaflet.run_layer_method()`\n10. `LeafletLayer.run_method()`\n\n### Fix\n\n1. Use `json.dumps()` for proper escaping of method/property names in `run_method()` and `get_computed_prop()`\n2. Remove the `eval()` fallback from `runMethod()` in `nicegui.js` \u2014 method names that are not found on the element now raise an error instead of being evaluated as arbitrary JavaScript\n\n### Migration\n\nCode that previously passed JavaScript functions as method names needs to use `ui.run_javascript()` instead:\n\n```python\n# Before:\nrow = await grid.run_grid_method(\u0027g =\u003e g.getDisplayedRowAtIndex(0).data\u0027)\n\n# After:\nrow = await ui.run_javascript(f\u0027return getElement({grid.id}).api.getDisplayedRowAtIndex(0).data\u0027)\n```",
"id": "GHSA-78qv-3mpx-9cqq",
"modified": "2026-02-24T19:56:18Z",
"published": "2026-02-24T19:56:18Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/zauberzeug/nicegui/security/advisories/GHSA-78qv-3mpx-9cqq"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-27156"
},
{
"type": "WEB",
"url": "https://github.com/zauberzeug/nicegui/commit/1861f59cc374ca0dc9d970b157ef3774720f8dbf"
},
{
"type": "PACKAGE",
"url": "https://github.com/zauberzeug/nicegui"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "NiceGUI vulnerable to XSS via Code Injection during client-side element function execution"
}
Sightings
| Author | Source | Type | Date |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.