Cloudanix VulnDB

CVE-2026-21860

Medium · 5.3

CVSS

5.3

EPSS

0.5%

Published

Jan 8, 2026

CISA due date

—

Cloudanix analysis

Schedule a fix SSVC: Track

Some web applications may crash or slow down when given specially named Windows files, so the affected software should be updated.

Exploitation
Remote Unauthenticated
Attacker needs
None
Complexity
Moderate
Impact
Denial Of Service
Component
Library
Class
Path Traversal
Remediation
Upgrade
Effort
Medium
Patch risk
Low

What it actually does

Werkzeug versions prior to 3.1.5 insufficiently reject Windows reserved device names when safe_join is used to combine a trusted base directory with attacker-controlled path segments. On Windows, names such as CON, AUX, NUL, PRN, COM1, and LPT1 are treated as special devices even when they include file extensions or trailing spaces, such as CON.txt or AUX . If an application relies on safe_join to validate user-supplied download, upload, static-file, or template-related paths, an attacker may be able to cause the application to access a Windows device name rather than a normal file. The documented impact is primarily limited availability impact, such as request hangs, exceptions, or service degradation, rather than code execution or data theft.

Why it matters to the business

Applications using vulnerable Werkzeug versions on Windows may be exposed to unauthenticated remote requests that trigger errors or degraded availability in file-handling endpoints. The risk is lower than vulnerabilities that enable data theft or system takeover: the CVSS score is 5.3, EPSS is low at 0.00441, there is no CISA KEV listing, and no known exploit maturity is reported. However, the issue has been public for 214 days, so affected internet-facing services should still be updated as part of normal patch hygiene, especially where Werkzeug is used broadly through Flask or other Python web stacks.

How an attack unfolds

An attacker first identifies a web endpoint that accepts a path, filename, attachment name, static file reference, or similar parameter and that ultimately calls Werkzeug safe_join to restrict access to an intended directory. If the application is running on Windows and uses a vulnerable Werkzeug release, the attacker submits a reserved Windows device name with an allowed-looking suffix, such as CON.txt, AUX.log, NUL.dat, COM1.txt, or LPT1.txt, or with trailing spaces or dots. Because the vulnerable safe_join logic does not correctly reject these Windows device aliases in all forms, the application may attempt to open the device name as though it were a file. Depending on the surrounding application behavior, this can result in blocked reads, exceptions, repeated 500 responses, worker exhaustion, or other availability degradation. Successful exploitation requires an exposed application code path that passes attacker-controlled path segments into safe_join and executes on Windows; Linux deployments are generally not affected by the Windows device-name behavior, though distribution packages should still be updated where listed by vendors.

How to fix it

Upgrade Werkzeug to version 3.1.5 or later. If consuming Werkzeug from source, use a version containing commit e3d06f4b1f7ff40a63eba78f81d9cda18f805d6d or later. For distribution-managed packages, apply the vendor-fixed package listed for the platform, including Debian 12 and Debian 13 fixed package version 5.17.3-1 where applicable in the provided advisory data. After upgrading, rebuild and redeploy containers, virtual environments, serverless packages, and application images so the patched dependency is actually in use. As defense in depth, reject Windows reserved device names at application boundaries for any user-controlled filename or path segment, including case-insensitive matches with extensions, trailing spaces, trailing dots, or URL-encoded equivalents. Avoid passing raw user input to file-serving routines, normalize and validate paths before use, and maintain allowlists of permitted filenames where practical.

How to confirm the fix worked

Confirm the installed Werkzeug version is 3.1.5 or later using dependency inventory, package lockfiles, SBOMs, container image scans, or runtime checks such as Python package metadata. For source-based deployments, confirm the code includes commit e3d06f4b1f7ff40a63eba78f81d9cda18f805d6d or equivalent fix. For Debian-managed environments, confirm the installed vendor package is at or above the fixed version identified by the vendor advisory. Validate that all deployed artifacts were rebuilt after the upgrade, not only that source manifests were changed. Where safe to test, exercise file-handling endpoints with reserved device names such as CON.txt, AUX.log, NUL.dat, COM1.txt, and LPT1.txt and confirm the application rejects them with a controlled 400/404-style response rather than hanging, throwing unhandled exceptions, or attempting file access. Regression tests should include mixed case, URL encoding, extensions, trailing spaces, and trailing dots.

Typical attack path

  1. Discover a Python/Werkzeug or Flask-based web application with endpoints that accept user-controlled file or path values.
  2. Send benign path probes to identify download, static-file, upload-preview, attachment, or file-serving behavior.
  3. Submit Windows reserved device names using extensions, trailing spaces, trailing dots, URL encoding, or mixed case, such as CON.txt, AUX.log, or NUL%20.
  4. Trigger the vulnerable safe_join validation path so the application treats the device alias as a safe child path.
  5. Cause the application to open or process the Windows device name, leading to errors, request hangs, or degraded service availability.
  6. Repeat requests or target high-cost endpoints to amplify operational impact.

How to detect it

To assess prior exploitation or probing, review web access logs, reverse proxy logs, WAF logs, application logs, and APM traces for requests containing Windows reserved device names in URL paths, query parameters, form fields, or JSON fields used as filenames. Focus on file-serving and path-handling endpoints such as download, upload, attachment, static, media, export, import, preview, or template routes. Search case-insensitively for reserved names followed by a dot, trailing space, trailing dot, URL-encoded dot, or URL-encoded space. Correlate hits with HTTP 500 responses, 400/404 rejections, long request durations, upstream timeouts, worker recycling, application exceptions, or Windows file I/O errors. Relevant log artifacts may include messages about invalid filenames, failed file opens, request timeouts, BrokenPipeError, OSError, PermissionError, or application-specific error handlers around file reads. Because this vulnerability does not inherently provide code execution or a stable malware artifact, detection should focus on exploit attempts and availability side effects rather than host compromise indicators.

  • CON.txt
  • CON.log
  • CON%2Etxt
  • CON%20
  • CON.
  • AUX.txt
  • AUX.log
  • AUX%2Etxt
  • AUX%20
  • AUX.
  • NUL.txt
  • NUL.log
  • NUL%2Etxt
  • NUL%20
  • NUL.
  • PRN.txt
  • PRN.log
  • PRN%2Etxt
  • PRN%20
  • PRN.
  • COM1.txt
  • COM1%2Etxt
  • COM1%20
  • COM2.txt
  • COM3.txt
  • COM4.txt
  • COM5.txt
  • COM6.txt
  • COM7.txt
  • COM8.txt
  • COM9.txt
  • LPT1.txt
  • LPT1%2Etxt
  • LPT1%20
  • LPT2.txt
  • LPT3.txt
  • LPT4.txt
  • LPT5.txt
  • LPT6.txt
  • LPT7.txt
  • LPT8.txt
  • LPT9.txt
  • CONIN$
  • CONOUT$
  • (?i)(^|[/?&=\\])(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|%2e|%20|\+|\s)

What your security team should do

  • Prioritize patching internet-facing Python web applications that run on Windows and use Werkzeug or frameworks that depend on it.
  • Upgrade Werkzeug to 3.1.5 or later and rebuild all containers, virtual environments, and deployment artifacts that bundle the dependency.
  • Inventory applications that call safe_join or expose user-controlled file/path parameters, especially download, upload, static-file, and attachment endpoints.
  • Add application-level validation that blocks Windows reserved device names case-insensitively, including names with extensions, trailing spaces, trailing dots, and URL encoding.
  • Review web and application logs for historical probes using reserved device names and correlate with 500 errors, request timeouts, worker restarts, or availability incidents.
  • Treat this as normal-priority patching where Linux-only deployments are confirmed and no vulnerable Windows execution path exists, but still remediate through dependency updates to avoid future exposure.

The record

Werkzeug is a comprehensive WSGI web application library. Prior to version 3.1.5, Werkzeug's safe_join function allows path segments with Windows device names that have file extensions or trailing spaces. On Windows, there are special device names such as CON, AUX, etc that are implicitly present and readable in every directory. Windows still accepts them with any file extension, such as CON.txt, or trailing spaces such as CON. This issue has been patched in version 3.1.5.

Affected packages

Ecosystem Package Introduced Fixed
PyPI werkzeug 0 3.1.5
Chainguard airflow-2 0 0
Chainguard airflow-3 0 0
Chainguard airflow-core-2 0 0
Chainguard mlflow 0 3.8.1-r1
Chainguard mlflow-iamguarded-compat 0 3.8.1-r1
Chainguard open-webui 0 0.7.2-r0
Chainguard py3.10-ambassador 0 0
Chainguard py3.11-ambassador 0 0
Chainguard py3.11-azure-functions-worker 0 4.42.0-r0
Chainguard py3.12-ambassador 0 0
Chainguard py3.12-azure-functions-worker 0 4.42.0-r0
Chainguard py3.13-ambassador 0 0
Chainguard py3.13-azure-functions-worker 0 4.42.0-r0
Chainguard superset-4.1 0 4.1.4-r7
Chainguard superset-5.0 0 5.0.0-r12
Chainguard tensorflow-cpu-jupyter 0 2.20.0-r8
Wolfi airflow-3 0 0
Wolfi mlflow 0 3.8.1-r1
Wolfi mlflow-iamguarded-compat 0 3.8.1-r1
Wolfi open-webui 0 0.7.2-r0
Wolfi py3.10-ambassador 0 0
Wolfi py3.11-ambassador 0 0
Wolfi py3.12-ambassador 0 0
Wolfi py3.13-ambassador 0 0
Wolfi superset-4.1 0 4.1.4-r7
Wolfi superset-5.0 0 5.0.0-r12
Wolfi tensorflow-cpu-jupyter 0 2.20.0-r8

Related vulnerabilities