CVE-2025-66645
NiceGUI <= 3.3.1 has a directory traversal vulnerability in add_media_files.
- CVSS 7.5
- CWE-22
- Input Validation and Sanitization
- Remote
NiceGUI is a Python-based UI framework. Versions 3.3.1 and below are vulnerable to directory traversal through the App.add_media_files() function, which allows a remote attacker to read arbitrary files on the server filesystem. This issue is fixed in version 3.4.0.
- CWE
- CWE-22
- CVSS base score
- 7.5
- Published
- 2025-12-09
- OWASP
- A01 Broken Access Control
- Orthogonal defect classification
- Checking
- Code defect classification
- Missing Check
- Category
- Input Validation and Sanitization
- Subcategory
- Path Traversal
- Accessibility scope
- Remote
- Impact
- Information Disclosure
- Affected component
- NiceGUI
- Fixed by upgrading
- Yes
Solution
Upgrade NiceGUI to version 3.4.0 or later.
Vulnerable code sample
import os
import uvicorn
from fastapi import FastAPI, HTTPException
from starlette.responses import FileResponse
from pathlib import Path
# NOTE: This code is a representation of the described vulnerability.
# The CVE number is fictional, and this code uses FastAPI (NiceGUI's foundation)
# to simulate the directory traversal flaw.
# --- Environment Setup for Demonstration ---
# Create a directory structure to demonstrate the traversal
APP_ROOT = Path(__file__).parent
MEDIA_DIR = APP_ROOT / "media"
SECRET_FILE = APP_ROOT / "secret.txt"
os.makedirs(MEDIA_DIR, exist_ok=True)
# Create a safe file inside the intended media directory
with open(MEDIA_DIR / "public.txt", "w") as f:
f.write("This is a public file.")
# Create a secret file outside the media directory that the attacker will try to access
with open(SECRET_FILE, "w") as f:
f.write("This is a sensitive server secret.")
# -----------------------------------------
app = FastAPI()
# This function simulates the behavior of the vulnerable `App.add_media_files()`
# by creating a route that serves files from a local directory.
def add_media_files_vulnerable(url_path: str, local_directory: Path):
@app.get(f"/{url_path}/{{filepath:path}}")
async def serve_file(filepath: str):
# VULNERABILITY: The user-provided 'filepath' is directly joined with the
# base directory path without any sanitization or security checks.
# An attacker can use '..' path components to traverse up the filesystem.
requested_path = os.path.join(local_directory, filepath)
# The application checks if the file exists but does not validate that
# the resolved path is still within the intended 'local_directory'.
if os.path.exists(requested_path) and os.path.isfile(requested_path):
return FileResponse(requested_path)
raise HTTPException(status_code=404, detail="File not found")
# A developer using the vulnerable version of the library would call this function.
add_media_files_vulnerable(url_path="media", local_directory=MEDIA_DIR)
if __name__ == "__main__":
# To test the vulnerability:
# 1. Install dependencies: pip install fastapi uvicorn
# 2. Run this script: python your_script_name.py
# 3. Access the legitimate file: http://127.0.0.1:8000/media/public.txt
# 4. Exploit the traversal to access the secret file: http://127.0.0.1:8000/media/../secret.txt
uvicorn.run(app, host="0.0.0.0", port=8000)Patched code sample
import pathlib
import os
class App:
"""
This is a simplified, conceptual representation of the NiceGUI App class
to demonstrate how a directory traversal vulnerability can be fixed.
"""
def __init__(self):
# In a real application, this would be the root directory for media files.
# .resolve() is used to get the canonical absolute path of the directory.
self.media_root = pathlib.Path('nicegui_media_root').resolve()
# For demonstration, ensure the base directory exists.
self.media_root.mkdir(exist_ok=True)
def add_media_files(self, url_path: str, local_folder_from_user: str) -> None:
"""
A conceptual, fixed version of the vulnerable add_media_files function.
This version prevents directory traversal by ensuring the resolved
file path is safely within the intended media root directory before
it is used.
"""
# Step 1: Resolve the path provided by the user against the media root.
# The `resolve()` method is critical as it canonicalizes the path,
# processing any '..' components and symbolic links.
# A vulnerable implementation might just use os.path.join() without resolving.
try:
requested_path = (self.media_root / local_folder_from_user).resolve()
except FileNotFoundError:
# If the base path doesn't exist, we can't serve it. This is a
# standard error, not a security flaw in itself.
# In a real app, this might log an error or simply do nothing.
return
# Step 2: THE FIX - Check if the resolved path is within the allowed media root.
# This is the core of the directory traversal prevention. It ensures
# that the resulting path has not "escaped" the intended parent directory.
# For Python 3.9+, one could use: `requested_path.is_relative_to(self.media_root)`
# The method below is compatible with older Python versions.
common_path = os.path.commonpath([self.media_root, requested_path])
if str(self.media_root) != common_path:
# If the longest common path is not the media root itself, it means the
# user-provided path has traversed outside the allowed directory.
raise PermissionError(
f"Directory traversal attempt blocked. The path '{local_folder_from_user}' "
"resolves outside the allowed media directory."
)
# Step 3: If the check passes, the application can safely proceed.
# The original logic to register the path for serving would go here.
# For example: self._register_media_route(url_path, requested_path)
passPayload
../../../../../../etc/passwd
Cite this entry
@misc{vaitp:cve202566645,
title = {{NiceGUI <= 3.3.1 has a directory traversal vulnerability in add_media_files.}},
author = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
year = {2025},
note = {VAITP Python Vulnerability Dataset, entry CVE-2025-66645},
howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2025-66645/}}
}
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 ::
