Introducing the PostQ CLI
Quantum-risk scanning that fits in your terminal, your CI pipeline, and a 2 MB binary.
We cut v0.1.0 of the PostQ CLI — a single static binary you can install with brew install PostQDev/tap/postq. Point it at any hostname and you get a real TLS handshake, a full certificate-chain walk, and a list of every algorithm that’s going to be a liability the day a sufficiently large quantum computer shows up. Total time: usually under 100 ms.
This post is a quick tour of why the CLI exists, what it actually does today, and where we’re taking it next.
Why a CLI, when we already have a web scanner?
The PostQ web scanner is great for one-off checks and for teams that live in a dashboard. But three things kept coming up in conversations with engineers actually doing the migration work:
- “Can I run it in CI?” Their security team wanted a hard gate that blocks PRs introducing new RSA-2048 endpoints. A web tool doesn’t fit there.
- “Can it run inside our VPC?” A lot of the interesting hosts are private. They aren’t going to punch holes in their firewall so a SaaS scanner can poke them.
- “Can I script it?” Engineers want to feed it a list of 400 hosts from an internal inventory tool, fan out, and dump JSON into something downstream.
A CLI is the obvious answer to all three. The not-so-obvious part was how to ship it without making it painful to install.
Constraints we picked
Before writing a line of code, we wrote down a few rules to keep us honest:
- Stdlib only.No external Go dependencies. None. Every time we’ve added “just one library” to a CLI, we’ve regretted it within a year. Go’s standard library has a perfectly good
crypto/tls,encoding/json, andnet/http. That’s most of what a scanner needs. - CGO disabled. Means fully static binaries. Means it runs in distroless, scratch, Lambda, and the weird Alpine container someone’s still using in 2025.
- Cold start under 100 ms. We want this thing to feel snappy in CI. JVM-based scanners take longer to boot than ours takes to scan five hosts.
- Exit codes are a contract.
0= clean,1= error,2= found Critical or High. We’ll bend on a lot of things, but not this. People wire those numbers into pipelines.
The result: a 2 MB binary that does one thing well and shuts up the rest of the time.
What v0.1 actually does
Two commands. That’s the whole surface area.
postq scan url example.com api.example.com www.example.com \
--concurrency 5For each host, the CLI opens a TCP connection, performs a real TLS handshake (no string-matching nonsense), pulls down the full certificate chain, and analyzes:
- The negotiated cipher suite and TLS version
- The leaf cert’s public key algorithm and size (RSA-2048, P-256, etc.)
- The certificate’s signature algorithm — this one catches a lot of people, since you can have a “modern” ECDSA cert that’s still signed with SHA1-RSA somewhere up the chain
- Expiry, issuer, subject, SANs
Each finding gets a severity, a short explanation of why it’s a problem, and a concrete fix recommendation. Output looks roughly like this:
PostQ scan — example.com:443
Risk score: 100/100 (Critical)
Findings: 6
[CRITICAL] ECDSA public key (P-256)
Elliptic-curve discrete log is broken in polynomial time by Shor's algorithm.
fix: Migrate to ML-DSA (CRYSTALS-Dilithium) for signatures.
[HIGH ] Quantum-vulnerable signature algorithm (SHA256-RSA)
The certificate signature itself is quantum-vulnerable. Even with PQ key
exchange, a quantum attacker could forge certificates.
fix: Issue replacement certificate signed with ML-DSA.
Took 64msAdd --json for machine-readable output, or --no-upload to keep everything local. Findings get pushed to your PostQ dashboard by default so the rest of your team can see them, but the CLI works totally offline if you’d rather it didn’t phone home.
The other command is postq scan list, which pulls the recent scans from your org so you can grep through history without leaving the terminal.
One trick we’re proud of
The exit code thing is small but matters. If you drop this into a GitHub Actions workflow:
- name: Scan public endpoints
run: |
brew install PostQDev/tap/postq
postq scan url \
api.mycompany.com \
www.mycompany.com \
auth.mycompany.com...the job fails the moment a Critical or High shows up. No custom jq-parsing, no glue scripts, no “wait did the job pass because it was clean or because the scanner crashed?”. We’ve seen enough security tools that swallow errors and exit 0. Not this one.
What’s next
v0.1 is intentionally narrow: TLS endpoints, nothing else. Here’s what shipped next and what we’re still working on, in roughly the order we’re landing it:
postq scan code <path>— static analysis of source code for hardcoded RSA, ECDSA, MD5, weak TLS configs, and forgotten OpenSSL one-liners. Useful for finding the crypto your app is doing internally, not just on the wire.postq scan k8s— walk a kubeconfig and check every TLS Secret, Ingress certificate, and service-mesh mTLS policy in the cluster.postq scan cloud aws,scan cloud azure,scan cloud gcp— enumerate KMS keys, ACM/Key Vault certs, load balancers, secret stores. The cloud providers each have their own “this key uses RSA-2048” story. We’ll roll it up.- SARIF, JUnit, and CSV outputs — so you can pipe results straight into GitHub code scanning, Jenkins reports, or whatever spreadsheet your compliance team insists on.
postq signandpostq verify— the same hybrid signing operations our SDKs support, but from the command line. Good for CI artifact signing.
The interactive shell is now there when you run postq locally. The one-shot commands stay invisible in CI and unmissable when they find something.
Try it
# macOS / Linux
brew install PostQDev/tap/postq
postq
# Anywhere with Go ≥ 1.23
go install github.com/postqdev/postq-cli/cmd/postq@latest
postq
# Or grab a binary directly
# https://github.com/PostQDev/postq-cli/releasesContact us to grab an API key, then run the shell:
postq
# then inside the shell:
scan url example.comSource is on GitHub. Issues, feature requests, and weird edge cases all welcome — especially the weird edge cases. PRs too, if you’re feeling generous.
We’re going to write more posts like this as we ship things. Next up: a deep-dive on what “hybrid signing” actually means in practice, and why dual-signing every artifact for the next decade is going to be the new normal.