{"answers":{"affected":"2 open source packages ship an affected version, including setuptools.","exploited":"There is no known exploitation of GHSA-xmj3-9gf7-h52w in the wild and no public exploit code.","fix":"Upgrade setuptools to 84.1.0 or later.","what":"GHSA-xmj3-9gf7-h52w is a vulnerability in setuptools, published on 23 Oct 2026."},"fix_prompt":"Check this codebase for GHSA-xmj3-9gf7-h52w and fix it if it is affected.\n\nWhat it is: GHSA-xmj3-9gf7-h52w is a vulnerability in setuptools, published on 23 Oct 2026. \nExploitation: There is no known exploitation of GHSA-xmj3-9gf7-h52w in the wild and no public exploit code.\n\nAffected packages and fixed versions:\n- setuptools (PyPI): affected from 38.2.2; fixed in 84.1.0\n- setuptools (PyPI): affected from 38.2.2; fixed in 84.1.0\n\nTask:\n1. Search the dependency manifests and lockfiles (for example package.json, package-lock.json, requirements.txt, poetry.lock, uv.lock, pom.xml, build.gradle, go.mod, Cargo.lock, Gemfile.lock) and any Dockerfiles for the affected packages, including transitive dependencies.\n2. If an affected version is in use, upgrade it to the fixed version for its release line with the project's package manager, so the lockfile is regenerated. Prefer the smallest upgrade that fixes it.\n3. If there is no fix, or the upgrade would break the build, do not guess: explain the risk and the safest workaround instead.\n4. Run the tests and summarise what changed and why.\n5. If nothing in the project is affected, say so and change nothing.\n\nReference: https://insights.sbomify.com/GHSA-xmj3-9gf7-h52w/ (Markdown: https://insights.sbomify.com/GHSA-xmj3-9gf7-h52w/index.md)","id":"GHSA-xmj3-9gf7-h52w","markdown":"https://insights.sbomify.com/GHSA-xmj3-9gf7-h52w/index.md","name":"GHSA-xmj3-9gf7-h52w","record":{"aliases":[],"analysis":null,"analysis_generated_by":null,"assigner":null,"cpe":[],"cvss":{"score":null,"severity":null,"source":null,"vector":null,"version":null},"cwes":[],"description":"### Summary\n\nOn Windows, attacker-controlled content in a wheel's\n`.dist-info/namespace_packages.txt` can cause setuptools' legacy wheel\ninstallation path to create an `__init__.py` outside the requested\n`destination_eggdir`.\n\nThe attacker can influence the destination path, but not the contents of\nthe created file.\n\n### Details\n\nTested setuptools commit:\n\n`6ead555c5fb29bc57fe6105b1bffc163f56fd558`\n\nRelevant source:\n\n`setuptools/wheel.py`\n\nSHA-256:\n\n`359b7e0d5dd8c3135653abe08a8ed5dc0352eadfd7df22cb5e2b5303b7c3cafd`\n\nThe relevant call path is:\n\n`Wheel(wheel_path).install_as_egg(destination)`\n→ `_install_as_egg`\n→ `_convert_metadata`\n→ `_fix_namespace_packages`\n\nA wheel can provide attacker-controlled content in:\n\n`\u003cdistribution\u003e.dist-info/namespace_packages.txt`\n\nThe namespace value is eventually used approximately as:\n\n```python\nmod_dir = os.path.join(destination_eggdir, *mod.split('.'))\nmod_init = os.path.join(mod_dir, '__init__.py')\n\nIf mod is a Windows drive-qualified absolute path containing no dots,\nmod.split('.') preserves it as a single component.\nOn Windows, os.path.join(destination_eggdir, absolute_component) discards\nthe original base directory and resolves to the attacker-supplied absolute\npath.\nThe existing wheel filename and ZIP traversal checks do not validate this\nmetadata value before it is subsequently interpreted as a filesystem path.\n\n```markdown\n### PoC\n\nThe reproduction was performed entirely inside a disposable temporary\ndirectory.\n\nLayout:\n\n```text\nsandbox/\n    destination/\n    outside/\n    input/\n    canary.txt\n```\n\nA synthetic wheel was created containing:\n\n`demo_pkg-1.0.dist-info/namespace_packages.txt`\n\nwhose content was the absolute path of:\n\n`sandbox\\outside`\n\nThe real acquired setuptools implementation was then invoked:\n\n```python\nsetuptools.wheel.Wheel(synthetic_wheel).install_as_egg(\n    sandbox_destination\n)\n```\n\nThe operation completed without exception.\n\nExpected metadata was created under:\n\n`sandbox\\destination\\EGG-INFO`\n\nbut setuptools also created:\n\n`sandbox\\outside\\__init__.py`\n\nThe file did not exist before execution.\n\nIts contents were:\n\n```python\n__import__('pkg_resources').declare_namespace(__name__)\n```\n\nThe unrelated canary remained byte-identical.\n\nThe sandbox was deleted after recording the evidence.\n```\n\n### Impact\n\nA crafted wheel can cause setuptools to create a fixed-content\n`__init__.py` outside the intended installation directory at a\nfilesystem path influenced by the wheel, with the permissions of the\nprocess performing the installation.\n\nThe demonstrated reproduction required the target parent directory to\nalready exist.","ecosystems":["PyPI"],"exploits":{"exploitdb":null,"first_seen":null,"github_poc":null,"max_poc_stars":null,"metasploit":null,"nuclei":null,"refs":[],"tier":null},"has_fix":true,"headline":"setuptools: Windows path escape via namespace_packages.txt during legacy wheel installation Description","id":"GHSA-xmj3-9gf7-h52w","indexable":true,"kev":null,"kind":"advisory","links":{"ecosystem":"PyPI","product":null,"products":[],"type":null,"year":"2026"},"n_packages":2,"n_references":null,"packages":[{"ecosystem":"PyPI","fixed":["84.1.0"],"introduced":["38.2.2"],"last_affected":[],"package":"setuptools","purl":null,"source":"GHSA-xmj3-9gf7-h52w"},{"ecosystem":"PyPI","fixed":["84.1.0"],"introduced":["38.2.2"],"last_affected":[],"package":"setuptools","purl":"pkg:pypi/setuptools","source":"GHSA-xmj3-9gf7-h52w"}],"products":null,"published":"2026-10-23","related":[],"sources":[{"class":"attribution","licence":"CC BY 4.0","name":"GitHub Advisory Database","prefix":"GHSA"}],"ssvc":{"automatable":null,"exploitation":null,"technical_impact":null},"state":null,"updated":null,"vendors":null},"summary":null,"url":"https://insights.sbomify.com/GHSA-xmj3-9gf7-h52w/"}