Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain
-
AccessIdentify internet-facing Tornado StaticFileHandler
-
DeliveryLocate or plant symlink escaping static root
-
ExploitSend unauthenticated GET for symlink path
-
ExecutionPrefix check passes, open() follows link
-
ImpactRead config/private keys/secrets
Vulnerability Assessment
| Weakness |
CWE
OWASP Top 10:2025
A01:2025 - Broken Access Control
ASVS 5.0
V5 - File Handling Symlink resolution safety
|
| Exploitation Conditions | Requires an application using tornado.web.StaticFileHandler to serve static files AND a symbolic link that resolves outside the configured static root existing inside that root. Per the advisory, this condition arises in apps serving user-uploadable content, or where the static directory is populated by build/deploy pipelines that create symlinks (npm link, webpack, Docker volume mounts, CDN sync tools); an attacker who can trigger symlink creation or exploit a pre-existing one succeeds. No authentication or user interaction is needed (PR:N/UI:N), and exploitation is purely a GET request. The limiting factor (CVSS 4.0 AT:P) is the symlink precondition: a static tree that never contains out-of-root symlinks is not exploitable. The read is bounded to files accessible to the Tornado process user. Fixed in 6.5.9, which uses os.path.realpath() and adds an opt-in allowed_symlink_directory. |
| Impact | This is a genuine, high-value issue for exposed Tornado deployments but its real-world exploitability hinges on a precondition rather than being a turnkey remote read. The vendor CVSS 4.0 vector (8.2, AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N) correctly captures the key nuance: it is network-reachable and unauthenticated (PR:N/UI:N), with high confidentiality impact (VC:H) and no integrity or availability impact - but it carries AT:P (Attack Requirements: Present), reflecting that a symlink escaping the static root must already exist inside it or be plantable by the attacker. A public PoC exists in the GHSA advisory (full reproduction steps), so weaponization effort is trivial where the precondition holds - but POC availability is NOT active exploitation. There is no EPSS score and no CISA KEV listing in the provided data, so there is no evidence of in-the-wild exploitation. The honest read: this is a real priority for any Tornado app that serves user-uploadable content or whose static dir is populated by build/deploy tooling that creates symlinks (npm link, webpack, Docker volume mounts, CDN sync), and a lower priority for static trees that never contain symlinks. Note a scoring nuance to verify: in CVSS 3.1 terms the symlink precondition is better expressed as AC:H, which would lower the 3.1-equivalent score versus the 8.2 4.0 figure. |
| Exploit ScenarioDerived | An attacker identifies a Tornado application serving files via StaticFileHandler and locates (or, via an upload/build pipeline, plants) a symbolic link inside the static root that points outside it - e.g. to /etc/passwd, a private key, or an app config file. They then issue an unauthenticated GET for that path; os.path.abspath() plus the startswith() prefix check passes because symlinks aren't resolved, while the subsequent os.path.isfile/open follow the link and return the target's contents. A public PoC with complete reproduction steps is published in the GHSA advisory. |
Get an e-mail when this CVE is exploited, patched or re-scored. Free account.
Alert meAnalysisAIv1 – Oct 01, 2026
Unauthenticated local file disclosure in Tornado before 6.5.9 lets remote attackers read files outside a configured static root by requesting a symbolic link that lives inside that root but resolves elsewhere, exposing configuration files, private keys, and application secrets readable by the Tornado process user. Exploitation is a single GET request requiring no authentication and no user interaction (assessed CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N), but it depends on a precondition rather than being turnkey: an out-of-root symlink must already exist inside the static directory, a situation the upstream advisory says arises in applications serving user-uploadable content or where build/deploy pipelines (npm link, webpack, Docker volume mounts, CDN sync tools) create symlinks. The issue is fixed in 6.5.9, public reproduction steps are published in the upstream GitHub Security Advisory, and there is no CISA KEV listing.
RemediationAI
Upgrade to Tornado 6.5.9 or later - vendor-released patch: 6.5.9 (pip install -U "tornado>=6.5.9"), delivered by upstream PR https://github.com/tornadoweb/tornado/pull/3719 and commit https://github.com/tornadoweb/tornado/commit/437ab5f76565403b3403438d2e555d11f8128d32, which switches get_absolute_path()/validate_absolute_path() to os.path.realpath() and adds the opt-in allowed_symlink_directory parameter; see the advisory at https://github.com/tornadoweb/tornado/security/advisories/GHSA-c2m8-h5v5-343r. If immediate upgrade is not possible, the most direct compensating control is to guarantee the static root contains no symlinks that resolve outside it: audit the tree with find <root> -type l -exec realpath {} \; and remove or replace any escaping links, and disable symlink following in whatever populates the directory (npm install --no-bin-links, avoid npm link/webpack symlink output, copy rather than bind-mount Docker volumes, and configure CDN/sync tooling to dereference links) - the trade-off is that legitimate symlink-based deploy layouts must be reworked and any in-root symlink convenience is lost. Do not serve user-uploaded content through StaticFileHandler on a shared filesystem; keep uploads in a dedicated path that is not symlink-writable by unprivileged users, or front static content with a reverse proxy (e.g. nginx) configured with symlink containment, accepting the added operational complexity of an extra component. Running the Tornado process as a low-privilege account with no access to /etc/passwd, private keys, or secret stores reduces the blast radius but does not eliminate the read, so it is a hardening measure rather than a fix. Removing any code path by which an attacker can cause symlink creation (upload, archive extraction, template or plugin writes into the static tree) closes the precondition entirely at the cost of restricting those features.
Affected VersionsENISA
Affected Packages
Source: OSV (Open Source Vulnerabilities)
Affects your stack
Affects 1 package in pypi
Checking this CVE against your own stacks and servers is part of the Basic plan and up.
Technical ContextAI · show details
The flaw sits in tornado.web.StaticFileHandler and is classified as CWE-59 (Improper Link Resolution Before File Access, i.e. link following). Two cooperating methods are involved: get_absolute_path() normalises the requested path with os.path.abspath(), and validate_absolute_path() applies the same os.path.abspath() to the configured root and then performs a string prefix check (startswith('/var/www/static/')). os.path.abspath() collapses '.' and '..' segments but deliberately does not resolve symbolic links, so a path such as /var/www/static/link passes the prefix test no matter where 'link' actually points. The subsequent os.path.exists() and os.path.isfile() calls, however, do follow symlinks, so the file ultimately opened is the symlink's target - which may be anywhere on the filesystem reachable by the process user. The upstream fix replaces os.path.abspath() with os.path.realpath() in both methods so the resolved real path of the target is validated against the root, and it introduces an opt-in allowed_symlink_directory parameter for deployments that intentionally serve out-of-root symlinks. The regression tests added upstream confirm that escaping file and directory symlinks now return 403, that in-root symlinks still serve, and that a missing versus existing out-of-bounds target both return 403 so the handler cannot be used as a filesystem existence oracle. The affected component is the pip-distributed tornado package (CPE cpe:2.3:a:tornadoweb:tornado, EUVD-2026-90657), present anywhere an application mounts StaticFileHandler over a directory that may contain symlinks; the CVSS:4.0 vector's AT:P (Attack Requirements: Present) captures that this is only exploitable when the symlink precondition holds.
Know when Tornado gets its next vulnerability
- Watch products and get an email when something new is published
- Check this CVE against your own stack and servers
- Exploit and PoC references, threat intelligence from 22 sources
No credit card · 7-day full trial
Severity by source
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N
Network, unauthenticated, no UI; AC:H because exploitation depends on an out-of-root symlink existing inside the static dir (not attacker-guaranteed); confidentiality-only arbitrary file read, so I/A:N.
Primary rating from Vendor (VulnCheck).
CVSS VectorVendor: VulnCheck
DescriptionCVE.org
Tornado before 6.5.9 contains a path traversal vulnerability in StaticFileHandler that follows symbolic links inside the static root without confirming the resolved target stays within it. When a symlink pointing outside the static directory exists inside it, unauthenticated attackers can request it to read files such as configuration files, private keys, and application secrets accessible to the process user.
Articles & Coverage 1
Technical POC Analysis
CWE-59 (Improper Link Resolution Before File Access, "Link Following").
Full technical POC analysis - root cause, step-by-step exploitation and patch breakdown - is part of the Pro and Business plans.
Executive ViewAI
Tornado, the Python web framework used across a wide range of internal and customer-facing services, can be tricked into serving files from outside its designated static content directory, potentially exposing configuration files, private keys and application secrets to anyone who can reach the affected endpoint. Exploitation requires no credentials and no user interaction, but only succeeds where a symbolic link escaping the static root already exists - most commonly in services that accept user uploads or that rely on build and deployment tooling such as npm link, webpack, Docker volume mounts or CDN sync. Leadership should care because the data at risk is the credential material that protects other systems, making this a plausible stepping stone to broader compromise of the environments running Tornado.
Apply vendor patch.
Threat Intelligence Overview
How this decision was reached
The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.
What every action level means
SSVC AssessmentENISA
Priority Score
Attack Technique
Path traversal exploits occur when applications use user-controlled input to construct file system paths without proper validation.
An issue in Docmosis Tornado v.2.9.7 and before allows a remote attacker to execute arbitrary code via a crafted script
An issue was discovered in Docmosis Tornado prior to version 2.9.5. Rated high severity (CVSS 8.8), this vulnerability i
py3-tornado in Alpine Linux received a security fix packaged as version 6.5.4-r0, addressing an unspecified vulnerabilit
Docmosis Tornado <= 2.9.4 is vulnerable to Directory Traversal leading to the disclosure of arbitrary content on the fil
An issue was discovered in Docmosis Tornado prior to version 2.9.5. Rated high severity (CVSS 7.5), this vulnerability i
Denial of service in the Tornado web framework's CurlAsyncHTTPClient (all releases before 6.5.9) lets an unauthenticated
In versions of Tornado prior to 6.5.5, the only limit on the number of parts in `multipart/form-data` is the `max_body_s
Memory amplification denial of service in the Tornado Python web framework before 6.5.8 lets unauthenticated remote atta
Credential leakage in Tornado's CurlAsyncHTTPClient (all releases through 6.5.6) lets sensitive per-request state — clie
Denial-of-service in Tornado prior to 6.5.8 allows unauthenticated remote attackers to stall the entire server by sendin
Tornado Python web framework on Alpine Linux received a security fix in package version 6.5.4-r0, addressing an uncharac
Tornado is a Python web framework and asynchronous networking library. Rated high severity (CVSS 7.5), this vulnerabilit
EUVD-2026-90657
GHSA-4cjq-6jh9-w2f5
NVD
CVE.org
EPSS
Vulnrichment
Exploit-DB