Who this is for: anyone who installs packages with pip, uv, conda or pixi, anyone running programs that make HTTPS calls with libraries such as requests, and anyone maintaining Python Docker images or CI.
This article is based on official statements from the Python projects (CPython and pip developers), the certifi, uv and conda projects, Mozilla, Google, eMudhra and the Linux distributions. It does not cover how to attack anything or how the keys were recovered. Social media has been calling this a "Python security emergency", but no code execution flaw has been found in Python itself.
続報待ち:この記事は公式発表に合わせて更新します
October 24, 2026 (JST)まだ分かっていないこと
- Whether CPython's ssl module will reject the compromised intermediate keys (the change is in review and not merged yet)
- How Python 3.11 and 3.12, and their Docker official images, will handle the old pip (the release managers plan to backport the ssl module change that blocks the compromised intermediates instead of bumping pip; not merged as of October 24)
- eMudhra's final root-cause report
- Chrome's root removal, scheduled for October 27 (Pacific time)
The Python projects published their notice on October 20 and released Python 3.15.1, 3.14.9 and 3.13.17 on October 21. Chrome and Firefox blocked the affected intermediates on October 17. No exploitation has been announced. We will add the decisions on 3.11 and 3.12 and any further CPython changes once they are confirmed.
Am I affected? A quick table by environment
Whether you are affected depends on which part of your Python setup carries a CA list. One machine can hold separate lists for each Python version, each way Python was installed and each virtual environment.
| Environment | What carries the old list | What to do |
|---|---|---|
| Any environment that uses pip | The certifi vendored inside pip (survives an OS fix) | Upgrade pip to 26.2.2+ |
| Programs configured to use standalone certifi, such as requests | The standalone certifi package | Upgrade certifi to 2026.10.19+ |
| Environments using uv | The CA list built into uv | Upgrade uv to 0.13.4+ |
| conda, Mamba, pixi | Each tool plus the certifi and ca-certificates packages | Upgrade to conda 26.9.4+ and pixi 0.82.1+, and upgrade certifi and ca-certificates in the environment |
| Python from the python.org macOS installer | The certifi shipped with the installer | Follow the official post to upgrade pip and certifi; on 3.13+ move to the fixed Python |
| Docker images and CI | Whatever pip, certifi and OS bundle existed at build time | Rebuild without the cache |
| pip or certifi installed from Linux packages (apt, dnf) | The OS ca-certificates (Debian patches pip to use it) | Update ca-certificates to the fixed version |
When using urllib3 directly, the default is the system CA store. Update that store; if your configuration explicitly uses certifi or another bundle, update that bundle too (urllib3's certificate verification guide).
What happened (from official statements)
- Report
- On October 17, 2026, a security researcher reported to the Apple, Google, Microsoft and Mozilla root programs and to eMudhra that the private keys of eight eMudhra intermediate certificates could be recovered
- Scope
- Eight intermediates. Six are for TLS (HTTPS) and were trusted by Chrome, Mozilla, Microsoft and Apple; two are for code signing. All were created in a key generation ceremony on April 30, 2025. The six TLS intermediates chain to the root emSign ECC Root CA - G3 (the two code-signing ones sit under a different root)
- Cause
- Google says the private keys were generated with insufficient randomness. Mozilla says it recovered the keys independently and confirmed that the key generation was flawed. eMudhra says a step in the ceremony produced a second, weak set of keys alongside the strong ones, and the weak keys were the ones used. The full root cause is still under investigation
- What the keys allow
- Mozilla says the keys could be used to issue fraudulent HTTPS certificates for sites the holder does not control. An attacker who can intercept a user's connection could use them to impersonate websites and potentially read or modify traffic
- eMudhra's response
- Revoked all eight on October 18. It says seven were never used in production and the one that was had not issued any certificate. It stopped issuance under this root on October 20, and on October 22 announced that it will exit the global SSL/TLS certificate business
- Browsers
- Chrome blocked the keys through CRLSet on October 17. Firefox blocked them the same day through OneCRL and shipped Firefox 158.0.1 and ESR updates on October 20. On October 20 Mozilla decided on an emergency removal of the root and removed it from NSS 3.131.1. Chrome will remove it on October 27 (Pacific time)
- Python projects
- They published a notice on October 20 (updated through October 22) asking users to upgrade to at least certifi 2026.10.19, pip 26.2.2, uv 0.13.4, sigstore 4.5.1, conda 26.9.4 and pixi 0.82.1, and to rebuild container images with layer caching disabled. On October 21 they released Python 3.15.1, 3.14.9 and 3.13.17, which bundle pip 26.2.2
certifi is the widely used Python package that holds a list of trusted certificate authorities. It is derived from Mozilla's list, and requests and pip use it to decide whether a server's certificate is genuine. certifi 2026.10.18 (published October 18, UTC) removed all emSign roots, and 2026.10.19 (published October 20, UTC) restored the emSign roots that are not affected. certifi's own advisory lists 2026.10.18 as patched, but the GitHub Advisory Database entry and the Python projects recommend 2026.10.19 or later for compatibility with the unaffected emSign roots. certifi 2026.10.23 then removed two more emSign roots to follow Mozilla (eMudhra says that removal was planned earlier and is unrelated to this incident).
How serious is it?
Chrome, Firefox
Blocked on October 17. Also reject certificates missing from public CT logs
pip before 26.2.2
Always reads its vendored certifi, even after an OS fix
requests and other certifi-based clients
Use standalone certifi older than 2026.10.19
uv before 0.13.4, Docker images
Keep the list from build time
Browsers are protected by two things: they receive certificate blocks automatically, and they reject certificates that are not in the public Certificate Transparency (CT) logs. Google says no TLS certificates chaining to the affected intermediates were logged to CT before its block, so no forged certificate could have been used against CT-enforcing clients.
pip and requests use neither mechanism. They judge only by the CA list they carry, so if that list is old, they accept a forged certificate as genuine.
What could happen
- An attacker on the network path redirects connections to PyPI, python.org and other sites to a fake server
- pip install installs a tampered package
- API keys or passwords sent with requests are read
What an attacker needs, and what we know
- The attacker must be able to sit on your network path (the same Wi-Fi, a compromised router, a corporate proxy and so on)
- There is no code execution flaw in Python itself
- No exploitation had been announced as of October 24
Do not be complacent. Mozilla said on October 20 that multiple people had independently recovered the keys and some had disclosed this publicly, so making a forged certificate is not hard. Avoid running an old pip anywhere someone could get on the path, such as public Wi-Fi, shared networks or the network around a CI runner. Our guide to public Wi-Fi risks covers that side.
First, check your versions
Check the pip version
Run this with the Python you want to check (inside the virtual environment, if you use one). Version 26.2.2 or later is fixed.
python -m pip --versionRunning pip on its own can point at another Python's pip. Use python -m pip so you know which Python you are checking.
Check the certifi version
This shows the standalone certifi that requests and similar libraries use. Version 2026.10.19 or later is fixed. If it is not installed, pip prints a "not found" warning.
python -m pip show certifiThe certifi vendored inside pip is a separate copy. Run python -m pip debug and look for the certifi== line under "vendored library versions". After you upgrade to pip 26.2.2, it reads 2026.10.19.
Check uv and conda
Run uv --version (0.13.4+ is fixed), conda --version (26.9.4+) and pixi --version (0.82.1+).
List every place Python is installed
One machine often has the OS Python, a python.org Python, Pythons from Homebrew or pyenv, and per-project virtual environments (such as .venv). A virtual environment is any directory with a pyvenv.cfg file. Writing the full list down first makes it much harder to miss one.
Upgrade in a safe order
The order matters. An old pip trusts the affected certificates, so if it simply downloads a new pip and that download is intercepted, a fake pip could be installed. The Python projects recommend installing pip with a pinned file hash (a fingerprint of the file's contents) and then using that pip for everything else.
Upgrade pip to 26.2.2 with a pinned hash
The official post and the Python blog give a command with the pip 26.2.2 file URL and its SHA-256 hash. It has this shape. Copy the URL and hash exactly from the official post (we deliberately do not reproduce them here).
python -m pip install "pip @ <URL from the official post>#sha256=<hash from the official post>"With a pinned hash, pip refuses to install a file whose contents differ, so an intercepted download cannot install a fake pip. The official post says browsers should already have updated their stores and can be used for checking. For example, open the pip 26.2.2 files page on PyPI and confirm the hash shown there matches.
Use the new pip to upgrade certifi and uv
Once pip is 26.2.2, use it to upgrade certifi. If you installed uv with pip, upgrade it here too.
python -m pip install --upgrade certifi
python -m pip install --upgrade uvIf you installed uv with its standalone installer, follow uv's advisory and move to 0.13.4 or later. The advisory says that if you switch uv to the system certificates instead, you must confirm the OS has already removed the affected root or intermediates.
Repeat in every virtual environment
pip and certifi live inside each virtual environment. The Python projects ask users to upgrade pip and uv in every existing virtual environment on the system. For old environments you no longer use, recreating or deleting them can be quicker.
Move 3.13 to 3.15 to the fixed releases; on 3.11 and 3.12, upgrade pip in every new venv
Python 3.15.1, 3.14.9 and 3.13.17 bundle pip 26.2.2, so new environments created with python -m venv also get the fixed pip.
The Python projects say there will be no 3.11 or 3.12 release that bundles a newer pip, because of compatibility risk. Upgrade pip first thing every time you create a virtual environment. pip 26.2.2 supports Python 3.10 and later. On 3.9 and older the fixed pip is not available, so upgrade Python itself (3.10 has also reached end of life).
For the python.org macOS Python, upgrade with that interpreter
Python from the python.org macOS installer ships certifi. The blog lists commands for 3.13, 3.14 and 3.15 (the official post shows 3.15 as an example) that call that interpreter directly, for example /Library/Frameworks/Python.framework/Versions/3.15/bin/python3.15, to upgrade pip and certifi. Upgrade the free-threaded build (such as python3.15t) separately. If pip install --upgrade certifi fails on the certifi shipped by the installer, the official post suggests reinstalling it with --ignore-installed --no-deps certifi.
Docker, CI and lockfiles
This is where fixes are most often missed. Fixing your laptop does nothing for images and CI runners, which keep the old list from build time.
Rebuild Docker images without the cache
The Python projects ask you to rebuild container images with layer caching disabled so the latest OS certificates are fetched. Re-pull the base image as well, for example with docker build --pull --no-cache. After rebuilding, run python -m pip --version inside the container to confirm.
On October 21 the Docker official images updated their 3.13 and later definitions to the fixed Python releases (3.15.1, 3.14.9 and 3.13.17). The image maintainers say they will not bump pip in the 3.11 and 3.12 tags unless Python publishes new releases. If you use 3.11 or 3.12 images, upgrade pip to 26.2.2 in your Dockerfile with a pinned hash.
Raise certifi pins in requirements and lockfiles
A pin such as certifi==2025.x.x in requirements.txt or constraints.txt puts the old certifi straight back. The same goes for uv.lock, poetry.lock, pylock.toml and Pipfile.lock. Raise certifi to 2026.10.19 or later, regenerate the lockfile and roll it out to your images and CI.
Exempt certifi and pip from dependency cooldowns
If you use a setting that waits a fixed period before accepting newly published versions (a dependency cooldown), the fix will not arrive until the period ends. A Python packaging maintainer warned that cooldown users stay exposed until they update. Exempt certifi, pip and uv from that setting.
Upgrade the actions and tools your CI uses
The pypa/gh-action-pypi-publish GitHub Action used for publishing to PyPI has a fixed release, v1.14.3. For cibuildwheel, upgrade to v4.3.4 or later (v4.3.3 brought the fix; v4.3.4 also covers pip on Python 3.9 and other targets). Check that your CI configuration does not pin older versions.
Watch for copies cross-signed by another CA
Some of the affected intermediates also had copies cross-signed by another certificate authority. Cross-signing lets the same intermediate key be trusted under a different root. A CPython core developer says the root used for that cross-signing is present in certifi releases before April 2025 and in old pip versions that bundle them (for example, pip 25.0.1 with certifi 2024.8.30). According to the cross-signing CA, that root had already been removed from the Chrome and Mozilla stores but was still trusted by Microsoft and Apple as of October 18 (Mozilla record). Debian, and Ubuntu 14.04 to 20.04 (USN-8944-2), also removed that cross-signing root alongside the emSign root. The cross-signing CA says it revoked the cross-signed copies on October 19, but most clients outside the browser do not check revocation. Deleting only the emSign root from an old bundle is not enough, because the cross-signing root would remain. Move to certifi 2026.10.19 or later (certifi releases since April 2025 no longer contain the cross-signing root).
Update the OS certificates (ca-certificates)
On Linux, the ca-certificates package holds the system CA list. curl and Pythons installed from OS packages use it.
| Distribution | Official notice | Fixed version |
|---|---|---|
| Debian 13 (trixie) | DSA-6572-1 (October 20) | ca-certificates 20250419+deb13u1 |
| Debian 12 (bookworm) | DLA-4845-1 | ca-certificates 20250419~deb12u2 |
| Ubuntu 26.10, 26.04, 24.04, 22.04 | USN-8944-1 (October 20) | ca-certificates 20260816ubuntu0.(release) |
| Ubuntu 20.04, 18.04, 16.04, 14.04 | USN-8944-2 (October 20) | Provided through Ubuntu Pro (ESM) |
Debian's fix removes emSign ECC Root CA - G3 and the cross-signing root. Ubuntu's USN-8944-1 removes emSign ECC Root CA - G3 and, on 22.04 to 26.04, refreshes the list to version 2.90 of the Mozilla bundle; USN-8944-2 removes both roots on 14.04 to 20.04. pip installed from Debian's own package (python3-pip) is patched to read the OS list instead of the vendored certifi, so updating ca-certificates fixes it. On Windows and macOS, install the OS updates.
How to confirm you are done
Check three versions everywhere
On your machine, in every virtual environment, inside every Docker image and in CI, confirm pip 26.2.2+, certifi 2026.10.19+ and uv 0.13.4+. If even one old copy remains, you are not done.
Confirm the affected root is gone from certifi's list
python -m certifi prints the path of certifi's bundle file. If the name "emSign ECC Root CA - G3" no longer appears in it, the list is fixed.
grep -c "emSign ECC Root CA - G3" "$(python -m certifi)"An output of 0 means it is gone. With Debian or Ubuntu's packaged certifi the file has no certificate names, so 0 proves nothing; check the ca-certificates version instead. pip's vendored list is fixed once pip is 26.2.2 or later.
Check pins and the OS
Search your requirements files and lockfiles for certifi and make sure nothing older than 2026.10.19 is pinned. On Linux, confirm ca-certificates is at or above the fixed version in the table above, for example with apt policy ca-certificates.
This site's view: protecting browsers does not protect everything else
Browser users were protected within hours without doing anything, because browsers receive blocks automatically and reject certificates missing from CT logs. pip, requests and CI images have neither. Each holds its own copy of the CA list, and the owner has to update every copy one by one. There are as many copies as there are virtual environments and images.
One habit also helps against the next incident of this kind: keep package hashes in your requirements (--require-hashes). If the hashes live in your own files, an intercepted download cannot swap in a package with different contents. See auditing dependencies with OSV-Scanner for pinning and checking dependencies, and the LiteLLM 1.107.0 malware incident for a case where the distribution channel itself was attacked.
For website operators
Chrome will stop trusting emSign ECC Root CA - G3 on October 27 (Pacific time). Google asks operators whose certificates chain to this root to get a new TLS certificate from another hierarchy (under a different root) in the Chrome Root Store immediately. If you use an eMudhra certificate, check the issuer's guidance.
Timeline
April 30, 2025
eMudhra creates intermediates, including the eight affected ones, in a key generation ceremony.October 17, 2026
A security researcher reports that the eight keys can be recovered. Chrome (CRLSet) and Firefox (OneCRL) block them the same day.October 18
eMudhra revokes the eight intermediates. certifi 2026.10.18 removes all emSign roots.October 19
The cross-signing CA revokes its cross-signed copies.October 20
Mozilla decides on emergency removal of the root. certifi 2026.10.19, pip 26.2.2 and uv 0.13.4 are released and the Python projects publish their notice. Debian and Ubuntu update ca-certificates. Google announces Chrome will remove the root on October 27.October 21
Python 3.15.1, 3.14.9 and 3.13.17 and conda 26.9.4 are released. The Docker official images update their 3.13+ definitions to the fixed Python releases.October 22
eMudhra announces it will exit the global SSL/TLS certificate business.October 23
certifi 2026.10.23 removes two more emSign roots to follow Mozilla.
Sources (public record)
The facts in this article come from the public sources below. We do not reproduce how the keys were recovered or anything usable for an attack.
- Python projects, "Information for Python users regarding eMudhra / emSign CA certificate security incident" (October 20, 2026; later posts checked through October 24) — discuss.python.org
- Python, "Python 3.15.1, 3.14.9 and 3.13.17 are out" (October 21, 2026) — blog.python.org
- certifi security advisory (GHSA-6q48-6c7w-9gw2) — github.com / GitHub Advisory Database github.com
- certifi, "Remove emsign" (#437, October 18, 2026) — github.com / certifi release history pypi.org
- pip changelog (26.2.2: upgrade certifi to 2026.10.19) — pip.pypa.io
- uv security advisory (GHSA-hq85-5cpj-mr62) and 0.13.4 — github.com
- conda, "Security updates for conda, Mamba, and Pixi" (October 21, 2026) — conda.org
- Google, "Protecting Chrome and Android Users from Compromised eMudhra Intermediate CA Certificates" (October 20, 2026) — blog.google
- Mozilla, "Protecting Firefox users following the compromise of eMudhra intermediate certificates" (October 20, 2026) — blog.mozilla.org
- Mozilla incident record (Bug 2083449: the eight intermediates, revocation times, root removal, cross-signed copies) — bugzilla.mozilla.org
- eMudhra, "eMudhra Statement on Recent Certificate Security Incident" (first published October 20, updated October 22) — emudhra.com
- eMudhra, "eMudhra to exit global SSL/TLS certificate business" (October 22, 2026) — emudhra.com
- Reporting on eMudhra's exit (The Record, October 22, 2026) — therecord.media
- Debian, "DSA-6572-1 ca-certificates" (October 20, 2026) — lists.debian.org / "DLA-4845-1 ca-certificates" lists.debian.org
- Ubuntu, "USN-8944-1" and "USN-8944-2" ca-certificates (October 20, 2026) — ubuntu.com / ubuntu.com
- Docker official image (python) issue, "These images ship vulnerable pip" (fix for 3.13+, handling of 3.11 and 3.12) — github.com
- CPython, "Distrust compromised eMudhra intermediate CA keys" (additional ssl module defense, not merged as of October 24) — github.com
- Status of Python versions — devguide.python.org
Update history
2026-10-24: First version, based on the Python projects' October 20 notice and posts through October 23, the Python 3.15.1, 3.14.9 and 3.13.17 releases, the certifi, pip and uv advisories, statements from Google, Mozilla and eMudhra, and the Debian and Ubuntu ca-certificates updates. We will update this page once the handling of 3.11 and 3.12 and any further CPython change are decided.
Read next
- Auditing dependencies: Auditing dependencies with OSV-Scanner
- Attacks on distribution channels: LiteLLM 1.107.0 malware incident / Trivy supply chain compromise
- When a vulnerability is announced: CVE remediation playbook
- Impersonation on the network path: Public Wi-Fi risks
- Terms: What is public-key cryptography? / What is Let's Encrypt?