Skip to main content

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/rand for keys) is not detected yet.
  • Only the repo root's .gitignore/.pqcheckignore are honored.
  • Dependency findings are inventory (introduces metadata 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

pqcheck-0.0.1-py3-none-win_amd64.whl (4.2 MB view details)

Uploaded Python 3Windows x86-64

pqcheck-0.0.1-py3-none-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl (4.1 MB view details)

Uploaded Python 3manylinux: glibc 2.28+ x86-64manylinux: glibc 2.5+ x86-64

pqcheck-0.0.1-py3-none-macosx_11_0_x86_64.whl (4.2 MB view details)

Uploaded Python 3macOS 11.0+ x86-64

pqcheck-0.0.1-py3-none-macosx_11_0_arm64.whl (3.9 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

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

Hashes for pqcheck-0.0.1-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 5930cc896a85ead357ab8e712970e5b993ea8fb6228f5257f1f463f7a3b9a451
MD5 55902b24e1b4a5ed552fe622e86b8e8e
BLAKE2b-256 6c06ce53d67a89a017d2c7e441b464d9aa399f6ec453eb23e12116185e051f01

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

File hashes

Hashes for pqcheck-0.0.1-py3-none-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
Algorithm Hash digest
SHA256 51c12e48675e8d8a06841a1e31dd4bb9dfdd47dbdfaa345f35bfb607d8266ff4
MD5 ab9bb5fdb450626c478030b544cfce17
BLAKE2b-256 4ffb0afd284fdf761658a788917bfead8755e711c1fcf35a5228240bb0a68e66

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pqcheck-0.0.1-py3-none-macosx_11_0_x86_64.whl.

File metadata

File hashes

Hashes for pqcheck-0.0.1-py3-none-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 0606297bc7c78ad5b0f37440f7ba1330321ce7e1ca0238cca60c2c35f2985d41
MD5 26390f660d096eb317a599b7b8c14b0f
BLAKE2b-256 3ae11afaf65fe60a9ff0916de009e69c6aeddf6b1f28cfc668f57ff352b2fdf5

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pqcheck-0.0.1-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pqcheck-0.0.1-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 1fc4dba748b5e9b9bc953246cb5655fe000bd332bfe12159ad64feb27f1745f4
MD5 3bed0c2991211e668fbb034583023a10
BLAKE2b-256 f941c25d1bb0fa080667d97e4955d4cfc656fd8606384ea06f5aa0c7dabbcd47

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page