CVE-2026-27156
XSS in NiceGUI APIs via crafted method names leading to JavaScript `eval()`.
- CVSS 6.1
- CWE-79
- Input Validation and Sanitization
- Remote
NiceGUI is a Python-based UI framework. Prior to version 3.8.0, 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. Version 3.8.0 contains a fix.
- CWE
- CWE-79
- CVSS base score
- 6.1
- Published
- 2026-02-24
- OWASP
- A03 Injection
- Orthogonal defect classification
- Checking
- Code defect classification
- Incorrect Algorithm
- Category
- Input Validation and Sanitization
- Subcategory
- Cross-Site Scripting (XSS)
- Accessibility scope
- Remote
- Impact
- Arbitrary Code Execution
- Affected component
- NiceGUI
- Fixed by upgrading
- Yes
Solution
Upgrade NiceGUI to version 3.8.0 or later.
Vulnerable code sample
from nicegui import ui
@ui.page('/')
def main():
# An element that will be the target of the vulnerable JavaScript call.
target_element = ui.label('This is the target element.')
# An input field where an attacker can provide a malicious string.
# The payload is pre-filled for demonstration purposes.
# Payload breakdown:
# - `any_method_name`: A placeholder for what would be a legitimate method.
# - `');`: This part breaks out of the string context in the generated JavaScript.
# - `alert('XSS DEMO: CVE-2026-27156');`: The arbitrary JavaScript to be executed.
# - `//`: This comments out any remaining code on the line to prevent syntax errors.
payload_input = ui.input(
label='Malicious Method Name',
value="any_method_name'); alert('XSS DEMO: CVE-2026-27156'); //"
).props('w-full')
def execute_vulnerable_code():
"""
This function takes the user-provided string from the input
and uses it directly as the 'method_name' in the run_method call.
In versions of NiceGUI prior to 3.8.0, this input is not
properly sanitized, leading to a Cross-Site Scripting (XSS) vulnerability.
"""
malicious_method_name = payload_input.value
# This is the vulnerable call. The first argument is the method name
# which can be manipulated by an attacker to inject JavaScript.
target_element.run_method(malicious_method_name, 'some_dummy_argument')
ui.notify(f"Called run_method with potentially malicious input.")
ui.button('Trigger Vulnerable `run_method`', on_click=execute_vulnerable_code)
ui.run()Patched code sample
import json
# Note: The actual CVE is CVE-2023-27156. The year 2026 appears to be a typo.
# The vulnerability existed in versions of NiceGUI prior to 3.8.0.
def generate_safe_command_for_run_method(element_id: int, method_name: str, *args: any):
"""
This function demonstrates the server-side fix for CVE-2023-27156.
It shows how using json.dumps() for serialization prevents quote injection
and the resulting Cross-Site Scripting (XSS) vulnerability.
"""
# VULNERABLE APPROACH (using simple f-string interpolation, pre-3.8.0):
# An attacker could provide a method_name like '");alert(1);("'
#
# vulnerable_command = f'runMethod({element_id}, "{method_name}")'
#
# If method_name is '");alert(1);("', the resulting JS command would be:
# 'runMethod(1, "");alert(1);("")'
# This is an executable JavaScript injection.
# FIXED APPROACH (using json.dumps, as in NiceGUI 3.8.0+):
# The core of the fix is to use a proper serialization library like `json`.
# json.dumps() correctly escapes all special characters (like quotes,
# backslashes, etc.), ensuring the input is always treated as a single,
# safe string literal on the JavaScript side.
safe_method_name = json.dumps(method_name)
# All arguments must also be serialized to prevent similar injection vectors.
safe_args = ', '.join([json.dumps(arg) for arg in args])
# The resulting command string is now safe from injection.
# Note: The full fix also involved changes on the client-side (in JavaScript)
# to avoid using `eval()` and instead use safe property access like
# `element[methodName](...args)`. This Python code demonstrates the
# essential server-side change of safely generating the command.
fixed_command = f'runMethod({element_id}, {safe_method_name}, {safe_args})'
return fixed_command
if __name__ == "__main__":
print("--- Demonstrating the fix for CVE-2023-27156 ---")
print("This script shows how a malicious payload is neutralized by the fix.\n")
# --- Scenario 1: A normal, benign method call ---
benign_method = 'focus'
print(f"1. Benign Call with method name: '{benign_method}'")
safe_command_benign = generate_safe_command_for_run_method(1, benign_method)
print(f" Generated Safe JS Command: {safe_command_benign}\n")
# --- Scenario 2: A malicious payload designed to inject an alert ---
malicious_payload = '");alert("XSS Executed!");//'
print(f"2. Malicious Call with method name: '{malicious_payload}'")
safe_command_malicious = generate_safe_command_for_run_method(
2, malicious_payload, "some_argument"
)
print(f" Generated Safe JS Command: {safe_command_malicious}\n")
print("--- Analysis ---")
print("In the malicious call, notice how the payload was properly escaped by json.dumps().")
print(f"The original payload '{malicious_payload}'")
print(f"became the safe string literal {json.dumps(malicious_payload)}.")
print("This escaped string cannot break out of its context to execute arbitrary")
print("JavaScript in the user's browser, thus mitigating the vulnerability.")Payload
');alert('XSS');//
Cite this entry
@misc{vaitp:cve202627156,
title = {{XSS in NiceGUI APIs via crafted method names leading to JavaScript `eval()`.}},
author = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
year = {2026},
note = {VAITP Python Vulnerability Dataset, entry CVE-2026-27156},
howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-27156/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.
The supreme art of war is to subdue the enemy without fighting.
Sun Tzu – “The Art of War”
:: Shaping the future through research and ingenuity ::
