BREW-SCHEMATHESIS-CVE-20… (GHSA-V5GW-MW7F-84PX)

Vulnerability from osv_homebrew – Published: 2026-08-13 17:34 – Updated: 2026-08-23 21:37 – Source website
VLAI
Summary
Starlette has Path Traversal vulnerability in StaticFiles
Details

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": [
    {
      "ecosystem_specific": {
        "fix": "bump",
        "range_state": "fixed",
        "resource": "starlette",
        "resource_purl": "pkg:pypi/starlette@1.6.0",
        "upstream_fixed_in": "0.27.0"
      },
      "package": {
        "ecosystem": "Homebrew",
        "name": "schemathesis",
        "purl": "pkg:brew/schemathesis"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "4.24.3"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "database_specific": {
    "confidence": "high",
    "source": "matched",
    "strategy": "registry",
    "upstream_evidence": [
      {
        "ecosystem": "PyPI",
        "key": "pkg:pypi/starlette@1.6.0",
        "name": "starlette",
        "resource": "starlette",
        "strategy": "registry",
        "subject_version": "1.6.0"
      },
      {
        "ecosystem": "PyPI",
        "key": "pkg:pypi/starlette@1.6.0",
        "name": "starlette",
        "resource": "starlette",
        "strategy": "registry",
        "subject_version": "1.6.0"
      }
    ]
  },
  "details": "### Summary\nWhen using `StaticFiles`, if there\u0027s 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.\n\n### Details\nThe root cause of this issue is the usage of `os.path.commonprefix()`:\nhttps://github.com/encode/starlette/blob/4bab981d9e870f6cee1bd4cd59b87ddaf355b2dc/starlette/staticfiles.py#L172-L174\n\nAs 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.\n\nWhen 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.\n\nThe 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.\n\n### PoC\nIn order to reproduce the issue, you need to create the following structure:\n\n```\n\u251c\u2500\u2500 static\n\u2502   \u251c\u2500\u2500 index.html\n\u251c\u2500\u2500 static_disallow\n\u2502   \u251c\u2500\u2500 index.html\n\u2514\u2500\u2500 static1.txt\n```\n\nAnd run the `Starlette` app with:\n\n```py\nimport uvicorn\nfrom starlette.applications import Starlette\nfrom starlette.routing import Mount\nfrom starlette.staticfiles import StaticFiles\n\n\nroutes = [\n    Mount(\"/static\", app=StaticFiles(directory=\"static\", html=True), name=\"static\"),\n]\n\napp = Starlette(routes=routes)\n\n\nif __name__ == \"__main__\":\n    uvicorn.run(app, host=\"0.0.0.0\", port=8000)\n```\n\nAnd running the commands:\n\n```shell\ncurl --path-as-is \u0027localhost:8000/static/../static_disallow/\u0027\ncurl --path-as-is \u0027localhost:8000/static/../static1.txt\u0027\n```\nThe `static1.txt` and the directory `static_disallow` are exposed.\n\n### Impact\nConfidentiality is breached: An attacker may obtain files that should not be open to the public.\n\n### Credits\nSecurity 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.\n",
  "id": "BREW-schemathesis-CVE-2023-29159",
  "modified": "2026-08-23T21:37:11Z",
  "published": "2026-08-13T17:34:18Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/encode/starlette/security/advisories/GHSA-v5gw-mw7f-84px"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2023-29159"
    },
    {
      "type": "WEB",
      "url": "https://github.com/encode/starlette/commit/1797de464124b090f10cf570441e8292936d63e3"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/encode/starlette"
    },
    {
      "type": "WEB",
      "url": "https://github.com/encode/starlette/blob/4bab981d9e870f6cee1bd4cd59b87ddaf355b2dc/starlette/staticfiles.py#L172-L174"
    },
    {
      "type": "WEB",
      "url": "https://github.com/encode/starlette/releases/tag/0.27.0"
    },
    {
      "type": "WEB",
      "url": "https://github.com/pypa/advisory-database/tree/main/vulns/starlette/PYSEC-2023-83.yaml"
    },
    {
      "type": "WEB",
      "url": "https://jvn.jp/en/jp/JVN95981715"
    }
  ],
  "schema_version": "1.7.3",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Starlette has Path Traversal vulnerability in StaticFiles",
  "upstream": [
    "GHSA-v5gw-mw7f-84px",
    "CVE-2023-29159",
    "PYSEC-2023-83"
  ]
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.

Loading…

Loading…

Loading…

Related by attack behaviour

Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.


Loading…