Post-quantum cryptography risk scanner for source code and dependency graphs.
Project description
pqcheck
Generate a Cryptography Bill of Materials (CBOM) for your codebase in seconds, and gate CI on a crypto policy you can read.
pqcheck scans source code and dependency lockfiles for cryptographic
algorithm usage — RSA, ECDSA, AES modes, legacy hashes, post-quantum
primitives — and emits a CycloneDX 1.6 CBOM plus SARIF 2.1.0, evaluated
against a versionable YAML policy. It runs on a laptop and in CI with no
server, no account, and no network access during the scan.
Why now: NIST IR 8547 deprecates RSA and ECC by 2030 and disallows them
by 2035. Every migration framework (OMB M-23-02, the EU coordinated
roadmap, FS-ISAC guidance) makes inventory the first step. The existing
open tooling for that step needs a SonarQube server; the commercial
options start at enterprise pricing. This is the pip install version.
Status: pre-release. v0.1.0 lands on PyPI with Sigstore-signed
wheels. Until then: uv sync --all-extras && uv run pqcheck --help.
Leia em português.
Quickstart
$ pqcheck scan ./your-repo --policy cryptoct-default
✗ src/auth.py:42 — RSA [banned/critical, confidence high] — Shor — migrate to ML-KEM-768
⚠ src/hash.py:7 — BLAKE2B [default/medium, confidence high]
✓ src/aead.py:12 — AES [approved/info, confidence high]
dependencies: 47 parsed
policy cryptoct-default-1.0.0: 1 fail, 1 warn, 1 allow
Machine-readable outputs:
$ pqcheck scan . --policy cryptoct-default --format cbom -o cbom.cdx.json
$ pqcheck scan . --format sarif -o pqcheck.sarif # imports into GitHub Code Scanning
Gate CI (exit 1 when the policy trips):
$ pqcheck scan . --policy br-bcb-conservative --fail-on policy
$ pqcheck self-audit # fixed policy, CBOM always written
--fail-on high gates on base severity instead; --strict treats WARN
decisions as failures. A finding's displayed severity is demoted by
detection confidence, but gating always reads the base severity — low
confidence never lets RSA through.
What it detects
| Surface | Coverage |
|---|---|
| Python source | stdlib hashlib, cryptography (current + legacy + decrepit paths), pycryptodome — via AST, no execution |
| Go source | stdlib crypto/* and golang.org/x/crypto — union of a bundled go/types analyzer (semantic: key sizes, curves, modes) and a tree-sitter pass that also covers GOOS/cgo-gated files, which type resolution cannot see by construction |
| Lockfiles | pyproject.toml, uv.lock, requirements.txt, pom.xml, go.mod+go.sum, package-lock.json |
Java is next on the roadmap; it is not in v0.1.
Policies
Six bundled policies, all plain YAML you can fork:
cryptoct-default/cryptoct-strict/cryptoct-advisory— the general tiers (fail / fail-hard / report-only).br-bcb-conservative— for Brazilian financial institutions aligning their inventory with the cybersecurity controls of Res. CMN 4.893/2021.br-drex-piloto— the strictest profile, for teams that want new code quantum-safe by construction.br-vendor-dd— advisory profile for vendor due-diligence annexes.
To be clear about the regulatory framing: no Brazilian regulation currently mandates a cryptographic inventory or PQC migration. The BR profiles anticipate that direction; they do not claim an obligation that does not exist.
pqcheck policy show <name> prints any of them resolved;
pqcheck policy validate <file> checks your own against the schema.
Measured precision
Every HIGH/CRITICAL finding across a 10-repo public corpus (pyjwt,
paramiko, sigstore-python, age, go-jose, smallstep/crypto, …) was
human-adjudicated by reading the flagged line: 230 findings, 0 false
positives. Protocol, pinned SHAs, and verdicts are in tests/corpus/.
The honest caveat: explicit-call detection is precise by construction;
recall (what the scanner misses) is not yet measured — that is the next
corpus iteration.
Known limitations
- Findings carry no usage context yet: the policy cannot distinguish "RSA verifying a third-party webhook" from "RSA encrypting data at rest". Context-scoped rules are parsed but deliberately not shipped in the bundled policies until detectors emit context.
- No hybrid-scheme detection (X25519MLKEM768 reads as X25519).
- Insecure RNG usage (
math/randfor keys) is not detected yet. - Only the repo root's
.gitignore/.pqcheckignoreare honored. - Dependency findings are inventory (
introducesmetadata in the CBOM); they do not trip the policy gate in v0.1 — call sites do.
Development
Requires Python 3.12+ and uv:
uv sync --all-extras, then uv run pytest, uv run ruff check .,
uv run mypy. See CONTRIBUTING.md.
License
Apache-2.0. See SECURITY.md for the vulnerability disclosure process and the honest list of classical crypto this project itself transitively depends on.
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 Distributions
Built Distributions
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 pqcheck-0.0.1-py3-none-win_amd64.whl.
File metadata
- Download URL: pqcheck-0.0.1-py3-none-win_amd64.whl
- Upload date:
- Size: 4.2 MB
- Tags: Python 3, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5930cc896a85ead357ab8e712970e5b993ea8fb6228f5257f1f463f7a3b9a451
|
|
| MD5 |
55902b24e1b4a5ed552fe622e86b8e8e
|
|
| BLAKE2b-256 |
6c06ce53d67a89a017d2c7e441b464d9aa399f6ec453eb23e12116185e051f01
|
Provenance
The following attestation bundles were made for pqcheck-0.0.1-py3-none-win_amd64.whl:
Publisher:
cli-release.yml on Rafael-Ryu/pqcheck
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pqcheck-0.0.1-py3-none-win_amd64.whl -
Subject digest:
5930cc896a85ead357ab8e712970e5b993ea8fb6228f5257f1f463f7a3b9a451 - Sigstore transparency entry: 1792150561
- Sigstore integration time:
-
Permalink:
Rafael-Ryu/pqcheck@b4e661bd7a92f6e37100286eeb2c99e17bdbc180 -
Branch / Tag:
refs/tags/pqcheck-v0.0.1 - Owner: https://github.com/Rafael-Ryu
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
cli-release.yml@b4e661bd7a92f6e37100286eeb2c99e17bdbc180 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pqcheck-0.0.1-py3-none-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl.
File metadata
- Download URL: pqcheck-0.0.1-py3-none-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
- Upload date:
- Size: 4.1 MB
- Tags: Python 3, manylinux: glibc 2.28+ x86-64, manylinux: glibc 2.5+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
51c12e48675e8d8a06841a1e31dd4bb9dfdd47dbdfaa345f35bfb607d8266ff4
|
|
| MD5 |
ab9bb5fdb450626c478030b544cfce17
|
|
| BLAKE2b-256 |
4ffb0afd284fdf761658a788917bfead8755e711c1fcf35a5228240bb0a68e66
|
Provenance
The following attestation bundles were made for pqcheck-0.0.1-py3-none-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl:
Publisher:
cli-release.yml on Rafael-Ryu/pqcheck
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pqcheck-0.0.1-py3-none-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl -
Subject digest:
51c12e48675e8d8a06841a1e31dd4bb9dfdd47dbdfaa345f35bfb607d8266ff4 - Sigstore transparency entry: 1792150718
- Sigstore integration time:
-
Permalink:
Rafael-Ryu/pqcheck@b4e661bd7a92f6e37100286eeb2c99e17bdbc180 -
Branch / Tag:
refs/tags/pqcheck-v0.0.1 - Owner: https://github.com/Rafael-Ryu
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
cli-release.yml@b4e661bd7a92f6e37100286eeb2c99e17bdbc180 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pqcheck-0.0.1-py3-none-macosx_11_0_x86_64.whl.
File metadata
- Download URL: pqcheck-0.0.1-py3-none-macosx_11_0_x86_64.whl
- Upload date:
- Size: 4.2 MB
- Tags: Python 3, macOS 11.0+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0606297bc7c78ad5b0f37440f7ba1330321ce7e1ca0238cca60c2c35f2985d41
|
|
| MD5 |
26390f660d096eb317a599b7b8c14b0f
|
|
| BLAKE2b-256 |
3ae11afaf65fe60a9ff0916de009e69c6aeddf6b1f28cfc668f57ff352b2fdf5
|
Provenance
The following attestation bundles were made for pqcheck-0.0.1-py3-none-macosx_11_0_x86_64.whl:
Publisher:
cli-release.yml on Rafael-Ryu/pqcheck
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pqcheck-0.0.1-py3-none-macosx_11_0_x86_64.whl -
Subject digest:
0606297bc7c78ad5b0f37440f7ba1330321ce7e1ca0238cca60c2c35f2985d41 - Sigstore transparency entry: 1792150411
- Sigstore integration time:
-
Permalink:
Rafael-Ryu/pqcheck@b4e661bd7a92f6e37100286eeb2c99e17bdbc180 -
Branch / Tag:
refs/tags/pqcheck-v0.0.1 - Owner: https://github.com/Rafael-Ryu
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
cli-release.yml@b4e661bd7a92f6e37100286eeb2c99e17bdbc180 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pqcheck-0.0.1-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: pqcheck-0.0.1-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 3.9 MB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1fc4dba748b5e9b9bc953246cb5655fe000bd332bfe12159ad64feb27f1745f4
|
|
| MD5 |
3bed0c2991211e668fbb034583023a10
|
|
| BLAKE2b-256 |
f941c25d1bb0fa080667d97e4955d4cfc656fd8606384ea06f5aa0c7dabbcd47
|
Provenance
The following attestation bundles were made for pqcheck-0.0.1-py3-none-macosx_11_0_arm64.whl:
Publisher:
cli-release.yml on Rafael-Ryu/pqcheck
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pqcheck-0.0.1-py3-none-macosx_11_0_arm64.whl -
Subject digest:
1fc4dba748b5e9b9bc953246cb5655fe000bd332bfe12159ad64feb27f1745f4 - Sigstore transparency entry: 1792150852
- Sigstore integration time:
-
Permalink:
Rafael-Ryu/pqcheck@b4e661bd7a92f6e37100286eeb2c99e17bdbc180 -
Branch / Tag:
refs/tags/pqcheck-v0.0.1 - Owner: https://github.com/Rafael-Ryu
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
cli-release.yml@b4e661bd7a92f6e37100286eeb2c99e17bdbc180 -
Trigger Event:
push
-
Statement type: