PyPI Wheels Carry Binaries Nobody Can Tie to Their Source
Security / explainer
PyPI Wheels Carry Binaries Nobody Can Tie to Their Source
Python developer Artem Golubin argues that clean source can ship beside a malicious wheel, and the May 2026 TanStack incident shows a valid signature does not settle it.
Nothing in PyPI's upload path proves that the compiled binary in a Python wheel was built from the source code published beside it, and a signature from a trusted build pipeline does not fix that. Security developer Artem Golubin made the first half of that argument in a post last updated Oct. 15, 2026, and a May 2026 incident shows the second half.
The attack Golubin describes needs a publisher account or a build pipeline an attacker can use. It has not been reported as used in the wild, and his post names no package that was hit this way.
What a wheel is and why pip prefers it
A wheel is a prebuilt package for one Python version, one platform and one processor architecture. pip prefers wheels to source distributions because installing from source needs the right compiler and system libraries on the user's machine. Golubin says each release of his own packages ships up to 90 different wheels.
Many popular Python packages keep their speed-critical parts in C, C++ or Rust, so the wheel holds machine code, not readable Python. That is the part a scanner cannot read as text.
The verification gap Golubin describes
His central claim, quoted from the post: "there is no proper way to make sure a package was compiled using the same source code when it was uploaded to PyPI." Two consequences follow in his telling.
- An attacker can publish clean source and a malicious binary together.
- An implant can wait: "An attacker can plant a small implant that would only trigger after some time," which lets it outlast a scan on release day.
He adds that most scanning looks at source, and that "there is very little focus in analyzing the binaries." Golubin runs a malicious-code scanner called Hexora, so he has a stake in how scanning gets done. Reverse engineering a binary is much harder to automate than reading source, which is his point.
His mitigation is blunt: "compile all Python dependencies from scratch and never install the most recent version." Few teams can do that for a full dependency tree, and the post does not claim otherwise.
What PyPI attestations do prove
PyPI's attestations documentation describes digital attestations that "bind each release distribution" to "a strong cryptographic digest of its contents." The verifier can then confirm that a package "was attested to by a particular identity", with GitHub Actions given as an example. PyPI allows attestations to be signed by Trusted Publisher identities on GitHub Actions, GitLab CI/CD and Google Cloud.
The page does not claim an attestation shows the code is safe, and it does not describe a check that the binary matches the repository source. The only provenance form it mentions is SLSA Provenance, described as attesting to a package's original source location.
| Control | What it ties together | What it does not show |
|---|---|---|
| Wheel file digest | The file to its bytes | Who built it |
| Attestation | The file to a named publisher identity | That the code is benign |
| Source scan | The published source to a ruleset | That the binary matches the source |
The TanStack case, May 11, 2026
Wiz's incident record shows why identity is not safety. Starting around 2000 UTC on May 11, 2026, a group Wiz calls TeamPCP published dozens of trojanized packages to npm and PyPI over roughly six hours, beginning with the @tanstack namespace. @tanstack/react-router alone has about 12 million weekly downloads, per Wiz.
The malicious versions went out through legitimate trusted publishing workflows using valid GitHub Actions OIDC identities. Wiz warns that provenance, trusted publishing metadata and signing "should not be considered indicators that affected releases were safe." The same wave reached @mistralai, @uipath and @opensearch-project.
That case involved npm and PyPI together, and Wiz does not describe a binary-versus-source mismatch. It shows the weaker point Golubin's argument rests on: the signature answers "who published this", and only the pipeline's own integrity answers "what did it build".
Each of Golubin's 90 wheels is a separate binary to build, attest and scan, and a source-only scanner reads none of them. For related reading on how long-lived flaws sit unnoticed, see the AA26-281A coverage of old CVEs and the Cisco Secure Email Gateway root flaw.
What a team can do before the tooling catches up
Golubin's own advice is to build from source and avoid the newest release. A narrower step is to pin versions and delay upgrades, which gives scanners and the community time to flag a bad release. Teams that require attestations should treat them as an identity check and keep the scanning, because the May 11 incident passed the identity check.
Neither PyPI's page nor Golubin gives a date for mandatory binary attestation. PyPI's documentation, as fetched, says nothing about making attestations compulsory.
Sources
More in Security
- 01Microsoft Fixes 1,411 Flaws in October Patch Tuesday, One ExploitedThe Oct. 13 release is a record by BleepingComputer’s count, but three trackers report three different totals and the exploited bug needs a user to open a file.
- 02Broadcom Wi-Fi Bug Has No CVE and No Patch on Belgian GatewaysResearcher Quentin Kaiser says a WPS overflow in Broadcom’s SDK dates to at least 2010 and lets an attacker in radio range run code without the network key.
- 03Palo Alto Patches PAN-OS CVE-2026-0322 as Attackers Reach Management InterfacesThe flaw gives an authenticated administrator root on the firewall. Palo Alto lists no workaround, and CISA gave federal agencies three days.
- 04Cisco Secure Email Gateway CVE-2026-76519: One Crafted Attachment Reaches RootCisco rates the flaw 9.8 and says it is exploited. The scanner update that fixes it needs no restart, and the advisory lists no workaround.