NIST deprecates RSA-2048 from 2030. Find every one of them before attackers do.
🐍
🐍 PyPI
Not in CISA KEV
HIGH severity

CVE-2023-29159 — starlette

HIGHFix: encode/starlette@1797de4

CVE-2023-29159 is a high-severity (CVSS 7.5) Path Traversal vulnerability in starlette. 1 public exploit or proof-of-concept reference is indexed, so weaponization risk is real. A fix is available for starlette — see the affected versions and patch details below.

Starlette has Path Traversal vulnerability in StaticFiles

Also known asGHSA-v5gw-mw7f-84pxPYSEC-2023-83
Published
Updated
Affected
1 pkg
Patched
1 / 1
Exploits
1 known
Exploitation data as of Nov 7, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
  • CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.

Exploitation and automatability from CISA’s SSVC triage for CVE-2023-29159.

EPSS Exploitation Probability

via FIRST.org ↗
2.6%probability of exploitation in next 30 days
Lower Risk+0.54%
Lower risk than most CVEs85th percentile — riskier than 85% of all scored CVEsHighest risk
1.01%1.71%2.40%3.09%1.5%2.6%May 26Sep 26Nov 26

Probability of exploitation in the next 30 days, from FIRST.org EPSS.

How urgent is this, really

Where this sits among everything scored

Real-World Exposure

1 pkg affected
🐍starlette

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects PyPI packages — download data is not available via public APIs for these ecosystems.

Description

Summary

When using StaticFiles, if there's a file or directory that starts with the same name as the StaticFiles directory, that file or directory is also exposed via StaticFiles which is a path traversal vulnerability.

Details

The root cause of this issue is the usage of os.path.commonprefix(): https://github.com/encode/starlette/blob/4bab981d9e870f6cee1bd4cd59b87ddaf355b2dc/starlette/staticfiles.py#L172-L174

As stated in the Python documentation (https://docs.python.org/3/library/os.path.html#os.path.commonprefix) this function returns the longest prefix common to paths.

When passing a path like /static/../static1.txt, os.path.commonprefix([full_path, directory]) returns ./static which is the common part of ./static1.txt and ./static, It refers to /static/../static1.txt because it is considered in the staticfiles directory. As a result, it becomes possible to view files that should not be open to the public.

The solution is to use os.path.commonpath as the Python documentation explains that os.path.commonprefix works a character at a time, it does not treat the arguments as paths.

PoC

In order to reproduce the issue, you need to create the following structure:

├── static
│   ├── index.html
├── static_disallow
│   ├── index.html
└── static1.txt

And run the Starlette app with:

import uvicorn
from starlette.applications import Starlette
from starlette.routing import Mount
from starlette.staticfiles import StaticFiles


routes = [
    Mount("/static", app=StaticFiles(directory="static", html=True), name="static"),
]

app = Starlette(routes=routes)


if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)

And running the commands:

curl --path-as-is 'localhost:8000/static/../static_disallow/'
curl --path-as-is 'localhost:8000/static/../static1.txt'

The static1.txt and the directory static_disallow are exposed.

Impact

Confidentiality is breached: An attacker may obtain files that should not be open to the public.

Credits

Security researcher Masashi Yamane of LAC Co., Ltd reported this vulnerability to JPCERT/CC Vulnerability Coordination Group and they contacted us to coordinate a patch for the security issue.

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐍PyPIstarlette≥ 0.13.5&&< 0.27.00.27.0pip install --upgrade 'starlette==0.27.0'

Affected Products

1 product · 1 configurations
Application
starletteencode
≥ 0.13.5 && < 0.27.0
range
Exploits & PoCs
1

Research use only. For defensive security, authorized penetration testing, and academic research only. Never execute exploit code against systems without explicit written authorization.

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for starlette, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update starlette to 0.27.0 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2023-29159 is resolved across your whole dependency graph.

  3. Workarounds

    Resolve every user-supplied path to its canonical form and reject anything that escapes the intended directory, and run the component under an account that has no read or write access outside the directory it legitimately serves.

Frequently Asked Questions

### Summary When using `StaticFiles`, if there's a file or directory that starts with the same name as the `StaticFiles` directory, that file or directory is also exposed via `StaticFiles` which is a path traversal vulnerability. ### Details The root cause of this issue is the usage of `os.path.commonprefix()`: https://github.com/encode/starlette/blob/4bab981d9e870f6cee1bd4cd59b87ddaf355b2dc/starlette/staticfiles.py#L172-L174 As stated in the Python documentation (https://docs.python.org/3/library/os.path.html#os.path.commonprefix) this function returns the longest prefix common to paths. W
O3 Security · Impact-Aware SCA

Is CVE-2023-29159 in your dependencies?

Find it across PyPI, including transitive dependencies.

CVE-2023-29159: starlette Path Traversal — Fixed in 0.27.0