pqcheck 0.7.2 → 0.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +165 -106
  2. package/bin/pqcheck.js +1 -1
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -1,78 +1,139 @@
1
1
  # pqcheck
2
2
 
3
- > **Public Surface Blast Radius scanner** — find out how much of your data unlocks when quantum decryption arrives.
3
+ > **Decryption Blast Radius scanner** — find out how much of your data unlocks when quantum decryption arrives.
4
4
 
5
5
  ```bash
6
- npx pqcheck chase.com
6
+ npx pqcheck stripe.com
7
7
  ```
8
8
 
9
- That's it. No install. Works from any terminal with Node 18+.
9
+ Zero install. Works in any terminal with Node 18+. Free, no signup, no API key.
10
+
11
+ The same scanner that powers [quantapact.com](https://quantapact.com), the browser extension, and the GitHub Action.
10
12
 
11
13
  ---
12
14
 
13
15
  ## What it does
14
16
 
15
- `pqcheck` scans any HTTPS domain and computes its **Decryption Blast Radius Score** — the first continuous metric for harvest-now-decrypt-later (HNDL) risk. Every other TLS scanner answers "is post-quantum cryptography enabled?" with a yes/no. `pqcheck` answers the question that actually matters: *if an adversary harvests this traffic today and decrypts it in 2035, how much past + future data unlocks?*
17
+ `pqcheck` scans any HTTPS domain and computes its **Decryption Blast Radius score** — the first continuous metric for harvest-now-decrypt-later (HNDL) risk. Every other TLS scanner answers "is post-quantum cryptography enabled?" with yes/no. `pqcheck` answers the question that actually matters: *if an adversary harvests this traffic today and decrypts it in 2035, how much past + future data unlocks?*
16
18
 
17
19
  The score combines (Quantum / cert findings — our differentiator):
18
20
  - **Public-key reuse across rotations** — detects when the same private key has been live across multiple cert renewals (often 4+ years at large enterprises). **★ Unique to pqcheck — no other ASM/TLS scanner surfaces this.**
19
21
  - **Cipher-class probing** — does the server accept RSA fallback even if it prefers ECDHE?
20
22
  - **Certificate chain analysis** — including the intermediate cert (the chain's actual quantum failure point)
21
23
  - **Subject scale** — wildcard certs and subdomain count multiplying the blast radius
24
+ - **Hybrid PQC TLS detection** — credits servers using `X25519MLKEM768` with a methodology-aware discount
22
25
 
23
- Plus a full ASM check suite for credibility (so the report doesn't feel narrow):
24
- - **Email security** — SPF, DMARC, DKIM (15 selectors probed), BIMI
25
- - **HTTP header security** — HSTS (with preload + max-age), CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy, COOP, CORP
26
- - **Subdomain takeover detection** — fingerprint-based scan against AWS S3, GitHub Pages, Heroku, Shopify, Fastly, and 5+ other commonly-orphaned services
26
+ Plus a full ASM check suite for credibility:
27
+ - **Email security** — SPF, DMARC, DKIM (~30 selectors probed including Resend/Mailgun/SES/etc.), BIMI
28
+ - **HTTP header security** — HSTS (with preload + max-age), CSP, X-Frame-Options, Referrer-Policy, Permissions-Policy, COOP, CORP
29
+ - **Subdomain takeover detection** — fingerprint-based scan against AWS S3, GitHub Pages, Heroku, Shopify, Fastly, etc.
27
30
 
28
- ## Example
31
+ ## Commands
29
32
 
30
33
  ```
31
- $ npx pqcheck chase.com
34
+ npx pqcheck <domain> Scan + print human-readable report
35
+ npx pqcheck lock <domain> Generate quantapact.lock (QXM) committable manifest
36
+ npx pqcheck deps <domain> Scan all third-party origins on the page (supply-chain HNDL)
37
+ npx pqcheck diff <old.lock> <new.lock> Compare two QXM lockfiles; exit 2 on regression
38
+ npx pqcheck history <domain> Show 90-day score history (sparkline + samples)
39
+ npx pqcheck cert <file.pem> Analyze a local PEM/CRT cert file (offline, no network)
40
+ ```
32
41
 
33
- chase.com
34
- ─────────────────────────────────────
35
- PUBLIC SURFACE BLAST RADIUS: 5.6 / 10 (MEDIUM)
42
+ ### Multi-domain
36
43
 
37
- Public surface signals:
38
- TLS: TLSv1.3 (TLS_AES_128_GCM_SHA256)
39
- Hybrid PQC: no
40
- • Cert expires: in 127 days
41
- • HSTS: not detected
42
- • Subdomains: 47 (wildcard cert)
44
+ ```
45
+ npx pqcheck a.com b.com c.com Multi-domain scan (positional)
46
+ npx pqcheck --file domains.txt Bulk scan from a newline-separated file (# comments allowed)
47
+ ```
43
48
 
44
- Findings:
45
- [HIGH] Same RSA-2048 key reused for 4.2 years across 3 cert rotations
46
- [HIGH] ECDHE-only — quantum-vulnerable key exchange
47
- [MED] Wildcard cert spans 47 subdomains
49
+ ### Output formats
48
50
 
49
- ⚠ This is the PUBLIC surface only.
50
- Internal Blast Radius is typically 12–40× the public score.
51
+ | Format | Use case |
52
+ |---|---|
53
+ | `--format text` *(default)* | Human-readable terminal output |
54
+ | `--format json` (or `--json`) | Raw JSON for piping; NDJSON for multi-domain |
55
+ | `--format markdown` | GitHub-issue / Slack-ready Markdown |
56
+ | `--format csv` | Spreadsheet-friendly CSV row |
57
+ | `--format sarif` | SARIF 2.1.0 for upload to GitHub Code Scanning |
58
+ | `--gh-action` | GitHub Actions `::notice/::warning/::error` annotations |
51
59
 
52
- Plain-English impact:
53
- If quantum decryption arrives in 2030–2040, harvested traffic from
54
- chase.com (US banks) would unlock 4.2 years of session data, across
55
- 47 subdomains under one wildcard cert.
60
+ ### Common flags
56
61
 
57
- Full report: https://quantapact.com/?check=chase.com
58
- ```
62
+ | Flag | Purpose |
63
+ |---|---|
64
+ | `-h`, `--help` | Show help |
65
+ | `-v`, `--version` | Show version |
66
+ | `--threshold <0-10>` | Exit 2 if score meets or exceeds this (CI gate) |
67
+ | `-q`, `--quiet` | Print only the numeric score |
68
+ | `--watch [seconds]` | Poll every N seconds (default 300) and report changes |
69
+ | `--webhook <url>` | POST scan results to a URL (one-shot or each watch tick) |
59
70
 
60
- ## Usage
71
+ ### Subcommand-specific flags
61
72
 
62
- ```
63
- npx pqcheck <domain> Scan and print human-readable report
64
- npx pqcheck lock <domain> Generate quantapact.lock (QXM artifact for repos)
65
- npx pqcheck <domain> --format json Output raw JSON for piping / scripting
66
- npx pqcheck <domain> --format markdown Output GitHub-issue / Slack-ready Markdown
67
- npx pqcheck <domain> --threshold 7 Exit 2 if score ≥ 7 (CI gate)
68
- npx pqcheck <domain> --quiet Print only the numeric score
69
- npx pqcheck <domain> --watch [seconds] Continuously poll and report changes
70
- npx pqcheck <domain> --webhook <url> POST results to a URL on each scan
71
- npx pqcheck --help Show all options
72
- npx pqcheck --version Show version
73
+ **`pqcheck deps`:**
74
+ - `--lock` Also write `quantapact-deps.lock` + `.md`
75
+ - `-o <dir>` Output directory for `--lock` files
76
+ - `--max=<N>` Max third parties to scan (default 20)
77
+ - `--allowlist <file>` Exit **3** if any third-party not in allowlist (CI vendor-risk gate)
78
+
79
+ **`pqcheck lock`:**
80
+ - `-o <dir>` Output directory
81
+ - `--stdout` Print JSON to stdout instead of writing files
82
+
83
+ **`pqcheck history`:**
84
+ - `--days <N>` — History window (default 90)
85
+ - `--json` — Raw JSON output
86
+
87
+ ### Exit codes
88
+
89
+ | Code | Meaning |
90
+ |---|---|
91
+ | `0` | Success |
92
+ | `1` | Usage / network / scan error |
93
+ | `2` | Score met or exceeded `--threshold`, or `diff` detected regression |
94
+ | `3` | Allowlist violation (`pqcheck deps --allowlist`) |
95
+
96
+ ## Examples
97
+
98
+ ```bash
99
+ # Quick scan
100
+ npx pqcheck stripe.com
101
+
102
+ # CI gate — fail if score >= 7
103
+ npx pqcheck mybank.com --threshold 7
104
+
105
+ # Generate committable QXM lockfile (like SBOM, but for quantum exposure)
106
+ npx pqcheck lock mycompany.com
107
+
108
+ # Track posture changes in PRs by diffing lockfiles
109
+ npx pqcheck diff main.lock pr.lock
110
+
111
+ # Supply-chain HNDL — scan all third-party scripts/iframes on a page
112
+ npx pqcheck deps mycompany.com --lock
113
+
114
+ # Vendor-risk CI gate — fail PR if any third-party not in allowlist
115
+ npx pqcheck deps mycompany.com --allowlist allowed-vendors.txt
116
+
117
+ # Score history sparkline
118
+ npx pqcheck history mycompany.com
119
+
120
+ # Offline cert analysis (no network)
121
+ npx pqcheck cert ./mycert.pem
122
+
123
+ # Bulk scan from list, NDJSON output
124
+ npx pqcheck --file domains.txt --format json > scans.ndjson
125
+
126
+ # Upload findings to GitHub Code Scanning
127
+ npx pqcheck mybank.com --format sarif > pqcheck.sarif
128
+
129
+ # GitHub Actions inline PR annotations
130
+ npx pqcheck mybank.com --gh-action
131
+
132
+ # Watch mode — poll, alert via webhook on change
133
+ npx pqcheck mybank.com --watch 600 --webhook https://hooks.slack.com/...
73
134
  ```
74
135
 
75
- ### QXM — Quantum Exposure Manifest (commit-able to your repo)
136
+ ### QXM — Quantum Exposure Manifest
76
137
 
77
138
  Like SBOM, `package-lock.json`, or `cargo audit` outputs — track quantum exposure as a versioned artifact in your repo. Diffs surface real changes in pull requests.
78
139
 
@@ -83,97 +144,95 @@ npx pqcheck lock yourcompany.com
83
144
  # quantapact-report.md — human-readable summary (renders on GitHub)
84
145
  ```
85
146
 
86
- Commit both files. Re-run `npx pqcheck lock` whenever you want to refresh; the diff in the next PR shows what changed (score, findings, key-reuse window).
147
+ Commit both files. Use `npx pqcheck diff old.lock new.lock` in CI to surface regressions in PR comments.
87
148
 
88
- **In CI:**
149
+ Schema documented at [quantapact.com/schemas/qxm/v1](https://quantapact.com/methodology/qxm).
89
150
 
90
- ```yaml
91
- - name: Refresh QXM lockfile
92
- run: npx pqcheck@latest lock yourcompany.com
93
- - name: Fail if score regressed
94
- run: npx pqcheck@latest yourcompany.com --threshold 7
151
+ ### Supply-chain dependency scanning
152
+
153
+ ```bash
154
+ npx pqcheck deps stripe.com
155
+ # Output: every third-party origin on stripe.com (analytics, CDN, fonts, etc.) graded for quantum risk
95
156
  ```
96
157
 
97
- The lockfile schema is documented at [quantapact.com/schemas/qxm/v1](https://quantapact.com/methodology) and is intended to be stable across CLI versions.
158
+ Add `--lock` to write `quantapact-deps.lock` + `.md` for committing or PR comparison. Add `--allowlist file.txt` to gate CI on vendor approval.
98
159
 
99
- ### Exit codes
160
+ ## Companion surfaces
100
161
 
101
- | Code | Meaning |
102
- |------|---------|
103
- | 0 | Success — score below threshold (or no threshold set) |
104
- | 1 | Usage / network / scan error |
105
- | 2 | Score met or exceeded `--threshold` |
162
+ This CLI is one of four ways to consume the [Decryption Blast Radius API](https://quantapact.com/api):
106
163
 
107
- ### CI integration
164
+ | Surface | Where |
165
+ |---|---|
166
+ | **CLI** (this package) | `npx pqcheck` |
167
+ | **Browser extension** | Chrome Web Store / Firefox AMO / Edge — toolbar badge per tab + dependency analysis |
168
+ | **GitHub Action** | [`quantapact/pqcheck/action@main`](https://github.com/quantapact/pqcheck/tree/main/action) — PR comments, SARIF upload, lockfile generation |
169
+ | **Slack `/pqcheck`** | [Install on workspace](https://quantapact.com/install-slack) |
170
+ | **Web** | [quantapact.com](https://quantapact.com) — share-friendly URLs at `/r/<domain>` |
108
171
 
109
- The `--threshold` flag turns `pqcheck` into a quantum-risk gate for any pipeline:
172
+ ## Public API
110
173
 
111
- ```yaml
112
- # .github/workflows/quantum-risk-gate.yml
113
- - name: Check public-surface quantum-decryption risk
114
- run: npx pqcheck mycompany.com --threshold 7
115
- ```
116
-
117
- If the score is 7.0 or higher, the step fails and the PR can't merge.
174
+ `pqcheck` is a wrapper around the public Quantapact API. You can also call the API directly:
118
175
 
119
- For GitHub Actions specifically, there's also a [first-class action](https://github.com/mzon7/quantapact/tree/main/action) with `score` / `grade` / `report-url` outputs:
120
-
121
- ```yaml
122
- - uses: mzon7/quantapact/action@main
123
- with:
124
- domain: mycompany.com
125
- threshold: '7'
176
+ ```bash
177
+ curl -s "https://www.quantapact.com/api/scan?domain=stripe.com" | jq '.grade, .score'
126
178
  ```
127
179
 
128
- For finer control, combine `--quiet` with shell logic:
180
+ Full API reference at [quantapact.com/api](https://quantapact.com/api).
129
181
 
130
- ```bash
131
- SCORE=$(npx pqcheck mybank.com --quiet)
132
- echo "Public surface blast radius: $SCORE / 10"
133
- ```
182
+ **Rate limit:** ~60 requests/minute per IP. No API key required. Returns HTTP 429 if exceeded — back off and retry.
134
183
 
135
- Or grab the full JSON for richer analysis:
184
+ ## Methodology
136
185
 
137
- ```bash
138
- npx pqcheck mybank.com --format json | jq '.findings[] | select(.severity=="high")'
139
- ```
186
+ Decryption Blast Radius scoring methodology is fully open. Component weights, PQC discount math, the "what we DON'T claim" sections, edge cases — all documented:
140
187
 
141
- ## Web version
188
+ - [Decryption Blast Radius](https://quantapact.com/methodology/decryption-blast-radius) — core methodology
189
+ - [Score components](https://quantapact.com/methodology/score-components) — the 4-bar weighted breakdown + PQC discount
190
+ - [QXM lockfile schema](https://quantapact.com/methodology/qxm) — committable manifest format
191
+ - [Browser extension methodology](https://quantapact.com/methodology/browser-extension) — supply-chain HNDL detection logic
192
+ - [Methodology library](https://quantapact.com/methodology) — full index
142
193
 
143
- Same scanner, browser-friendly UI: **[quantapact.com](https://quantapact.com)**
194
+ ## Versioning + stability
144
195
 
145
- Shareable per-domain reports at `quantapact.com/r/<domain>` the URL unfurls in Twitter / Slack / LinkedIn with a dynamically-generated card showing the grade.
196
+ We don't break the API contract. New fields are added; old fields are preserved. If we ever need a breaking change, it ships at `/api/v2/scan` with a deprecation timeline.
146
197
 
147
- ## Public leaderboard
198
+ The CLI follows the same policy — output formats are stable across minor versions.
148
199
 
149
- Sector rankings updated nightly across:
200
+ ## Privacy
150
201
 
151
- - US Banks (20 peers)
152
- - US Healthcare Systems (20 peers)
153
- - Major SaaS / Cloud Platforms (30 peers)
154
- - US Federal Government (25 peers)
155
- - Major EU & UK Banks (25 peers)
156
- - US Defense Contractors (15 peers)
157
- - Global Automakers (15 peers)
158
- - Global News & Media (15 peers)
159
- - US Telecom & ISPs (15 peers)
160
- - US Airlines (10 peers)
161
- - UK Government & Public Services (15 peers)
202
+ `pqcheck` sends the domain you scan to `quantapact.com/api/scan` (so the TLS handshake can be performed from the public internet). No other data is sent — no email, no client-side identifier. The server logs anonymized analytics: domain, hashed IP (for rate limiting), user-agent. We don't track individual users across scans. See [quantapact.com/privacy](https://quantapact.com/privacy).
162
203
 
163
- **[quantapact.com/leaderboard.html](https://quantapact.com/leaderboard.html)**
204
+ ## CI integration
164
205
 
165
- ## Methodology
206
+ ```yaml
207
+ # .github/workflows/quantum-risk-gate.yml
208
+ - name: Quantapact public-surface gate
209
+ run: npx pqcheck@latest mycompany.com --threshold 7
210
+ ```
166
211
 
167
- The Decryption Blast Radius scoring methodology is fully open and documented at **[quantapact.com/methodology](https://quantapact.com/methodology)**. Citable; methodology paper coming soon.
212
+ For richer integration (sticky PR comments, SARIF upload to Code Scanning, lockfile diff on regression), use the [GitHub Action](https://github.com/quantapact/pqcheck/tree/main/action):
168
213
 
169
- ## Privacy
214
+ ```yaml
215
+ - uses: quantapact/pqcheck/action@main
216
+ with:
217
+ domain: mycompany.com
218
+ threshold: '7'
219
+ comment-on-pr: 'true'
220
+ generate-sarif: 'true'
221
+ - uses: github/codeql-action/upload-sarif@v3
222
+ with:
223
+ sarif_file: pqcheck-results.sarif
224
+ ```
225
+
226
+ ## Disclaimer
170
227
 
171
- `pqcheck` sends the domain you scan to the Quantapact API (so the actual TLS handshake can be performed from the public internet). No other data is sent no email, no IP-tied identifier, nothing client-side. The server-side `/api/scan` endpoint stores anonymous scan results in a 30-minute cache to avoid duplicate scans of the same domain. See [quantapact.com/privacy](https://quantapact.com/privacy) for full details.
228
+ `pqcheck` measures only the **public** surface of a domain what's observable from the open internet. Internal Blast Radius (east-west traffic, internal databases, VPN tunnels, backup pipelines) is typically 12–40× the public score depending on sector. A passing public-surface grade does **not** mean low internal exposure.
172
229
 
173
230
  ## License
174
231
 
175
232
  MIT. © 2026 Quantapact.
176
233
 
177
- ## Disclaimer
234
+ ---
178
235
 
179
- `pqcheck` measures only the **public** surface of a domain — what's observable from the open internet. Internal Blast Radius (east-west traffic, internal databases, VPN tunnels, backup pipelines) is typically 12–40× the public score depending on sector. A passing public-surface grade does **not** mean low internal exposure.
236
+ **Source:** [github.com/quantapact/pqcheck](https://github.com/quantapact/pqcheck) *(public, pending org transfer to `quantapact/pqcheck`)*
237
+
238
+ **Issues / feedback:** [quantapact.com/feedback](https://quantapact.com/feedback) or open an issue on the repo.
package/bin/pqcheck.js CHANGED
@@ -7,7 +7,7 @@
7
7
  // =============================================================================
8
8
 
9
9
  const API_BASE = process.env.PQCHECK_API_BASE || "https://quantapact.com";
10
- const VERSION = "0.7.2";
10
+ const VERSION = "0.7.3";
11
11
 
12
12
  const ANSI = {
13
13
  reset: "\x1b[0m",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pqcheck",
3
- "version": "0.7.2",
3
+ "version": "0.7.3",
4
4
  "description": "Decryption Blast Radius scanner — find out how much of your data unlocks when quantum decryption arrives.",
5
5
  "keywords": [
6
6
  "post-quantum",
@@ -21,7 +21,7 @@
21
21
  "bugs": "https://quantapact.com",
22
22
  "repository": {
23
23
  "type": "git",
24
- "url": "https://github.com/mzon7/quantapact.git",
24
+ "url": "https://github.com/quantapact/pqcheck.git",
25
25
  "directory": "cli"
26
26
  },
27
27
  "license": "MIT",