Audit the certificate authorities your machine trusts: who runs them, which government they answer to, and which roots nobody vouches for.
Project description
certlens
Your machine trusts ~150 certificate authorities. Do you know who they are?
certlens reads a trust store, joins it against the Common CA Database, and tells you who operates every root you trust, which government they answer to, and which roots nobody's root program vouches for.
[English] · Русский
Real output. That scan found two TLS-interception proxies and an unidentified root on the machine it ran on.
The problem
Any one of the ~150 root CAs your machine trusts can issue a certificate for any domain, and your browser will accept it silently. Most people have never looked at the list. The tooling to enumerate a trust store exists. The tooling to judge one did not.
This is not a hypothetical concern, and it is not a niche one:
"Windows trusts 322 root certificates issued by 122 different organizations. I think this is a good point I would never trust 122 people in my life with my bank-account details. But if I trust my browser it seems that is exactly what I'm doing. Isn't there a better way?" — Hacker News, on a 255-point thread
"Is there any tool out there that will monitor my system's use of root CAs? So far I have not found anything … there are root CAs I do not think I need to trust; Hong Kong Post Office comes to mind as one I would rather not trust." — security.stackexchange.com, Nov 2023
"Is there a way to check if any non-standard root CAs have been added to my browser, without going through them one by one and comparing them to a fresh install? … It's too easy for arbitrary programs to add root CAs." — Hacker News, after the Superfish scandal
"There are now tons of Certification Authorities (CAs) that are trusted by default in major OS's, many of which are unrecognizable without online lookup or reference." — security.stackexchange.com, 177 votes, 25,884 views
And the stakes are documented history, not speculation:
| When | What |
|---|---|
| 2019 | Kazakh ISPs required a government root on every device. Mozilla and Google blocked it: "once installed, allowed the government to decrypt and read anything a user types or posts." |
| 2020 | Kazakhstan tried again. Mozilla, Apple, Google and Microsoft all blocked it. |
| 2022 | Russia's Ministry of Digital Development issued its own root, valid until 2032. EFF: "paves the way for a decade of digital surveillance." |
| 2023 | EU eIDAS Article 45 would have forced browsers to trust state-designated CAs. 504 scientists from 39 countries objected. |
| 2024 | Chrome distrusted Entrust after "a pattern of compliance failures." |
certlens exists so you can answer the question for your own machine, in two seconds, without reading 150 certificates by hand.
Install
pip install certlens
No runtime dependencies. A tool that tells you what to trust should not ask you to trust a dependency tree first.
Quick start
certlens # audit the system trust store
certlens scan node # audit Node.js's compiled-in roots
certlens stores # list every trust store on this machine
certlens explain "Hongkong Post"
Answer the "should I remove this?" question
Use it as a CI gate
Fail a build when an unexpected root is baked into an image:
certlens scan --fail-on high
Exit codes: 0 clean · 1 findings at or above the threshold · 2 error.
# .github/workflows/trust.yml
- run: pip install certlens
- run: certlens scan --fail-on high
Other output formats
certlens scan -f json | jq '.findings[] | select(.severity=="high")'
certlens scan -f html -o report.html
certlens refresh # pull the newest CCADB data
What it detects
| Finding | Severity | Meaning |
|---|---|---|
REVOKED_ROOT_TRUSTED |
critical | CCADB says revoked; it is still in your store |
UNRECOGNISED_ROOT |
high | In no root program, matching no known product |
LOCAL_INTERCEPTION_ROOT |
high/medium | A known proxy, antivirus or dev tool root — named |
NO_ROOT_PROGRAM |
high | Known CA, included by no vendor |
SHORT_LIVED_ROOT |
high | Unknown root valid under a year — a proxy signature |
EXPIRED_ROOT |
medium | Expired but still trusted |
STALE_AUDIT |
low | Audit period ended over 460 days ago |
STATE_OPERATED_CA |
low | Operator is a government or state-owned body |
CA_INCIDENT_HISTORY |
low | Operator has a documented distrust event |
WIDE_DELEGATION |
info | 5+ external organisations can issue under this root |
JURISDICTION_CONCENTRATION |
info | One country holds over 30% of your roots |
VENDOR_PLATFORM_ROOT |
info | An OS vendor's own root (e.g. Apple), verified by pinned fingerprint |
certlens recognises roots from Burp Suite, Fiddler, Charles, mitmproxy, mkcert, HTTP Toolkit, Proxyman, Zscaler, Netskope, Palo Alto, Fortinet, Forcepoint, Blue Coat, Cisco Umbrella, Sophos, McAfee, Kaspersky, Avast, AVG, Bitdefender and ESET — so a legitimate corporate proxy shows up as named, not as an unexplained mystery.
How it compares
| certlens | trust_stores_observatory | paranoia | cert-manage | openssl/certmgr |
|
|---|---|---|---|---|---|
| Lists your roots | yes | yes | container images only | yes | yes |
| Names the operator | yes | no | no | no | no |
| Shows jurisdiction | yes | no | no | no | no |
| Flags state-operated CAs | yes | no | no | no | no |
| Detects injected/proxy roots | yes | no | no | no | no |
| Names the proxy product | yes | no | no | no | no |
| Vendor-program membership | yes | partial | no | no | no |
| Audit staleness | yes | no | no | no | no |
| CI exit codes | yes | no | yes | no | no |
| HTML report | yes | no | no | no | no |
| Runtime dependencies | none | several | Go binary | Go binary | n/a |
| Modifies your store | never | no | no | yes | yes |
The closest thing ever built for the specific "which of these are governments?" question was certaintls — 8 stars, last touched in 2021, and it keyed on country freedom scores rather than operator identity.
How it works
- Enumerate certificates from the chosen store, read-only.
- SHA-256 fingerprint each one.
- Join against CCADB, the database Mozilla, Apple, Microsoft, Google and Cisco use to run their root programs. certlens ships a snapshot (940 roots), so it works offline and in air-gapped CI.
- Apply the rule set and rank by severity.
Decoding uses the standard library's ssl module — the same OpenSSL your
Python already relies on. certlens hand-rolls no cryptography.
certlens never modifies a trust store. There is no code path that writes to one. Removing roots breaks machines in confusing ways; certlens gives you the information and gets out of the way.
A note on language
"State-operated" here is a statement about corporate structure — the operator is a government body or state-owned enterprise — not an accusation of wrongdoing. Plenty of state-run CAs are well-administered. The point is that you should know, and right now most people cannot find out.
Roadmap
- Windows CTL trust store support
- Firefox NSS
cert9.dbreader -
--diffagainst a previously saved scan, for fleet drift detection - SARIF output for code-scanning dashboards
- Optional check of which roots your machine has actually used
- Community-maintained interception-product signature list
Contributing
See CONTRIBUTING.md. The most valuable contributions are new
interception-product signatures and corrections to the state-operator mapping —
both live in certlens/knowledge.py and both are
plain data.
git clone https://github.com/Ax1zz/certlens
cd certlens
python3 -m unittest discover -s tests -t .
Data and licence
Certificate authority data comes from the Common CA Database, published by the CCADB and used here under its terms of use. certlens is not affiliated with CCADB, Mozilla, or any certificate authority.
certlens is released under the MIT licence.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file certlens-1.0.1.tar.gz.
File metadata
- Download URL: certlens-1.0.1.tar.gz
- Upload date:
- Size: 116.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.25
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
29396b5e2e9f8007384757267b6ea7af1629f2351ebbbabb37ae8359afce6bcf
|
|
| MD5 |
4ef6828d7f2ddf641b6adfe798a0695a
|
|
| BLAKE2b-256 |
60e41d8b3b870b6e9303cdc16ec0160acf0860b65f9ac3732fc78558f36d43d9
|
File details
Details for the file certlens-1.0.1-py3-none-any.whl.
File metadata
- Download URL: certlens-1.0.1-py3-none-any.whl
- Upload date:
- Size: 101.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.25
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fb9eeebc5ead4dd0127779fe85866f4668bab5ea59a79ffc440d636684662cc3
|
|
| MD5 |
40978591f6d9acf5cd98fe97c4a3dd05
|
|
| BLAKE2b-256 |
e2aff30a0a8c556ca54658e2c2d3745e692670edeb60bf4edbadf1902d9e2013
|