Karya Semi
HomeBlogSearchCategoriesAboutContact
Karya Semi

Less noise. More notes.

HomeBlogAboutContactPrivacy PolicyDisclaimer

© 2026 Karya Semi. All rights reserved.

XGitHubLinkedIn
  1. Home
  2. /Categories
  3. /Software Engineering

PyPI Closes the Windows of Exposure: Inside the 14-Day Release File Rejection Rule

An analysis of the Python Package Index's new security policy rejecting new file uploads to existing releases after 14 days, its impact on supply chain security, and developer deployment pipelines. Strictly do NOT use em-dashes ('—' or '--') anywhere. Use commas, hyphens, or colons instead. Do NOT use LaTeX math '$' tags.

Dian Rijal Asyrof/July 26, 2026/6 min read
Illustration for PyPI Closes the Windows of Exposure: Inside the 14-Day Release File Rejection Rule

Most developers assume that once a software package is published, it becomes a static piece of history. You lock your dependencies, specify a version like requests==2.28.1, and assume you will get the exact same code every time you build your container or deploy to production. But package registries do not always work like immutable ledgers.

On the Python Package Index, commonly known as PyPI, a release is not a single file. It is a collection of files. When a maintainer publishes a new version of a library, they might upload a source distribution first. Later, they might upload precompiled binary wheels for macOS and various Linux architectures. Historically, there was no time limit on this. A maintainer, or anyone who gained access to their account, could upload a new wheel to a version that was released five years ago.

This open window created a significant security gap. PyPI recently closed it by introducing a strict 14-day limit on uploading new files to existing releases. It is a simple change, but it fundamentally alters how python supply chain security works.

The Architecture of a Python Release

To understand why this change matters, we have to look at how python packages are distributed. When you build a library, you typically generate two types of files: source distributions and wheels.

A source distribution, or sdist, contains the raw source code. If your library includes C extensions, the user's machine has to compile them during installation. This requires compiler tools on the target system, which can make installations slow and error-prone.

A wheel is a precompiled binary format. It is built for a specific Python version and CPU architecture. When you run pip install, pip checks if there is a compatible wheel for your system. If it finds one, it downloads it and unpacks it directly. This bypasses the compilation step entirely.

Because wheels offer a faster install experience, pip always prefers a compatible wheel over a source distribution. If a release has both package-1.0.0.tar.gz and package-1.0.0-cp310-cp310-manylinux.whl, pip will pull the wheel every time you install on a compatible Linux system.

This prioritization logic is highly efficient, but it also creates a subtle vulnerability.

The Mechanics of Post-Release Poisoning

Imagine a popular library that was last updated in 2021. The maintainer uploaded a source distribution, but they never got around to building wheels for every single platform. The release works fine, and thousands of projects depend on it, pinning it to version 1.0.0.

Now, fast forward to today. An attacker wants to compromise systems running this package. They do not want to publish a new version like 1.0.1 because that triggers alerts. Security tools monitor package registries for new versions, and developers might notice their dependency scanners flagging an unexpected update.

Instead, the attacker targets the old 1.0.0 release. They compromise the maintainer's PyPI credentials, perhaps through a leaked API key found in a public repository or a credential stuffing attack.

Once inside, the attacker does not touch the existing source distribution. They simply upload a new, malicious wheel to the 1.0.0 release. They tag it to support common systems, like modern Linux and Windows environments.

The next time a developer runs their deployment pipeline, pip looks for package==1.0.0. It sees the new wheel. Since a wheel is preferred over the old source distribution, pip downloads the malicious wheel. The attacker's code runs during the installation process, granting them access to the build server or production environment.

The developer has no idea they have been compromised. They did not change their dependency file. They did not upgrade the package version. The build log still shows it installed version 1.0.0. The attack happened entirely behind the scenes because PyPI allowed new files to be attached to old releases indefinitely.

Closing the Window: The 14-Day Rule

PyPI's new policy directly addresses this threat. Once a release is created, maintainers have a strict 14-day window to upload any additional distribution files for that release. Once those 14 days pass, the release is permanently locked. You cannot upload a new wheel, and you cannot upload a new source distribution.

If you try to upload a file after the window closes, PyPI's API will reject it with an error. The only way to distribute new files is to create a new release version.

Choosing a 14-day window instead of making releases instantly immutable accommodates the complexity of modern build systems. Many maintainers use automated build systems that run across multiple platforms. Building wheels for macOS and Windows can take time, especially if a build agent fails or a compiler issue needs manual troubleshooting. A 14-day window gives maintainers plenty of time to resolve these build issues and upload all necessary files.

But it prevents attackers from targeting old, unmonitored releases. If an attacker gains access to an account, they can no longer poison a release that was published months or years ago. They are forced to publish a new version, which is much easier to detect and flag.

How Maintainers Must Adapt

For most projects, this change will not disrupt daily operations. Modern CI/CD pipelines usually build and upload all files within a few hours of tag creation.

But there are scenarios where maintainers will need to change their habits.

Consider the release of a new Python version, such as Python 3.13. In the past, a maintainer might have decided to build Python 3.13 wheels for older, stable versions of their library. This allowed users on older versions to adopt the new Python runtime without upgrading the library itself.

Under the new rules, this is impossible if the older library version is more than 14 days old. The maintainer must release a new patch version of the library that includes the new wheels. While this requires a bit more effort, it is ultimately a safer practice. It ensures that a version tag on PyPI remains a reliable representation of a specific point in time.

Another challenge involves projects with manual release steps. If a maintainer uploads a source distribution from their laptop and plans to upload wheels later when they have access to a different machine, they must do so within two weeks. If they forget, they will have to bump the version number.

