If you use requests in Python batch jobs that call APIs from internal core systems, or in web application containers, whether a TLS endpoint is trusted is in many cases decided by a certificate bundle (cacert.pem) contained in a small package called certifi. Updating the OS certificates does not change this bundle. So when a problem is found in the bundle, you keep using the old bundle unless you rebuild your Python dependencies and container images.
On October 20, 2026 (UTC), the certifi advisory GHSA-6q48-6c7w-9gw2 was registered in the GitHub Advisory Database as CRITICAL. It states that, for the root certificate emSign ECC Root CA - G3 included in the bundle, the private key of an eMudhra intermediate CA chaining to it was compromised and the CA revoked it. The fixed version is certifi 2026.10.19.
For this article, we reviewed the advisory, the certifi repository, and the published artifacts of PyPI and pip, and compared the contents of each version's bundle in a local virtual environment. For developers who maintain Python business systems and containers, we explain what changed, where old bundles remain, and how to check.
The only root removed is emSign ECC Root CA - G3
The advisory's description is as follows (excerpt).
Certifi versions before 2026.10.18 include the
emSign ECC Root CA - G3root certificate in their bundled CA store. Eight eMudhra intermediate CA certificates that chain to this root have compromised private keys and the CA has revoked them.
It states that an attacker holding the compromised key could issue certificates that appear valid for any hostname, and if positioned on the network path, could intercept or tamper with the TLS traffic of clients that trust the certifi bundle. Examples of affected software listed include requests, urllib3, pip and the Python.org installer for macOS. The affected range is 2019.03.09 or later and below 2026.10.19.
The fix came in two stages. Below are the results of examining the certifi repository history and extracting and comparing cacert.pem from each version.
| Version (PyPI release date and time, UTC) | Number of certificates in the bundle | emSign roots |
|---|---|---|
| 2026.7.22 (July 22) | 121 | 4: G1, G3, C1 and C3 |
| 2026.10.18 (October 18, 16:21) | 117 | None (all 4 removed in "Remove emsign") |
| 2026.10.19 (October 20, 02:24) | 120 | 3: G1, C1 and C3 (G3 not restored) |
The advisory states, "Certifi 2026.10.18 removed all emSign roots from the bundle. Certifi 2026.10.19 restored the emSign roots that are not affected. Upgrade to 2026.10.19 or later." Comparing the 2026.7.22 and 2026.10.19 bundles certificate by certificate, the only difference was that emSign ECC Root CA - G3 (SHA-256 fingerprint 86:A1:EC:BA:…:6B:BE:6B) was gone.

