GHSA-c2m8-h5v5-343r: Pip/tornado vulnerability

Published Sep 30, 2026
·
Updated

Summary StaticFileHandler allows an unauthenticated attacker to read arbitrary files from the server's filesystem by requesting a path that resolves to a symbolic link placed inside the static root directory. Any application that serves user-uploadable content, or whose static directory is populated by a build/deploy pipeline that creates symlinks (e.g. npm link, webpack, Docker volume mounts, CDN sync tools), is affected. An attacker who can trigger the creation of a symlink pointing outside the static root—or exploit one that already exists—can retrieve sensitive files such as /etc/passwd, private keys, configuration files, or application secrets.

Details The vulnerability is in tornado.web.StaticFileHandler, specifically in the interaction between two methods in tornado/web.py: - getabsolutepath uses os.path.abspath() to resolve the requested path: - validateabsolutepath uses the same os.path.abspath() on the root, then performs a string prefix check:

os.path.abspath() normalises . and .. segments but does not resolve symbolic links. As a result, a path like /var/www/static/link passes the startswith("/var/www/static/") check regardless of where link actually points.

Immediately after, os.path.exists() and os.path.isfile() do follow symlinks, so the file they ultimately open is the symlink's target. The fix would be to replace os.path.abspath() with os.path.realpath() in both methods, so the resolved real path of the symlink target is validated against the root, not just its string representation inside the static directory.

PoC Complete instructions, including specific configuration details, to reproduce the vulnerability. Prerequisites: Python 3.x, Tornado installed. 1. Create the environment mkdir -p /tmp/static echo "DBPASSWORD=s3cr3t" > /tmp/secret.conf ln -s /tmp/secret.conf /tmp/static/config.conf 2. Minimal vulnerable server (server.py): import tornado.web, tornado.ioloop

app = tornado.web.Application([ (r"/static/(.)", tornado.web.StaticFileHandler, {"path": "/tmp/static"}), ]) app.listen(8888) tornado.ioloop.IOLoop.current().start() 3. Exploit: curl http://localhost:8888/static/config.conf

Impact Any application using StaticFileHandler is potentially affected if: - the static directory contains symlinks pointing outside it (common with build tooling), or - the application allows file uploads into the static directory without stripping symlinks.

An unauthenticated remote attacker can read any file readable by the process user: application secrets, private TLS keys, database credentials, /etc/shadow, SSH keys, or source code (depending on the process's filesystem permissions).

Affected Software

1 affected componentFixes available
pip/tornado<=6.5.8
6.5.9

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade pip/tornado to a version that resolves this vulnerability.

    Fixed in 6.5.9
  2. Configuration

    Replace os.path.abspath() with os.path.realpath() in both get_absolute_path and validate_absolute_path so symlink targets are resolved and validated against the static root.

    tornado.web.StaticFileHandler path resolution in get_absolute_path and validate_absolute_path = os.path.realpath()

Event History

Sep 30, 2026
Advisory Published
via GitHub·11:48 PM
Data Sourced
via GitHub·11:48 PM
DescriptionWeaknessAffected Software

Frequently Asked Questions

1

Which deployments are most likely to be exposed?

Applications that serve user-uploadable content are affected if users can cause symlinks to be placed in the static root. Deployments are also exposed when build or deployment processes create symlinks there, including through npm link, webpack, Docker volume mounts, or CDN synchronization tools.

2

What does an attacker need to exploit this issue?

The attacker needs a symlink inside the static root that points outside that directory. They may create such a symlink through an available workflow, or request a symlink that already exists; no authentication is required to read files through it.

3

How can I assess whether an application may already be vulnerable?

Inspect the directory configured as the static root and the processes that populate it for symbolic links, especially links whose targets are outside the static root. Also review whether upload, build, deployment, or synchronization workflows can introduce symlinks into that directory.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203