Every few weeks, another Python package gets backdoored. Maintainer credentials leak, malicious versions land on PyPI, and hundreds of thousands of developers unknowingly install compromised code. The ecosystem learned in 2024 that token theft is not a theoretical risk — it is the dominant attack vector. In 2026, PyPI finally has the defenses to make that much harder. This is what changed, what still needs fixing, and what maintainers must do today.
In this tutorial, you will learn to:
- Understand how Anthropic’s $1.5M PSF grant is funding PyPI’s security overhaul
- Adopt Trusted Publishing (OIDC) to eliminate API tokens from your publishing workflow
- Use Sigstore attestations so consumers can verify your package provenance without managing keys
- Recognize the Q1 2026 supply chain attack patterns and what they mean for maintainers
- Apply a concrete security checklist to lock down your own PyPI package in 2026
Page Contents
The Funding Behind PyPI’s Security Overhaul
In December 2025, Anthropic committed $1.5 million to the Python Software Foundation over a two-year partnership focused entirely on ecosystem security. The investment — announced at pyfound.blogspot.com — explicitly targets CPython and PyPI improvements to prevent and mitigate supply chain attacks. The theregister.com reported the investment was earmarked specifically for “improving PyPI from a security perspective.”
That funding arrived at a pivotal moment. PyPI serves over a billion package downloads per day, making it one of the most targeted pieces of infrastructure in open source. We covered the full scope of the PSF grant and what it funds in an earlier post. The investment enables work the PSF could not previously afford: dedicated security engineering, formal audits, and infrastructure for provenance verification.
Trusted Publishing: Adoption Grows Past the 50,000-Project Milestone
The most significant security upgrade PyPI shipped in the last two years is Trusted Publishing — a mechanism that replaces long-lived API tokens with short-lived OIDC (OpenID Connect) credentials issued by your CI provider. Instead of storing a PyPI password-equivalent token in GitHub Secrets, your GitHub Actions workflow presents a cryptographic proof of identity directly to PyPI at publish time.
The numbers from the PyPI 2025 year-in-review post tell the story:
- 50,000+ projects now use Trusted Publishing
- About 25% of all files uploaded to PyPI in October 2025 were published via Trusted Publishers — up from roughly 10% in February 2024
- 1 million+ files had been published using a Trusted Publisher as of September 2025, per PEP 807
- PyPI expanded Trusted Publishing to GitLab Self-Managed instances and custom OIDC issuers in November 2025
That trajectory matters. More projects adopting Trusted Publishing means fewer long-lived API tokens sitting in GitHub Secrets — tokens that have been the starting point for nearly every major PyPI supply chain incident in recent years.
How Trusted Publishing Works
Understanding the mechanics helps maintainers appreciate why this is fundamentally more secure than token-based publishing.
Token-based publishing (the old way): You generate a PyPI API token, copy it into a GitHub Secret, and your workflow uses it to authenticate every publish. If an attacker steals that secret — through a phishing attack on the maintainer, a compromised GitHub account, or a vulnerability in the CI pipeline — they can publish any version of your package, forever, until you rotate the token.
Trusted Publishing (the new way): You register your GitHub Actions workflow as an authorized publisher in your PyPI project settings. When your workflow publishes, it obtains a short-lived JWT from GitHub’s OIDC provider, then exchanges it with PyPI for a scoped upload token valid for just that operation. No long-lived secret ever leaves PyPI.
# Minimal GitHub Actions workflow with Trusted Publishing
# No PyPI token stored in secrets — OIDC handles authentication
name: Publish Python Package
on:
release:
types: [published]
permissions:
id-token: write # Required for OIDC token exchange
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: pip build
- uses: pypa/gh-action-pypi-publish@release/v1
with:
# No 'password' or 'pypi-token' — uses OIDC
trusted-publishing: trigger
The key line is permissions: id-token: write. This grants GitHub permission to mint an OIDC JWT for this workflow. PyPI validates that JWT against GitHub’s OIDC endpoint, confirming the job ran in your repository under your conditions — without you ever handling a shared secret.
Sigstore Attestations: Provenance Without Managing Keys
Trusted Publishing eliminates token theft. Sigstore attestations take the next step — proving to consumers that the package they downloaded was built from the source they expect.
Sigstore is an open-source project (hosted under the Linux Foundation’s CNCF) that provides keyless signing. Instead of maintaining an RSA or GPG key pair — which is operationally complex and risky if the key leaks — you sign with an ephemeral certificate backed by Google’s Sigstore PKI. The certificate’s validity is recorded in Rekor, a public transparency log that anyone can query to verify a signature’s provenance.
PyPI’s attestation support went generally available in November 2024. When you publish via Trusted Publishing with a Sigstore-enabled client, PyPI automatically attaches a provenance attestation to every upload. According to the 2025 PyPI year-in-review, a growing share of uploads now include attestations — a number climbing as Trusted Publishing adoption climbs.
How to Verify a Package’s Attestation
Consumers can verify attestations using the sigstore Python package. This matters for organizations with strict supply chain requirements — they can verify the package they installed was built from a specific GitHub Actions run, on a specific commit, from their own repository.
# Install sigstore Python package
pip install sigstore
# Verify a package's attestation from PyPI
python -m sigstore verify provenance
--certificate-identity "https://github.com/owner/repo/.github/workflows/publish.yml"
--certificate-oidc-issuer "https://token.actions.githubusercontent.com"
your-package==1.0.0
The verification checks the attestation against Rekor’s transparency log, confirming the signature was issued by GitHub Actions at publish time and not later tampered with. This is fundamentally different from PGP signatures — there is no private key to manage or leak, and any consumer can independently verify provenance.
Malicious Package Trends Q1 2026: What Supply Chain Attacks Looked Like
The numbers are unambiguous: supply chain attacks targeting open-source package repositories surged 38% in Q1 2026 according to threat intelligence analysis, affecting npm, PyPI, Maven Central, Homebrew, and other registries. March 2026 was the worst month, with five major supply chain attacks including the Axios npm compromise.
For PyPI specifically, Q1 2026 brought three distinct campaigns that illustrate where the ecosystem remains vulnerable:
TeamPCP Campaign: LiteLLM and Telnyx (March 2026)
Between March 24–27, 2026, threat actor TeamPCP compromised two legitimate PyPI packages: LiteLLM (versions 1.82.7, 1.82.8) and Telnyx (versions 4.87.1, 4.87.2). These were not typo-squatting or fake packages — they were genuine packages with stolen publishing credentials.
The LiteLLM payload collected environment variables, SSH keys, cloud credentials, Kubernetes data, Docker configs, shell history, database credentials, and CI/CD secrets. Stolen data was encrypted with AES-256 and RSA-4096 before exfiltration to models.litellm[.]cloud. The malware also wrote persistence scripts to ~/.config/sysmon/sysmon.py and polled checkmarx[.]zone for follow-on payloads.
The Telnyx payload used a more sophisticated delivery mechanism: it downloaded a crafted WAV audio file from 83.142.209.203:8080/ringtone.wav at runtime, extracted an XOR-encrypted second-stage payload hidden in audio frames, and executed it in memory. This technique — embedding malicious code in audio files — is designed to bypass static analysis tools that only scan for known malicious signatures in code files.
Xinference Supply Chain Poisoning (April 2026)
By late April 2026, TeamPCP returned with three malicious versions of Xinference (versions 2.6.0, 2.6.1, 2.6.2) — a popular open-source AI model inference framework with over 680,000 total downloads from PyPI. The attackers obtained PyPI release credentials from Xinference maintainers, then encoded multi-layered Base64 payloads inside the project’s __init__.py module.
When users installed or imported Xinference, the Python interpreter automatically decoded and executed the payload in memory. The malware harvested cloud credentials, SSH keys, API tokens, database passwords, cryptocurrency wallets, Git credentials, SSL certificates, and infrastructure configuration files — exfiltrating everything to the attacker’s C2 server. The malicious code annotation included a “# hacked by teampcp” comment, though TeamPCP publicly denied involvement and claimed third parties were using their name.
Three-Ecosystem Strike (April 21–23, 2026)
A coordinated three-platform attack hit npm, PyPI, and Docker Hub within the same 48-hour window. PyPI’s target was Xinference (the same versions as above). The Docker Hub target was Checkmarx KICS Docker images. The npm target was the pgserve package. All three campaigns shared the same objective: stealing API keys, cloud credentials, SSH keys, and other sensitive information from developer environments and CI/CD pipelines. The attackers used application-layer protocols for C2 communication and, in some cases, PowerShell for execution.
Common Attack Pattern: Credential Theft
The pattern across Q1 2026 attacks is consistent: compromise the maintainer’s PyPI publishing credential, upload a malicious version, and embed code that exfiltrates credentials and secrets at install-time or import-time. The attacks are designed to remain undetected long enough to spread through CI/CD pipelines before removal.
Critical: If you installed
litellm1.82.7 or 1.82.8,telnyx4.87.1 or 4.87.2, orxinference2.6.0–2.6.2, treat your host or CI job as a full credential exposure event. Rotate all secrets immediately.
PyPI’s Second Security Audit: Findings and Fixes
PyPI completed its second external security audit in April 2026, conducted by Trail of Bits and funded by the Sovereign Tech Agency. This audit was narrower in scope than the first — focusing specifically on PyPI’s codebase and behaviors rather than its infrastructure.
The audit identified 14 total findings: 2 high, 1 medium, 7 low, and 4 informational. Twelve were remediated; 2 were accepted for now due to implementation complexity.
The most security-relevant findings:
- OIDC JTI anti-replay timing issue (High): PyJWT’s 30-second leeway window for JWT validation exceeded the Redis cache TTL for the JTI (JWT Token Identifier) claim, creating a 25-second replay window where a stolen JWT could be reused. PyPI has since aligned the cache TTL to outlive the full leeway window.
- Organization member invitation vulnerability (High): An issue in how organization membership invitations were processed could allow privilege escalation.
- Macaroon API token IP ban bypass (Informational, accepted): Session auth enforces IP bans, but macaroon tokens do not — allowing uploads from banned IPs with a valid API token. This is an accepted risk due to implementation complexity.
- Wheel metadata validation gap (Low): Upload-form metadata and embedded
.dist-info/METADATAare never compared, potentially allowing hidden dependencies in wheels.
The audit reinforces that Trusted Publishing’s OIDC flow is well-designed — the JTI issue was in a validation edge case, not the core protocol. PyPI remediated the replay window issue promptly.
Security Checklist: Securing Your PyPI Package in 2026
If you maintain a package on PyPI, here is what you should do right now, roughly ordered by impact:
1. Migrate to Trusted Publishing (Highest Impact)
Go to your project’s settings on pypi.org, navigate to Publishing, and add a Trusted Publisher for your GitHub Actions workflow. The official guide at docs.pypi.org/trusted-publishers/ covers GitHub, GitLab, Google Cloud, and more. Delete any PyPI API tokens you have stored in GitHub Secrets.
If you use pypa/gh-action-pypi-publish, adding Trusted Publishing is roughly 5 lines in your workflow YAML. The pyOpenSci guide walks through the full setup with environment-specific controls for release vs. test PyPI.
2. Enable 2FA on Your PyPI Account (High Impact)
PyPI now supports TOTP-based two-factor authentication with email verification for TOTP logins. Over 52% of active PyPI users have non-phishable 2FA enabled. If you are in the other 48%, enable it now — it is the last line of defense if your password is compromised.
3. Add Attestations to Your Publishing Workflow (Medium Impact)
When you publish via Trusted Publishing, PyPI automatically generates a Sigstore attestation for your package. To verify this is working, use sigstore-python to check attestations on your published packages. The official PyPI attestations guide covers producing attestations manually if you are not using the standard GitHub Actions flow.
4. Audit Your Project’s Dependency Tree (Medium Impact)
Malicious packages often hide in transitive dependencies. Tools like Safety, pip-audit, and Snyk scan your installed packages for known vulnerabilities. For supply chain integrity, pip-audit can catch malicious packages before they reach production.
5. Use PEP 740 Trust Model in Your Consumer Workflows (Medium Impact)
If you install packages in CI or production environments, verify PEP 740 Sigstore attestations to confirm you are installing exactly what your trusted workflow published. This prevents a compromised credential from slipping a malicious version past your automation.
# Verify package attestation in CI before proceeding with install
import subprocess
import sys
def verify_package_attestation(package_name, expected_repo):
"""Verify a package was published from the expected GitHub repository."""
result = subprocess.run([
sys.executable, "-m", "sigstore", "verify", "provenance",
"--certificate-identity", f"https://github.com/{expected_repo}/.github/workflows/publish.yml",
"--certificate-oidc-issuer", "https://token.actions.githubusercontent.com",
package_name
], capture_output=True)
return result.returncode == 0
6. Set Up Automated CVE Monitoring (Lower Impact, Ongoing)
PyPI processed over 2,000 malware reports in the past year, with 66% handled within 4 hours and 92% within 24 hours. Automated monitoring means you catch a compromise of your package faster. GitHub’s Dependabot and PyPI’s own security advisories via GitHub Advisories Database are free starting points.
7. Rotate API Tokens Regularly if You Cannot Use Trusted Publishing (Fallback)
If your project cannot use Trusted Publishing yet (e.g., no CI system with OIDC support), rotate your PyPI tokens regularly and use scoped tokens with the minimum permissions required. PyPI supports project-scoped tokens that can only upload to a specific project — use this over account-level tokens.
Common Mistakes and Gotchas
- Storing PyPI tokens in GitHub Secrets still: If you are still using a PyPI password-equivalent token in your CI, you have the same credential-theft exposure you had before Trusted Publishing. The migration takes an afternoon and eliminates the entire class of attack.
- Skipping
id-token: writepermission: Without this in your workflow YAML, the OIDC flow cannot mint a token. GitHub Actions will fail silently or fall back to token-based auth — not the behavior you want. - Using trusted publishing only for production: Many maintainers configure it only for release tags but not for pre-release versions, leaving a gap for attackers to publish alpha or beta versions with stolen credentials. Configure all relevant environments.
- Not verifying attestations: Publishing with attestations is only half the story — if you are a consumer, you need to verify them too. Many teams enable attestations but never check them in their install pipeline.
- Ignoring transitive dependencies: Attestations prove your package was built correctly, not that your dependencies are safe. LiteLLM was legitimate; its attackers did not need to compromise LiteLLM’s build — only its publishing credentials to push malicious releases.
Summary and Next Steps
PyPI’s security posture in 2026 is meaningfully stronger than it was two years ago. The combination of Trusted Publishing (eliminating token-based credential theft), Sigstore attestations (cryptographic provenance), and 2FA (account-level defense) gives maintainers real tools to protect their packages. The funding from Anthropic’s PSF partnership is accelerating this work — but adoption still has far to go. Only 25% of file uploads used Trusted Publishing as of October 2025, meaning 75% of packages still rely on long-lived API tokens.
If you maintain a public Python package and have not migrated to Trusted Publishing, that is the single highest-impact security action you can take in 2026. It takes an afternoon, eliminates an entire class of supply chain attacks, and is now supported across GitHub Actions, GitLab CI, Google Cloud Build, and custom OIDC issuers.
Frequently Asked Questions
Does Trusted Publishing work with all CI providers?
Trusted Publishing on PyPI officially supports GitHub Actions, GitLab CI, Google Cloud Build, and generic OIDC providers. As of November 2025, GitLab Self-Managed instances are supported. If your CI provider supports OIDC, you can use Trusted Publishing — the official docs cover the specifics for each provider.
What is the difference between Sigstore attestations and PGP signatures on PyPI?
PGP signatures require maintainers to manage a private key — if that key leaks, attackers can forge signatures for malicious packages. Sigstore eliminates the private key through keyless signing: ephemeral certificates are issued by a trusted PKI and backed by a public transparency log (Rekor), making verification independent of any secret a maintainer holds.
How do I know if a package I installed was compromised in the TeamPCP campaign?
If you installed litellm 1.82.7 or 1.82.8, telnyx 4.87.1 or 4.87.2, or xinference 2.6.0–2.6.2, treat the environment as fully compromised. Rotate all credentials on that host, audit your CI/CD pipelines, and check for unexpected processes or persistence mechanisms. PyPI quarantined the LiteLLM project and removed all malicious versions.
Can I use Trusted Publishing without losing ability to publish from multiple environments?
Yes. Trusted Publishing lets you register multiple publisher configurations — one per environment (production, test, staging). You can also use manual approval gates in GitHub Actions to require human sign-off before a release is published. The pyOpenSci guide covers environment-specific configuration with approval requirements.