2026.10.18 also removed the three unaffected roots. In the editorial team's assessment, environments upgraded to 2026.10.18 may fail verification if they connect to endpoints using certificates that chain to these three roots. If you are upgrading now, do not stop at 2026.10.18; go to 2026.10.19 or later.
Which library trusts which bundle
To identify what needs updating, consider separately whether each library you use reads the certifi bundle or the OS certificate store. Here is what we confirmed in the source.
| Usage | Trusted certificates | Evidence checked |
|---|---|---|
requests without specifying verify | certifi's cacert.pem | requests/certs.py uses from certifi import where, and adapters.py uses DEFAULT_CA_BUNDLE_PATH |
| pip (Python 3.10 or later) | OS store + certifi bundled with pip | index_command.py additionally loads certifi.where() into the truststore context |
Using urllib3 on its own without passing ca_certs | OS store | util/ssl_.py calls load_default_certs() |
The comment in requests/certs.py says, "This module returns the preferred default CA certificate bundle. There is only one — the one from the certifi package." httpx also has certifi as a PyPI dependency (we did not check how it loads the contents this time).
Since 24.2, pip verifies with both the OS certificates and certifi on Python 3.10 or later (NEWS: "Use system certificates and certifi certificates to verify HTTPS connections on Python 3.10+."). Even with settings that use the OS store, the certifi bundle bundled with pip continues to be loaded. The NEWS for pip 26.2.2 (released October 20) says "Upgrade certifi to 2026.10.19," so the bundled certifi has been upgraded to the fixed version. The bundled certifi in the previous release, 26.2.1, is 2026.06.17 and includes G3.
As the table above shows, urllib3, which the advisory lists as an example, uses the OS store when used on its own without passing ca_certs. However, if the application passes ca_certs=certifi.where(), it uses the certifi bundle, so check what is specified in the code.
We compared the bundles of each version ourselves
On October 21, 2026, we created a virtual environment in the editorial team's test environment (Linux, Python 3.11.17) and installed wheels obtained from PyPI (with hashes checked against PyPI's values) to verify.
$ python -m venv venv
$ venv/bin/python -m pip --version
pip 24.0 from …/venv/lib/python3.11/site-packages/pip (python 3.11)
$ venv/bin/python -c "import pip._vendor.certifi as c; print(c.__version__)"
2023.07.22
# certifi 2026.7.22 と requests 2.34.2 を入れた状態
certifi 2026.07.22
requests DEFAULT_CA_BUNDLE_PATH = …/site-packages/certifi/cacert.pem
certs 121 | emSign ECC Root CA - G3: True | emSign Root CA - G1: True
# certifi 2026.10.19 に上げた状態
certifi 2026.10.19
certs 120 | emSign ECC Root CA - G3: False | emSign Root CA - G1: True
# pip を 26.2.2 に上げた状態
pip 26.2.2 vendored certifi 2026.10.19
The default bundle of requests pointed to cacert.pem of the certifi installed in the virtual environment, and upgrading certifi removed G3 from the bundle.
Another finding was that the pip in a virtual environment created with python -m venv is old. In this environment, pip 24.0 bundled with Python 3.11 was installed, and its bundled certifi was 2023.07.22. Even if you upgrade the application's certifi, pip itself keeps using this old bundle. If your Dockerfile does not upgrade pip after python -m venv, upgrade pip as well.
If you set REQUESTS_CA_BUNDLE, requests uses that bundle instead of certifi (we confirmed with REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt that verify becomes that path). In that case, keeping the specified bundle up to date is the responsibility of whoever manages it.
Steps to check containers and production environments
From here on are the editorial team's suggestions. Old bundles can remain in three places: application dependencies, container images, and pip.
- Search your lock files. Check the certifi version in
requirements*.txt,poetry.lock,uv.lockandPipfile.lock. Even if it is not a direct dependency, it is installed as a dependency of packages such asrequests. - Check the version in running environments. Run
python -c "import certifi; print(certifi.__version__, certifi.where())"in the image or on the server and confirm it is 2026.10.19 or later. On servers with multiple virtual environments, run it with the Python the application actually uses. - Check the versions bundled with pip and uv. Use
python -c "import pip._vendor.certifi as c; print(c.__version__)"to confirm it is 2026.10.19 or later (pip 26.2.2 or later). pip 26.2.2 targets Python 3.10 or later, and as of October 21, no fixed pip release usable with Python 3.9 or earlier has been published on PyPI. uv uses its own bundled certificate bundle rather than certifi, so useuv --versionto confirm it is at or above 0.13.4 (released October 20), the fixed version for a separate advisory, GHSA-hq85-5cpj-mr62. - Rebuild images. The advisory asks you to "rebuild container images that vendor certifi." If certifi is pinned in a lock file, raise the version before building. Also check that old layers are not being reused from the base image cache.
- Search for
verifysettings. Search forverify=,ca_certs=,REQUESTS_CA_BUNDLEandSSL_CERT_FILE, and wherever a bundle other than certifi is referenced, confirm with that bundle's maintainer that it has been updated.
Even if you cannot rebuild images right away, certifi is a package with few dependencies, and the Python versions it supports on PyPI are 3.7 or later. requests requires certifi>=2023.5.7, so upgrading only certifi to 2026.10.19 still satisfies requests's dependency requirement. The editorial team recommends first upgrading certifi and pip, then checking items 2 and 3 above with the rebuilt image.
In Python installed from Linux distribution packages, as noted in the comment in requests/certs.py, where() may be replaced with the OS bundle. In that case, you need to update the OS's ca-certificates or similar. The page compiled by the person who reported this issue (emudhra.we-have-a-problem.com) lists fixed versions for Ubuntu, Debian, Alpine and others, but we have not checked each distribution's own announcements this time.
Reviewing certificate operations as a whole is also covered in protecting staging on the assumption that it will be discovered through CT logs and shorter SSL certificate validity periods and automatic renewal. Other changes in the uv 0.13 series are covered in what changed in uv 0.13.
Scope of verification
On October 21, 2026, we reviewed the JSON for GHSA-6q48-6c7w-9gw2 in github/advisory-database, the certifi/python-certifi repository (the commits "Remove emsign" and "Restore unaffected emSign roots," and
cacert.pemat tags 2026.07.22, 2026.10.18 and 2026.10.19), the public information on PyPI for certifi, pip, requests and httpx, and the pypa/pip repository (NEWS.rst,index_command.py) (document research). We also compared the certificates in the certifi 2026.7.22, 2026.10.18 and 2026.10.19 bundles with openssl in a virtual environment on Linux (Python 3.11.17), and checked the bundle path used byrequests, howREQUESTS_CA_BUNDLEtakes effect, and the versions of certifi bundled with pip 24.0, 26.2.1 and 26.2.2 (hands-on testing). We have not checked traffic using the compromised intermediate CA's certificate, connection failures with 2026.10.18, Windows or macOS, packages in each Linux distribution, or how the Mozilla certificate store handles this. On October 21, before publication, we also checked the guidance for Python users on discuss.python.org (asking users to update to certifi 2026.10.19, pip 26.2.2, uv 0.13.4 and others and to rebuild images), the uv advisory GHSA-hq85-5cpj-mr62, and the list of intermediate CAs on the page compiled by the reporter.
For updating the dependencies and containers of business systems and batch jobs built with Python, please contact us through development, AI and automation consultations.
References
- GHSA-6q48-6c7w-9gw2: certifi bundles emSign root CAs with compromised intermediate CA keys(github/advisory-database)
- GHSA-6q48-6c7w-9gw2(certifi/python-certifi)
- certifi/python-certifi — commit 5cb238c(Remove emsign)
- certifi/python-certifi — commit 662df63(Restore unaffected emSign roots)
- certifi — PyPI
- pip 26.2.2 NEWS (pypa/pip)
- pypa/pip — src/pip/_internal/cli/index_command.py
- psf/requests — src/requests/certs.py
- Information for Python users regarding eMudhra / emSign CA certificate security incident(discuss.python.org)
- GHSA-hq85-5cpj-mr62(astral-sh/uv)








