PyPI shipped one of its more meaningful security changes in years. As of July 22, 2026, releases older than 14 days can no longer accept new file uploads. No new wheels. No updated source distributions. If you missed the window, you are publishing a new version. The rule went live on July 8 in PyPI’s Warehouse codebase — and if it has not hit your release pipeline yet, it will.
What Actually Changed
Previously, PyPI allowed maintainers to add new files to an existing release indefinitely. You could ship version 1.2.3 today, then upload an ARM wheel for it three months later, still under the same version number. That model is now over. After 14 days, a release is frozen. Every artifact that belongs in it — binary wheels (.whl), source distributions (.tar.gz), or any other distribution file — must be uploaded before the window closes.
The rule is enforced at the registry level. There are no exceptions currently defined. If your release workflow uploads platform-specific wheels in separate CI runs spread across days — ARM on one runner, RISC-V on another, triggered by different pipelines — that workflow requires changes.
The Attack This Closes
The attack pattern this prevents is quiet by design. An attacker who compromises a maintainer’s PyPI API token — through phishing, a leaked CI secret, or a vulnerable third-party GitHub Action — does not need to publish a new version to do damage. They can add a malicious wheel to a release that already exists, already has users, and already has trust. Users with pinned dependencies (litellm==1.45.2, for instance) download the poisoned artifact on their next install without any version bump to alert monitoring tools. Dependency bots stay silent. No new diff appears in a pull request.
PyPI cited the March 2026 LiteLLM and Telnyx compromises as a catalyst — attackers exploited mutable release references through a vulnerable Trivy GitHub Action. Worth noting: PyPI also said it had not seen this specific attack exploited against PyPI directly. This rule is preventive, not a post-incident patch. That distinction matters — and it is the right call.
How Disruptive Is This, Really
PyPI ran the numbers before shipping. Of the top 15,000 packages, only 56 had uploaded a Python 3.14-compatible wheel more than 14 days after the release’s initial publication — roughly 0.4 percent. According to the official PyPI blog post, this was a deliberate data-backed decision before rolling the change out.
The fix for affected pipelines is not complicated. Consolidate your wheel builds into a single CI pipeline that completes within the release window. Tooling like cibuildwheel handles cross-platform matrix builds — Linux x86, ARM, macOS, Windows — in a single run. If you have already passed the 14-day cutoff for an existing release and need to add a wheel: publish a new patch version. Bumping from 1.2.3 to 1.2.4 is not a hardship. It is also more accurate about what you shipped and when.
Part of a Larger Shift
PyPI’s move is the third time-based supply chain defense to land in roughly six weeks, and the pattern is not coincidental. npm v12 blocked install scripts by default on July 8. GitHub’s Dependabot began enforcing a three-day default cooldown on routine version updates on July 14 — while keeping security updates immediate. Now PyPI closes the door on retroactive file uploads.
The shared logic across all three: automated pipelines are fast, and speed has become an attack surface. When a malicious package version can go from published to merged into a production build in under an hour, the automation itself is part of the vulnerability. Time-based friction — days instead of minutes — breaks the race condition attackers rely on without requiring developers to manually review each dependency update.
What This Does Not Fix
Be clear-eyed about the limits. The 14-day lock does not stop an attacker who publishes a new version entirely. It does not catch malicious code that stays dormant for longer than two weeks before activating. It will not protect against a compromised build system that poisons artifacts before they reach PyPI. And as the BleepingComputer analysis notes, Dependabot’s cooldown applies only to version updates — security updates bypass it entirely. The fastest automated path into your build pipeline is still at full speed by design.
PyPI also has not yet defined formal API semantics for what a “closed” release means — that is expected to arrive with PEP 694’s Upload 2.0 API, which remains in progress. For now, you cannot query whether a release is past its window without trying to upload and receiving a rejection.
What to Do Now
If you maintain Python packages, audit your release pipeline this week. Confirm that all wheels and distribution artifacts upload within 14 days of your release tag. If you use a multi-stage upload process that spreads across days, consolidate it. If you use Dependabot, verify your .github/dependabot.yml — the three-day cooldown is now the default, and you can adjust it explicitly if needed.
PyPI’s 14-day rule is not a complete answer to supply chain attacks. Nothing is. But it closes a specific, real attack vector with almost no impact on the overwhelming majority of maintainers. That is a good trade, and the Python ecosystem should take it without complaint.













