PyPI Blog: Releases now reject new files after 14 days
PyPI Security Update: 14-Day Window for File Uploads
The Python Package Index (PyPI) has implemented a new security measure: new files will now be rejected if they are uploaded to a release that is more than 14 days old.
🛡️ The Motivation for Change
The primary goal of this restriction is to safeguard the ecosystem against "poisoning." If a project's publishing tokens or CI/CD workflows are compromised, attackers could potentially inject malicious files into stable, older releases that users trust.
While there is currently no evidence that this specific vulnerability has been exploited, the technical possibility existed simply because attackers hadn't yet publicized the method.
The Risk Profile
Previously, a compromise could lead to a confusing "hybrid" state:
Some files in a release are safe.Other files in the same release are malicious.- Result: An indeterminate state that is difficult for users to verify and tedious for admins to clean up.
📜 Historical Context & Timeline
The road to this decision involved several years of discussion and specific security incidents.
- Initial Spark: The conversation began during the development of PEP 740 (Digital Attestations) in early 2024.
- The Catalyst: In March 2026, the packages
LiteLLMandTelnyxwere compromised. This occurred due to amutable referencewithin their implementation of the Trivy GitHub Action. - The Debate: Some developers argued against the change because they frequently added support for new Python versions to existing releases.
📊 Data-Driven Decision Making
To determine if this change would break too many workflows, PyPI analyzed their database. They specifically looked at the top 15,000 packages to see how many uploaded cp314 wheels more than two weeks after the initial release.
| Metric | Value |
|---|---|
| Sample Size (Top Packages) | 15,000 |
| Projects uploading files after 14 days | 56 |
| Impact Ratio |
At the Packaging Summit (PyCon US 2026), Safety Security Engineer Mike Fiedler presented these findings. The consensus among attendees was that it is acceptable to require a version bump to support new Python versions.
🛠️ Technical Implementation & Future State
The patch was officially merged on July 8th, 2026, by Seth Larson.
Current Limitations
Users should be aware that this behavior is currently "primitive." There are no official APIs to check if a release is locked, nor are there defined semantics for this state.
The Roadmap
Future stability will come via PEP 694, which will standardize:
Upload 2.0 APIStaged Previews
Once implemented, releases will have explicit states:
Open: Accepting new files.Closed: No further modifications allowed.
Example Workflow Adjustment
If you need to support a new Python version today, follow these steps:
- Identify the need for a new wheel (e.g., Python 3.14).
-
Upload wheel to existing version 1.2.3(Now Rejected). - Increment version to
1.2.4. - Upload all necessary files to the new release.
# Example of what happens now after 14 days
$ twine upload dist/*
ERROR: Release is too old to accept new files. Please bump the version.
(Conceptual representation of PyPI security)
Credits: This initiative was led by Seth Larson and Mike Fiedler at the Python Software Foundation, with support provided by Alpha-Omega.