Skip to main content

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.

PyPI License: MIT Python Dependencies Tests Read only

[English] · Русский


certlens scanning a trust store

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

certlens explain

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

  1. Enumerate certificates from the chosen store, read-only.
  2. SHA-256 fingerprint each one.
  3. 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.
  4. 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.db reader
  • --diff against 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.

Metadata

Release files for certlens 1.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for certlens 1.0.1
File Size Uploaded
certlens-1.0.1.tar.gz 116.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for certlens 1.0.1
File Interpreter ABI Platform
certlens-1.0.1-py3-none-any.whl Python 3 none any Details

Total release size: 218.3 kB

Release files / certlens-1.0.1.tar.gz

Download URL certlens-1.0.1.tar.gz
Size 116.9 kB
Tags Source
SHA-256 checksum
How to use checksums
29396b5e2e9f8007384757267b6ea7af1629f2351ebbbabb37ae8359afce6bcf
BLAKE2b-256 checksum
How to use checksums
60e41d8b3b870b6e9303cdc16ec0160acf0860b65f9ac3732fc78558f36d43d9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.9.25

Release files / certlens-1.0.1-py3-none-any.whl

Download URL certlens-1.0.1-py3-none-any.whl
Size 101.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
fb9eeebc5ead4dd0127779fe85866f4668bab5ea59a79ffc440d636684662cc3
BLAKE2b-256 checksum
How to use checksums
e2aff30a0a8c556ca54658e2c2d3745e692670edeb60bf4edbadf1902d9e2013
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.9.25

Release history Release notifications | RSS feed

This release

1.0.1 This release

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page