Medium severity5.9NVD Advisory· Published Apr 8, 2026· Updated Apr 15, 2026
CVE-2026-39844
CVE-2026-39844
Description
NiceGUI is a Python-based UI framework. Prior to 3.10.0, Since PurePosixPath only recognizes forward slashes (/) as path separators, an attacker can bypass this sanitization on Windows by using backslashes (\) in the upload filename. Applications that construct file paths using file.name (a pattern demonstrated in NiceGUI's bundled examples) are vulnerable to arbitrary file write on Windows. This vulnerability is fixed in 3.10.0.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
niceguiPyPI | < 3.10.0 | 3.10.0 |
Affected products
1Patches
12 files changed · +20 −2
nicegui/elements/upload_files.py+7 −2 modified@@ -3,7 +3,7 @@ from collections.abc import AsyncIterator from dataclasses import dataclass from io import BytesIO -from pathlib import Path, PurePosixPath +from pathlib import Path import aiofiles import anyio @@ -149,8 +149,13 @@ async def create_file_upload(upload: UploadFile, *, chunk_size: int = 1024 * 102 if temp_file: await temp_file.close() - filename = PurePosixPath(upload.filename or '').name # strips all path components + filename = _sanitize_filename(upload.filename) if temp_file: return LargeFileUpload(filename, upload.content_type or '', Path(str(temp_file.name))) else: return SmallFileUpload(filename, upload.content_type or '', buffer.getvalue()) + + +def _sanitize_filename(name: str | None) -> str: + """Strip all path components from a filename to prevent path traversal.""" + return (name or '').rsplit('/')[-1].rsplit('\\')[-1]
tests/test_upload.py+13 −0 modified@@ -3,6 +3,7 @@ import pytest from nicegui import events, ui +from nicegui.elements.upload_files import _sanitize_filename from nicegui.testing import Screen test_path1 = Path('tests/test_upload.py').resolve() @@ -163,3 +164,15 @@ def page(): screen.wait(0.1) assert reads[0].file.size() == size assert await reads[0].file.text() == tmp_file.read_text() + + +@pytest.mark.parametrize('input_name,expected', [ + ('simple.txt', 'simple.txt'), + ('../../etc/passwd', 'passwd'), + ('..\\..\\windows\\evil.exe', 'evil.exe'), + ('../..\\..\\mixed/traversal\\payload.txt', 'payload.txt'), + ('', ''), + (None, ''), +]) +def test_upload_filename_sanitization(input_name: str | None, expected: str): + assert _sanitize_filename(input_name) == expected
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/zauberzeug/nicegui/commit/d38a702e3af2da5b0708f689be8d71413fc77056nvdPatchWEB
- github.com/advisories/GHSA-w8wv-vfpc-hw2wghsaADVISORY
- github.com/zauberzeug/nicegui/security/advisories/GHSA-w8wv-vfpc-hw2wnvdVendor AdvisoryWEB
- nvd.nist.gov/vuln/detail/CVE-2026-39844ghsaADVISORY
- github.com/zauberzeug/nicegui/releases/tag/v3.10.0nvdRelease NotesWEB
News mentions
0No linked articles in our index yet.