Scan for Quantum-Vulnerable Crypto in GitHub Actions CI
Inventory your RSA and ECDH, gate the pull request, and baseline the rest — with a copy-paste workflow.
How to Find and Block Quantum-Vulnerable Cryptography in CI with GitHub Actions
You probably have RSA and ECDH scattered across your codebase and no map of where. Here’s a step-by-step way to inventory it — and stop new quantum-vulnerable crypto from getting merged — with a GitHub Actions workflow you can copy today.
If you’ve been told to “get ready for post-quantum” and don’t know where to start, this guide is the practical answer. By the end you’ll have three things: a map of where your code uses quantum-vulnerable cryptography, a CI gate that stops new instances from being merged, and a way to do it on a legacy repo without turning your whole build red. Every command runs today on the open-source, zero-dependency quantakrypto tools.
The problem
Somebody — an auditor, a customer security questionnaire, a CISO who read the NIST headlines — has started asking about post-quantum readiness. And the honest answer for most teams is: we don’t actually know where our quantum-vulnerable crypto is.
Two things make that a real problem, not a someday problem:
- The clock is already running. The threat is harvest-now, decrypt-later (HNDL): an adversary records your encrypted traffic today and stores it until a quantum computer can break the classical asymmetric algorithms — RSA, (EC)DH, ECDSA, EdDSA — protecting it. Anything with a long confidentiality lifetime (health records, legal data, long-lived keys) is exposed now, even though decryption happens years out.
- The standards are final, so this is on you. NIST published its first post-quantum algorithms in 2024 — ML-KEM (FIPS 203) for key exchange, ML-DSA (FIPS 204) and SLH-DSA (FIPS 205) for signatures. This is now an engineering task, not a research question.
Underneath, it’s really two problems. First, you can’t see where your quantum-vulnerable crypto lives — it’s spread across your own code and your dependencies. Second, even if you cleaned it up today, every new pull request quietly adds more. You need to solve both. Here’s how, in four steps.
Step 1 — See where you actually stand
Before you can fix anything, you need a map. Run the scanner against your repo — nothing to install:
npx @quantakrypto/qscan ./
You get a report of every quantum-vulnerable construct with its file and line, plus a 0–100 readiness score (0 is worst, 100 means no classical asymmetric crypto was found) — a single number you can trend over time or put on a README badge. The scanner covers inline crypto in 8 languages — JavaScript/TypeScript, Python, Go, Java/Kotlin, C#/.NET, Rust, Ruby, and C/C++ (OpenSSL) — plus PEM/SSH key material, TLS config, and dependency manifests across npm, PyPI, Cargo, Go modules, Maven, and RubyGems.
One honest caveat worth knowing up front: if the scan walks your files but finds nothing in a language it can read, it will not hand you a bare 100/100 — vulnerable code may simply live in a language it can't parse yet, so it tells you how many files it actually analyzed. Trust the inventory, not just the headline number.
Want a shareable, machine-readable inventory instead of terminal output? Emit a CycloneDX cryptographic bill of materials (CBOM) — one entry per (algorithm, primitive) with file:line evidence:
npx @quantakrypto/qscan . --cbom -o quantakrypto-cbom.json
That’s your answer to “where is our quantum-vulnerable crypto?” — in about a minute.
Step 2 — Stop the pile from growing
Knowing where you stand is worthless if the number keeps climbing behind you. This is the core of the fix: a CI check that scans every pull request and blocks new quantum-vulnerable crypto from being merged.
Create .github/workflows/pqc.yml. It scans on every PR and push to main, writes a SARIF report, and uploads it to GitHub code scanning so findings land in the Security tab:
name: Quantum Readiness
on:
pull_request:
push:
branches: [main]
permissions:
contents: read
security-events: write # required to upload SARIF to code scanning
jobs:
quantakrypto:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: quantakrypto — Quantum Readiness Scan
id: quantakrypto
uses: quantakrypto/pqc-tools/packages/action@v1
with:
path: "."
severity-threshold: "high"
fail-on-findings: "true"
format: "sarif"
output: "quantakrypto.sarif.json"
# Upload to GitHub code scanning (Security tab). Runs even if the scan failed.
- name: Upload SARIF
if: always()
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: ${{ steps.quantakrypto.outputs.sarif-file }}
The parts that matter:
permissions: security-events: writeis what lets the follow-up step push SARIF into code scanning — without it the upload fails. (See GitHub's SARIF upload docs.)severity-threshold: "high"means only findings athighorcriticalfail the build (ordering, most to least severe:critical > high > medium > low > info). Everything below is reported, never blocking.fail-on-findings: "true"makes the job exit non-zero when a blocking finding survives. Start with"false"if you want report-only while you get your bearings.if: always()on the upload is deliberate — you want the findings in the Security tab especially when the scan failed the job.
Now every reviewer sees quantum-vulnerable constructs as first-class code-scanning alerts, annotated inline on the exact line of the diff that introduced them. New debt stops here.
Step 3 — Don’t drown in existing debt
Here’s the wall most teams hit: turn fail-on-findings on against a mature repo and you light up hundreds of findings for crypto that's been there for years. Blocking all of it is useless — you want to stop new debt, not the existing pile.
The fix is a baseline: a small JSON file of the findings you’ve already accepted ({ "version": 1, "fingerprints": [ … ] }). Each fingerprint is a line-insensitive hash of the rule, file, and normalized snippet, so reformatting or moving code around doesn't resurface old findings. Anything in the baseline is suppressed; only genuinely new quantum-vulnerable crypto can fail the build.
Generate it once, on a clean main:
npx @quantakrypto/qscan . --write-baseline .quantakrypto/baseline.json
Commit that file and point the Action at it:
- name: quantakrypto — Quantum Readiness Scan
id: quantakrypto
uses: quantakrypto/pqc-tools/packages/action@v1
with:
path: "."
severity-threshold: "high"
fail-on-findings: "true"
baseline: ".quantakrypto/baseline.json"
From now on, PRs fail only when they introduce new findings. Every time you remediate something, re-run --write-baseline to shrink the accepted set — a visible, ratcheting record of progress. (The baseline format is shared between the CLI and the Action, so a file written locally is honored byte-for-byte in CI.)
That’s the whole adoption story: gate the growth, grandfather the past, chip away at the middle.
Step 4 — Turn findings into a plan (optional)
Finding the crypto is step one of migration, not the whole job. Two features bridge from “found it” to “here’s what to do about it.”
A migration-plan PR comment. Before you’re ready to gate at all, run the Action in advisory mode — it posts a deterministic, prioritized PQC migration plan as a pull-request comment and never fails the job. A gentle on-ramp for a team that isn’t ready to block builds yet:
- name: quantakrypto — Migration plan comment
uses: quantakrypto/pqc-tools/packages/action@v1
with:
mode: "comment-plan"
path: "."
comment-pr: "true"
github-token: ${{ github.token }}
(This one needs permissions: pull-requests: write.)
A CBOM for the auditor who started all this. The same --cbom output from Step 1 is exactly what compliance and supply-chain tooling wants — and it's deterministic (sorted components, stable serial number), so an unchanged tree produces a byte-identical file. Archive it as a build artifact and you have dated, reproducible evidence of your crypto posture:
- name: Generate CBOM
run: npx @quantakrypto/qscan . --cbom -o quantakrypto-cbom.json
- uses: actions/upload-artifact@v4
with:
name: quantakrypto-cbom
path: quantakrypto-cbom.json
More on the format at CycloneDX CBOM.
Running it outside GitHub
The gate lives in CI, but the same scanner runs anywhere — same findings, same score. On a big repo, scan only what changed instead of the whole tree:
# Files changed in your working tree.
npx @quantakrypto/qscan . --changed
# Everything changed since a base ref — e.g. the PR base.
npx @quantakrypto/qscan . --changed --since origin/main
The exit code is threshold-driven (0 clean, 1 findings at/above threshold, 2 usage error), so it drops into GitLab CI, Jenkins, a pre-commit hook, or any other runner — not just GitHub Actions.
When you start actually migrating
Once you move past inventory into fixing, two more pieces help. MCP (@quantakrypto/mcp) is a Model Context Protocol server that hands your AI coding agent the same post-quantum tools — scan, inventory, explain, suggest-hybrid — so it can reason about crypto exposure while it edits (claude mcp add quantakrypto npx @quantakrypto/mcp). Sieve (@quantakrypto/sieve) is a conformance battery for ML-KEM, ML-DSA, and SLH-DSA implementations — for checking the new crypto you migrate to. Everything is Apache-2.0, has zero runtime dependencies, and ships to npm with build provenance.
Where this leaves you
Four steps in, the vague “get ready for post-quantum” mandate has turned into something concrete: you know where your quantum-vulnerable crypto is, you’ve stopped new instances from merging, you’ve grandfathered the legacy pile so CI stays useful, and you can hand an auditor a dated CBOM. That’s a real starting position — and it took a workflow file and a one-line scan, not a migration project.
Start by running npx @quantakrypto/qscan ./ on your largest repo to get today's number, then drop the Step 2 workflow into .github/workflows/ to keep it from getting worse.
Links
- Repo: github.com/quantakrypto/pqc-tools
- npm: @quantakrypto/qscan · the quantakrypto org
- GitHub code scanning / SARIF: uploading a SARIF file
- NIST standards: FIPS 203 · FIPS 204 · FIPS 205
- CycloneDX CBOM: cyclonedx.org/capabilities/cbom
- quantakrypto: site · blog · book a readiness audit
Everything above runs on the published tools today. qScan’s remediation and richer evidence formats are actively evolving — newer detectors and outputs are landing in an upcoming release.

메타데이터
- post_id
- 2c152052cfa4
- slug
- scan-for-quantum-vulnerable-crypto-in-github-actions-ci-2c152052cfa4
- url
- https://medium.com/quantakrypto/scan-for-quantum-vulnerable-crypto-in-github-actions-ci-2c152052cfa4
- canonical_url
- https://medium.com/quantakrypto/scan-for-quantum-vulnerable-crypto-in-github-actions-ci-2c152052cfa4
- author_url
- https://medium.com/@leonacosta
- status
- ok
- fetched_at
- 2026-07-17 15:39:32