Moving to Trusted Publishers

To make package management even more secure, PyPI encourages maintainers to use Trusted Publishers. This authentication method uses OpenID Connect (OIDC) to link PyPI directly to code repositories on platforms like GitHub or GitLab.

Historically, maintainers had to generate a PyPI API token and store it as a secret in their repository. If an attacker gained access to the repository settings or compromised the CI/CD platform, they could steal the token and upload malicious files.

With Trusted Publishers, you do not store any long-lived secrets. When your GitHub Actions workflow runs, it requests a temporary identity token from GitHub. PyPI verifies this token against a pre-configured trust relationship. If the token matches, PyPI issues a short-lived access token that is only valid for the duration of that specific build.

Combining Trusted Publishers with the 14-day upload limit creates a double barrier for attackers. First, they cannot easily steal credentials because there are no permanent secrets to compromise. And even if they manage to hijack a workflow run, they cannot modify historical releases.

The Broader Push for Supply Chain Security

PyPI's 14-day rule is not an isolated experiment. It is part of a coordinated effort across the open-source ecosystem to secure software supply chains.

For years, package registries operated on a model of maximum convenience. Anyone could publish anything, and files could be modified or added with minimal friction. This open model helped open-source software grow rapidly, but it also made registries a prime target for supply chain attacks.

We are now seeing the consequences of that open model. Attackers regularly target registries like npm and PyPI to distribute malware and steal credentials.

In response, registries are tightening controls. PyPI now requires two-factor authentication for all maintainers. They have automated malware detection systems that scan new uploads. They have restricted the use of certain package names to prevent typosquatting. The 14-day rule is the latest tool in this security toolkit.

It represents a shift in thinking. We are moving away from the idea that package registries should be completely flexible storage systems. Instead, we are treating them as critical infrastructure that must prioritize integrity and predictability.

Best Practices for Developers

If you consume Python packages, this change helps protect you from silent dependency poisoning. But you still need to follow good security habits.

First, use a dependency locker. Tools like Poetry or Pipenv generate lock files that contain cryptographic hashes of every package file. When you install dependencies, the package manager verifies that the hash of the downloaded file matches the hash in the lock file. This ensures that even if someone manages to upload a malicious file within the 14-day window, your build will fail because the hash will not match.

Second, monitor your dependencies for updates. While the 14-day rule protects old versions, attackers can still publish malicious new versions. Automated tools can alert you when a dependency is updated, allowing you to review the changes before pulling them into your codebase.

For maintainers, the path forward is clear. Automate your release process using Trusted Publishers. Build all your wheels in a single, automated workflow run. This ensures that all distribution files are uploaded to PyPI at the same time, well within the 14-day window.

Ecosystem security is a shared responsibility. While PyPI's infrastructure changes make the platform safer, it is up to developers and maintainers to adopt the tools and practices that keep their code secure. The 14-day rule is a welcome change that closes a major security gap, making the entire Python ecosystem a little more resilient against supply chain threats.

DR

Dian Rijal Asyrof

Writes about useful AI tools, programming practice, and the craft of building reliable software.

Previous articleThe True Cost of $1.6B in Idle DeFi Liquidity: Capital Efficiency, Automated Vaults, and Yield OptimizationNext articleAndroid's Looming ADB Restriction: What It Means for Local Diagnostics and Device Modding
SecuritySoftware EngineeringProgramming
On this page↓
  1. The Architecture of a Python Release
  2. The Mechanics of Post-Release Poisoning
  3. Closing the Window: The 14-Day Rule
  4. How Maintainers Must Adapt
  5. Moving to Trusted Publishers
  6. The Broader Push for Supply Chain Security
  7. Best Practices for Developers

On this page

  1. The Architecture of a Python Release
  2. The Mechanics of Post-Release Poisoning
  3. Closing the Window: The 14-Day Rule
  4. How Maintainers Must Adapt
  5. Moving to Trusted Publishers
  6. The Broader Push for Supply Chain Security
  7. Best Practices for Developers

See also

Illustration for The Developer's Trap: Why Git Signed Commits Don't Guarantee Codebase Security
Software Engineering/Jul 15, 2026

The Developer's Trap: Why Git Signed Commits Don't Guarantee Codebase Security

Mandating Git commit signing is a trending compliance requirement. But relying on the green badge creates a false sense of security that leaves repositories vulnerable.

5 min read
GitSecurity
Illustration for GitHub's Advisory Database Hit 1,560 CVEs in May. Here's Why That Matters.
Software Engineering/Jun 30, 2026

GitHub's Advisory Database Hit 1,560 CVEs in May. Here's Why That Matters.

GitHub's Advisory Database processed 5x its normal volume in May. Private vulnerability reports jumped from 550 to 3,000 per week. Here's the impact and how teams should respond.

3 min read
Software EngineeringSecurity
Illustration for Designing Resilient Pydantic v2 Schemas: Advanced Validation, Custom Serialization, and Error Handling
Programming/Jul 26, 2026

Designing Resilient Pydantic v2 Schemas: Advanced Validation, Custom Serialization, and Error Handling

Learn how to use Pydantic v2's modern validation engine, model configuration, and custom serializers to build bulletproof data schemas in Python applications. Do NOT write any math symbols or variables wrapped in '$' dollar signs. Do NOT use LaTeX math '$' tags at all. Use backticks for variables (e.g., `validate_assignment`). Absolutely ZERO single dollar signs for math formulas. Do NOT generate any em-dashes ('—' or '--').

7 min read
ProgrammingBest Practices