Poetry CVE-2026-41140
LOWSeverity by source
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N/E:U/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Primary rating from Vendor (https://github.com/python-poetry/poetry) · only source for this CVE.
CVSS VectorVendor: https://github.com/python-poetry/poetry
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N/E:U/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Lifecycle Timeline
5Blast Radius
ecosystem impact- 7 pypi packages depend on poetry (5 direct, 2 indirect)
Ecosystem-wide dependent count for version 2.3.4.
DescriptionCVE.org
Summary
The extractall() function in src/poetry/utils/helpers.py:410-426 extracts sdist tarballs without path traversal protection on Python versions where tarfile.data_filter is unavailable. Considering only Python versions which are still supported by Poetry, these are 3.10.0 - 3.10.12 and 3.11.0 - 3.11.4.
Impact
Arbitrary file write (path traversal) from untrusted sdist content.
In practice, the impact is low because an attacker who exploits this vulnerability can as well include arbitrary code in a setup.py, which will be executed when the sdist is built after tar extraction. In other words, a malicious sdist can write arbitrary files by design. However, since it is unexpected and not by design that the file write already happens during tar extraction, this is still considered a vulnerability.
On Python 3.11.2 (Debian Bookworm default, directly tested), a crafted sdist with ../../ tar member paths writes files outside the intended extraction directory. The traversal occurs during metadata resolution (poetry add --lock), before the build backend is run.
Affected Environments:
- Python 3.10.0 through 3.10.12 (inclusive):
tarfile.data_filterabsent or broken - Python 3.11.0 through 3.11.4 (inclusive):
tarfile.data_filterabsent or broken - Debian Bookworm: Python 3.11.2 (default)
- Ubuntu 22.04 LTS: Python 3.10.6 (default)
Patches
Versions 2.3.4 and newer of Poetry ensure that paths are inside the target directory.
Root Cause
File: src/poetry/utils/helpers.py, lines 410-426:
def extractall(source: Path, dest: Path, zip: bool) -> None:
"""Extract all members from either a zip or tar archive."""
if zip:
with zipfile.ZipFile(source) as archive:
archive.extractall(dest)
else:
broken_tarfile_filter = {(3, 9, 17), (3, 10, 12), (3, 11, 4)}
with tarfile.open(source) as archive:
if (
hasattr(tarfile, "data_filter")
and sys.version_info[:3] not in broken_tarfile_filter
):
archive.extractall(dest, filter="data")
else:
archive.extractall(dest)
# <-- NO FILTER: path traversalOn Python versions without a working tarfile.data_filter, the else branch at line 426 calls tarfile.extractall() without any filter or path validation. This enables three attack vectors:
- Direct path traversal: Tar members with
../../path components write files outside the extraction directory. - Symlink traversal: A symlink member pointing outside dest, followed by a file written through that symlink, escapes the boundary.
- Hardlink attacks: Hardlink members can read arbitrary files (same inode) or overwrite targets outside dest.
Call Sites
This function is called from two locations:
src/poetry/installation/chef.py:104(_prepare_sdist): Duringpoetry install/poetry addwhen building a package from sdist. Only triggered when the executor is enabled (actual installation).src/poetry/inspection/info.py:322(_from_sdist_file): During dependency resolution (poetry lock/poetry add). This path is reached when the sdist'sPKG-INFOlacksRequires-Distmetadata, forcing Poetry to extract the archive (and afterwards build the package).
Suggested Fix
Apply path validation in the else branch, covering direct traversal, symlinks, and hardlinks:
def extractall(source: Path, dest: Path, zip: bool) -> None:
"""Extract all members from either a zip or tar archive."""
if zip:
with zipfile.ZipFile(source) as archive:
archive.extractall(dest)
else:
broken_tarfile_filter = {(3, 9, 17), (3, 10, 12), (3, 11, 4)}
with tarfile.open(source) as archive:
if (
hasattr(tarfile, "data_filter")
and sys.version_info[:3] not in broken_tarfile_filter
):
archive.extractall(dest, filter="data")
else:
# Validate all member paths before extraction
dest_resolved = dest.resolve()
safe_members = []
for member in archive.getmembers():
member_path = (dest_resolved / member.name).resolve()
if not member_path.is_relative_to(dest_resolved):
raise ValueError(
f"Refusing to extract {member.name}: "
f"would write outside {dest}"
)
if member.issym():
link_target = (member_path.parent / member.linkname).resolve()
if not link_target.is_relative_to(dest_resolved):
raise ValueError(
f"Refusing symlink {member.name}: "
f"target {member.linkname} outside {dest}"
)
elif member.islnk():
link_target = (dest_resolved / member.linkname).resolve()
if not link_target.is_relative_to(dest_resolved):
raise ValueError(
f"Refusing hardlink {member.name}: "
f"target {member.linkname} outside {dest}"
)
safe_members.append(member)
archive.extractall(dest, members=safe_members)AnalysisAI
Path traversal vulnerability in Poetry's tar extraction function allows arbitrary file writes when processing untrusted source distributions on Python 3.10.0-3.10.12 and 3.11.0-3.11.4, where the tarfile.data_filter safety mechanism is absent or broken. The vulnerability is triggered during dependency resolution (poetry add --lock) or installation before the build backend executes, enabling attackers to write files outside the intended extraction directory via crafted tar member paths, symlinks, or hardlinks in malicious sdists.
Technical ContextAI
Poetry's extractall() function in src/poetry/utils/helpers.py (lines 410-426) conditionally applies tarfile.data_filter to defend against path traversal attacks, but only when the filter is available and not in a known-broken state. On affected Python versions (3.10.0-3.10.12, 3.11.0-3.11.4)-including Debian Bookworm's Python 3.11.2 and Ubuntu 22.04 LTS's Python 3.10.6-the fallback code path calls tarfile.extractall() without any path validation. This exposes three attack vectors: direct path traversal using ../../ path components in tar member names, symlink traversal where symlink targets escape the extraction boundary, and hardlink attacks that can read or overwrite arbitrary files. The root cause is CWE-22 (improper limitation of a pathname to a restricted directory), where untrusted tar archive content is extracted without validating member paths against the destination directory.
RemediationAI
Upgrade Poetry to version 2.3.4 or newer, which includes path validation in the extractall() function to reject tar members with paths traversing outside the target directory, symlinks pointing outside the boundary, and hardlinks targeting external files. This is the primary and recommended fix. If an immediate upgrade is not possible, restrict Poetry's operation to Python 3.11.5 or later, or Python 3.10.13 or later (where tarfile.data_filter is functional), by configuring poetry/python version constraints in your CI/CD and development environments. Additionally, audit dependency sources and avoid adding untrusted or unverified packages via poetry add, and enable dependency verification mechanisms (e.g., signed package indexes) if available. A temporary compensating control (not recommended long-term) is to run poetry add and poetry lock in isolated containers with restricted filesystem access, though this adds operational overhead and does not address the root vulnerability.
Wazuh SIEM platform versions 4.4.0 through 4.9.0 contain an unsafe deserialization vulnerability in the DistributedAPI t
BentoML version 1.4.2 and earlier contains an unauthenticated remote code execution vulnerability through insecure deser
pgAdmin 4 contains critical remote code execution vulnerabilities in the Query Tool download and Cloud Deployment endpoi
The renderLocalView function in render/views.py in graphite-web in Graphite 0.9.5 through 0.9.10 uses the pickle Python
BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Rated critica
OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph
pyLoad download manager version prior to 0.5.0b3.dev77 exposes the Flask SECRET_KEY through an unauthenticated endpoint.
In Mercurial before 4.1.3, "hg serve --stdio" allows remote authenticated users to launch the Python debugger, and conse
Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/
pyLoad is the free and open-source Download Manager written in pure Python. Rated medium severity (CVSS 5.3), this vulne
Langflow (a visual LLM pipeline builder) contains a critical unauthenticated code execution vulnerability (CVE-2026-3301
Cross-user flow execution in Langflow (< 1.9.1) lets any authenticated API-key holder run another user's flow by passing
Same weakness CWE-22 – Path Traversal
View allShare
External POC / Exploit Code
Leaving vuln.today
GHSA-73h3-mf4w-8647