This is a mislabeled shipping crate problem, not a crowbar through the front door
CVE-2026-3219 affects pip through version 26.0.1, fixed in 26.1. The vulnerable logic can treat a concatenated or ambiguously structured archive as a ZIP based on ZIP metadata even when the filename says .tar.gz, which can lead pip to install files that do not match the archive type an operator thought they were installing.
In practice this is not an internet-reachable break-in; it is a *victim-installs-an-attacker-controlled-artifact* problem. Even though current PSF/CNA-linked advisory data shows a 4.6 MEDIUM CVSSv4 score, the real-world chain is narrower than that headline suggests: the attacker needs control of the package artifact or delivery path, active user/CI interaction, and a workflow that accepts ambiguous archives in the first place.
4 steps from start to impact.
Craft an ambiguous archive with tar + zip metadata
zipfile.is_zipfile() to trip while also presenting as a tar-based source distribution. The underlying bug is parser ambiguity: pip<=26.0.1 could prioritize ZIP handling even when the filename or operator expectation points to tar.- Attacker can create and host a specially crafted package archive
- Target workflow accepts archives outside a tightly controlled internal build pipeline
- Most enterprise package flows consume normal wheels from trusted indexes, not hand-crafted polyglot archives
- Hash pinning, repository curation, and artifact signing reduce the chance that a crafted archive is accepted
pip version exposure.Deliver it through a package source the victim will trust
requirements.txt, direct URL, private index, compromised mirror, or local file path that the victim's pip install workflow will use. This is the decisive friction point: exploitation requires a supply-chain foothold or user-assisted delivery, not unauthenticated remote reachability.- Victim runs
pipagainst attacker-controlled or attacker-influenced package content - User or CI job performs installation
- Internal mirrors often whitelist packages and normalize artifacts
- Modern CI usually builds from locked dependencies rather than arbitrary URLs or local archives
- Email, browser, or chat delivery still needs a human or pipeline operator to execute the install
Trigger vulnerable unpacking in pip<=26.0.1
pip, the vulnerable unpacking path can classify the file as ZIP and install the ZIP-interpreted contents rather than rejecting the ambiguity. The 26.1 fix changes this behavior so installation only continues when the file is uniquely identifiable as ZIP or tar.- Installed
pipversion is26.0.1or earlier - The install path reaches archive unpacking rather than a previously built wheel
- If a wheel is used instead of an sdist/archive path, this specific bug is sidestepped
- Tooling that pre-unpacks, validates, or repackages artifacts can break the chain before
pipsees the ambiguous file
pip-audit, Dependabot, GitHub Advisory ingestion, and OSV consumers can flag vulnerable versions, but they do not tell you whether your org installs ambiguous archives.Land integrity-impacting but narrow-scope results
- Installed files influence a build, package output, or local developer environment
- Downstream controls do not catch unexpected file layout or content
- Reproducible builds, artifact attestations, and post-build validation can catch drift
- The vulnerability does not itself provide direct unauthenticated RCE against a network service
The supporting signals.
| In-the-wild status | No evidence of active exploitation found in the sources reviewed; not in CISA KEV per the prompt and no campaign reporting surfaced in the PSF/GHSA/NVD references. |
|---|---|
| Proof of concept availability | Public technical reproduction exists via issue #13867 and the fix discussion in PR #13870; this is enough for competent attackers to reproduce without a turnkey weaponized repo. |
| EPSS | 0.00018 from the prompt. GitHub Advisory/OSV currently display roughly 0.018% / 5th percentile, which is directionally consistent with very low near-term exploitation likelihood. |
| KEV status | Not KEV-listed as provided in the prompt. No override to immediate emergency patching based on KEV. |
| Current authoritative scoring note | The prompt says there was no baseline, but as of 2026-04-20 the PSF CNA data shown by NVD and GitHub Advisory includes CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:A/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N = 4.6 MEDIUM. |
| Affected versions | Authoritative package range is all pip versions through 26.0.1 per OSV and GitHub Advisory. |
| Fixed version | Fixed in pip 26.1; the 26.1 changelog notes: fix installing .tar.gz source distributions that look like a zip file. |
| Exposure and scanning reality | Inference from product architecture: internet-wide scanners like Shodan/Censys/GreyNoise are largely irrelevant here because pip is a client-side package installer, not a remotely exposed daemon. Exposure is driven by where developers, CI runners, base images, and bootstrap scripts execute pip against untrusted archives. |
| Disclosure timeline | Bug reported in issue #13867 on 2026-03-26; fix merged in PR #13870 on 2026-04-19; CVE/advisory published 2026-04-20 via PSF security-announce. |
| Reporter / analyst attribution | The original bug reporter and patch author shown in GitHub is f3flight. GitHub Advisory credits amine-malloul-gira and tsokalski as analysts; PSF announcement was sent by Seth Larson. |
noisgate verdict.
The single biggest downgrade driver is attacker position: this is *not* unauthenticated remote exploitation, it is a supply-chain or user-assisted install path that requires the victim to run pip on an attacker-controlled ambiguous archive. That sharply limits reachable population and turns the issue into build/workstation integrity risk rather than broad fleet compromise.
Why this verdict
- Attacker position downgrade: exploitation requires control of the package artifact or delivery path plus a victim-initiated
pipinstall. That means post-social-engineering or post-supply-chain foothold, not first-stage remote compromise. - Exposure population downgrade:
pipis everywhere, but the vulnerable path only matters where teams ingest untrusted or non-normalized archives. Enterprises that mostly install wheels from PyPI or internal mirrors with hashes are exposed on paper but much less reachable in practice. - Blast radius downgrade: the direct impact is low-integrity confusion on the invoking host or CI runner, not guaranteed code execution against a server process. The compromise scope is usually one workstation, one image build, or one pipeline run.
Why not higher?
A higher rating would fit if this were remotely triggerable against a service or if the bug reliably yielded arbitrary file write or code execution on every install. The available sources describe confusing or incorrect installation behavior with local attack vector and active user interaction, which is materially narrower.
Why not lower?
It is still a real security flaw in a ubiquitous package manager, not mere cosmetic mislabeling. In organizations that consume third-party sdists, direct URLs, or locally staged archives in CI, ambiguous parsing can undermine package integrity assumptions and taint build outputs.
What to do — in priority order.
- Prefer wheels and pinned hashes — Force builds to consume curated wheel artifacts or hash-pinned packages from approved indexes. For a LOW verdict there is no formal mitigation SLA; treat this as backlog hygiene and implement during the next normal packaging-policy refresh.
- Block direct-URL and local-archive installs in CI — Disallow
pip installfrom arbitrary URLs, local file drops, or ad hoc archive paths in shared runners unless explicitly approved. This removes the easiest delivery path for ambiguous archives; for LOW, fold it into standard pipeline hardening work rather than emergency change windows. - Centralize package sources — Use an internal mirror or artifact repository that normalizes, scans, and records package content before developers or CI consume it. That pushes ambiguity handling out of end-user workstations and into a controllable choke point; again, no LOW mitigation SLA applies.
- Upgrade bootstrap images and venv seeds to
pip>=26.1— Refresh base images, devcontainers, golden workstations, and virtualenv seed packages so new environments stop inheriting vulnerablepipversions. For LOW, do this in the next routine toolchain uplift rather than as an out-of-band emergency patch.
- A WAF or edge firewall does not help because there is no remotely exposed service path to filter.
- Endpoint AV alone is not a reliable control here; the problem is parser ambiguity during package installation, not a known malware signature.
- MFA does nothing once a developer or CI job is already running
pipon the attacker-controlled archive.
Crowdsourced verification payload.
Run this on the target workstation, CI runner, container image, or base Python environment you want to assess. Invoke it with the same interpreter whose pip you care about, for example python verify_cve_2026_3219.py; no admin rights are required, and it checks the installed pip version in the current environment.
#!/usr/bin/env python3
"""
CVE-2026-3219 verifier for pip.
Outputs one of: VULNERABLE / PATCHED / UNKNOWN
Exit codes:
0 = PATCHED
1 = VULNERABLE
2 = UNKNOWN
"""
from __future__ import annotations
import re
import sys
try:
try:
from importlib import metadata as importlib_metadata
except Exception:
import importlib_metadata # type: ignore
except Exception:
print("UNKNOWN - unable to import package metadata support")
sys.exit(2)
def parse_version(v: str):
"""Very small parser sufficient for pip versions like 26.0.1 or 26.1."""
if not v or not isinstance(v, str):
return None
m = re.match(r"^(\d+)(?:\.(\d+))?(?:\.(\d+))?", v)
if not m:
return None
parts = [int(p) if p is not None else 0 for p in m.groups()]
while len(parts) < 3:
parts.append(0)
return tuple(parts[:3])
def main():
try:
version = importlib_metadata.version("pip")
except Exception as exc:
print(f"UNKNOWN - could not determine installed pip version: {exc}")
sys.exit(2)
parsed = parse_version(version)
fixed = (26, 1, 0)
if parsed is None:
print(f"UNKNOWN - unparseable pip version: {version}")
sys.exit(2)
if parsed < fixed:
print(f"VULNERABLE - installed pip version {version} is earlier than 26.1")
sys.exit(1)
else:
print(f"PATCHED - installed pip version {version} is 26.1 or later")
sys.exit(0)
if __name__ == "__main__":
main()
If you remember one thing.
pip actually runs in your estate: developer workstations, CI runners, base container images, venv bootstrap paths, and any automation that installs from direct URLs or local archives. Because this is LOW, there is no noisgate mitigation SLA and no noisgate remediation SLA beyond backlog hygiene; queue pip>=26.1 into the next routine toolchain refresh, but prioritize only the subsets that ingest untrusted sdists or ad hoc archive paths rather than fleets that install solely from pinned internal mirrors.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.