VAITP Dataset

← Back to the dataset

CVE-2025-66469

Reflected XSS in NiceGUI's CSS functions allows arbitrary JS execution.

  • CVSS 6.1
  • CWE-79
  • Input Validation and Sanitization
  • Remote

NiceGUI is a Python-based UI framework. Versions 3.3.1 and below are vulnerable to Reflected XSS through its ui.add_css, ui.add_scss, and ui.add_sass functions. The functions lack proper sanitization or encoding for the JavaScript context they generate. An attacker can break out of the intended <style> or <script> tags by injecting closing tags (e.g., </style> or </script>), allowing for the execution of arbitrary JavaScript. This issue is fixed in version 3.4.0.

CVSS base score
6.1
Published
2025-12-09
OWASP
A03 Injection
Orthogonal defect classification
Checking
Code defect classification
Missing Check
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 to version 3.4.0 or later.

Vulnerable code sample

from nicegui import ui, app

@ui.page('/')
def vulnerable_page():
    ui.label('Demonstration of Reflected XSS Vulnerability')
    ui.markdown('This page is vulnerable to XSS via the `style` query parameter.')

    # Retrieve potentially malicious input from the URL query string.
    payload = app.storage.request.query.get('style')

    if payload:
        # In the vulnerable version, the 'payload' is passed directly to ui.add_css
        # without any sanitization or encoding.
        # An attacker can close the intended <style> tag and inject a <script> tag.
        # Example Payload: </style><script>alert('XSS Vulnerability Executed')</script>
        ui.add_css(payload)
        
        ui.label('The following payload was injected:').classes('text-red-500')
        ui.code(payload).classes('w-full')
    else:
        ui.label('To test the vulnerability, add a `style` query parameter to the URL.')
        ui.link('Click here for a demonstration', '/?style=</style><script>alert("XSS")</script>')

# To test the vulnerability, run this script and navigate to a URL like:
# http://127.0.0.1:8080/?style=</style><script>alert("This is a demonstration of CVE-2025-66469")</script>
ui.run()

Patched code sample

def _validate_css_for_injection(content: str) -> None:
    """
    Prevents Reflected XSS by ensuring the provided content cannot break
    out of the intended <style> context. This represents the core of the fix
    for CVE-2025-66469.

    It works by disallowing substrings that an attacker would use to close
    the style tag and inject malicious script tags.
    """
    # Use lowercase for case-insensitive matching
    lower_content = content.lower()

    # Block the primary injection vector: a closing style tag
    if '</style>' in lower_content:
        raise ValueError('CSS content is not allowed to contain "</style>".')

    # As a defense-in-depth measure, also block closing script tags
    if '</script>' in lower_content:
        raise ValueError('CSS content is not allowed to contain "</script>".')


def add_css(content: str) -> None:
    """
    Represents the fixed version of ui.add_css.

    The fix is to call the validation function before any further processing.
    """
    _validate_css_for_injection(content)
    # ... original logic to add the validated CSS to the page would proceed here ...


def add_scss(content: str) -> None:
    """
    Represents the fixed version of ui.add_scss.

    The fix is to call the validation function before compilation and processing.
    """
    _validate_css_for_injection(content)
    # ... original logic to compile the validated SCSS and add it to the page would proceed here ...


def add_sass(content: str) -> None:
    """
    Represents the fixed version of ui.add_sass.

    The fix is to call the validation function before compilation and processing.
    """
    _validate_css_for_injection(content)
    # ... original logic to compile the validated SASS and add it to the page would proceed here ...

Payload

</style><script>alert('XSS')</script>

Cite this entry

@misc{vaitp:cve202566469,
  title        = {{Reflected XSS in NiceGUI's CSS functions allows arbitrary JS execution.}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2025},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2025-66469},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2025-66469/}}
}
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 ::