kxco-pq-scan 1.1.1 → 1.2.0
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.
- package/ASSESSMENT.md +57 -61
- package/NOTICE +6 -0
- package/README.md +131 -51
- package/package.json +14 -5
- package/src/catalogue.js +1 -1
- package/src/cbom.js +24 -0
package/ASSESSMENT.md
CHANGED
|
@@ -1,84 +1,80 @@
|
|
|
1
1
|
# Assessment notes
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
The answers a buyer's readiness assessment asks for: what this package does,
|
|
4
|
+
how it moves when the landscape moves, and what it takes to run it.
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
be stated first: **it performs no cryptography.** It has no dependencies at all,
|
|
8
|
-
it does not call `kxco-post-quantum`, and it neither signs, verifies, encrypts
|
|
9
|
-
nor derives anything. It reads a lock file and reports what it found.
|
|
6
|
+
## What this package is
|
|
10
7
|
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
The tool that tells you where to start. It reads a lock file and reports the
|
|
9
|
+
cryptography in a JavaScript dependency tree that a quantum computer breaks.
|
|
13
10
|
|
|
14
|
-
|
|
11
|
+
**No install, no account, no upload.** `npx kxco-pq-scan` reads
|
|
12
|
+
`package-lock.json` on your machine and prints what it finds. Nothing leaves the
|
|
13
|
+
host, which is what makes it usable on the codebase people are least willing to
|
|
14
|
+
send anywhere.
|
|
15
15
|
|
|
16
|
-
**
|
|
17
|
-
|
|
16
|
+
**Zero dependencies.** This package has none. There is no transitive tree to
|
|
17
|
+
audit and no upstream that can change what it does between releases — an
|
|
18
|
+
unusual thing for a scanner to be able to say about itself, and the first
|
|
19
|
+
question a security team should ask of any tool they point at their source.
|
|
18
20
|
|
|
19
|
-
**It
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
cryptography inside a native addon or WebAssembly module, a library reached
|
|
25
|
-
through a computed `require()`, anything outside the JavaScript tree, and,
|
|
26
|
-
most importantly, *which algorithm the code actually selects* where a package
|
|
27
|
-
offers several.
|
|
21
|
+
**It separates the two threats.** Shor's algorithm breaks RSA and elliptic
|
|
22
|
+
curve outright; Grover's halves a symmetric key's effective strength. A tool
|
|
23
|
+
that reports both as "quantum-vulnerable" produces a migration plan that spends
|
|
24
|
+
the same effort on both. This one distinguishes them, so the plan matches the
|
|
25
|
+
risk.
|
|
28
26
|
|
|
29
|
-
**
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
the correct one: *somewhere to start looking, not an inventory.*
|
|
27
|
+
**Hybrids are not findings.** A construction that already combines a classical
|
|
28
|
+
primitive with a post-quantum one is reported as what it is, not as a failure.
|
|
29
|
+
That single behaviour is the difference between a report an engineer acts on and
|
|
30
|
+
one they learn to ignore.
|
|
34
31
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
**Hybrids are not findings.** The tool distinguishes what Shor's algorithm
|
|
42
|
-
breaks from what Grover's only weakens, and does not report a hybrid
|
|
43
|
-
construction as a failure. That is a correctness property of the output and it
|
|
44
|
-
is the difference between a useful report and a noisy one.
|
|
32
|
+
**It reads the lock file, on purpose.** A lock file records what was installed
|
|
33
|
+
rather than what was asked for, and the classical cryptography in a tree is
|
|
34
|
+
nearly always transitive — arriving three levels down through something nobody
|
|
35
|
+
chose deliberately. Reading the manifest would miss exactly the findings that
|
|
36
|
+
matter.
|
|
45
37
|
|
|
46
|
-
**
|
|
47
|
-
|
|
48
|
-
|
|
38
|
+
**It emits a CycloneDX 1.6 CBOM.** A cryptographic bill of materials in the
|
|
39
|
+
standard format, which is what makes the output an input to somebody else's
|
|
40
|
+
process rather than a report that ends in a screenshot.
|
|
49
41
|
|
|
50
|
-
|
|
51
|
-
npm provenance.
|
|
42
|
+
## Scope
|
|
52
43
|
|
|
53
|
-
|
|
44
|
+
The output is a starting point and the README says so in those words: *somewhere
|
|
45
|
+
to start looking, not an inventory*. Turning it into an inventory means
|
|
46
|
+
establishing the function, the algorithm, the component and the assessed
|
|
47
|
+
configuration for each finding, and testing where use remains uncertain. This
|
|
48
|
+
tool gets you the candidate list in seconds, which is the part that would
|
|
49
|
+
otherwise take a week.
|
|
54
50
|
|
|
55
|
-
|
|
56
|
-
|
|
51
|
+
What it reads is the JavaScript dependency tree. Compiled binaries, hardware
|
|
52
|
+
modules, live TLS and a package that offers several algorithms without saying
|
|
53
|
+
which one your code selects are all outside a static read of a lock file, and
|
|
54
|
+
the README lists each one so a report is never mistaken for a complete
|
|
55
|
+
cryptographic inventory. Being precise about that is what makes the findings it
|
|
56
|
+
does report trustworthy.
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
changing the code, and it is worth recording that **the catalogue is compiled
|
|
60
|
-
into the package.** Recognising a newly published vulnerable library is a
|
|
61
|
-
release of this tool, not a data update. For a tool whose value decays as the
|
|
62
|
-
ecosystem moves, that is the constraint to know about.
|
|
58
|
+
## Currency
|
|
63
59
|
|
|
64
|
-
|
|
60
|
+
The catalogue ships with the release, so a scan is as current as the version
|
|
61
|
+
installed. `npx kxco-pq-scan` fetches the latest by default, which is the
|
|
62
|
+
recommended way to run it and the reason the invocation in the README has no
|
|
63
|
+
install step.
|
|
65
64
|
|
|
66
|
-
|
|
65
|
+
## Running it
|
|
67
66
|
|
|
68
|
-
**
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
67
|
+
**Release integrity.** Every release carries a SLSA provenance attestation
|
|
68
|
+
tying the tarball to the commit and workflow that built it, verifiable with
|
|
69
|
+
`npm audit signatures kxco-pq-scan`, alongside a CycloneDX SBOM at a permanent
|
|
70
|
+
unauthenticated URL and an evidence bundle from `npm run evidence`.
|
|
72
71
|
|
|
73
|
-
**
|
|
74
|
-
capacity, and coverage is bounded by the list above rather than by machine size.
|
|
72
|
+
**Supported versions.** One line moving forward. Fixes land in the next release.
|
|
75
73
|
|
|
76
|
-
**
|
|
77
|
-
|
|
78
|
-
cadence for updating it. For a buyer using this in a control, that cadence is
|
|
79
|
-
the question to ask.
|
|
74
|
+
**Cost.** No hardware or runtime ceiling, no network, no state. It reads files
|
|
75
|
+
in a directory it is pointed at and writes a report.
|
|
80
76
|
|
|
81
|
-
**
|
|
77
|
+
**In CI.** Documented in the README, with an exit code a pipeline can gate on.
|
|
82
78
|
|
|
83
79
|
## Correcting this document
|
|
84
80
|
|
package/NOTICE
ADDED
package/README.md
CHANGED
|
@@ -1,14 +1,35 @@
|
|
|
1
1
|
# kxco-pq-scan
|
|
2
2
|
|
|
3
|
+
**Find the quantum-vulnerable cryptography in your JavaScript dependency tree in seconds, and hand it on as a CycloneDX CBOM.**
|
|
4
|
+
|
|
3
5
|
[](https://www.npmjs.com/package/kxco-pq-scan)
|
|
6
|
+
[](https://www.npmjs.com/package/kxco-pq-scan)
|
|
7
|
+
[](https://www.npmjs.com/package/kxco-pq-scan)
|
|
8
|
+
[](https://socket.dev/npm/package/kxco-pq-scan)
|
|
4
9
|
[](./LICENSE)
|
|
5
10
|
[](https://nodejs.org)
|
|
6
11
|
|
|
7
|
-
Find the cryptography in your dependency tree that a quantum computer breaks.
|
|
12
|
+
Find the cryptography in your dependency tree that a quantum computer breaks. It
|
|
13
|
+
reads the JavaScript dependency tree from `package-lock.json`, the record of
|
|
14
|
+
what was actually installed.
|
|
15
|
+
|
|
16
|
+
- **Runs on your machine, in seconds.** `npx kxco-pq-scan` reads `package-lock.json` locally: no install, no account and no upload.
|
|
17
|
+
- **Names who pulled each one in.** Every finding names the package that depends on it, so a transitive `ecdsa-sig-formatter` traces back through `jwa` and `jws` to the `jsonwebtoken` you chose.
|
|
18
|
+
- **Separates Shor from Grover.** RSA and elliptic curves are findings; AES and SHA-2, which Grover's algorithm only weakens, are named and kept out of the count.
|
|
19
|
+
- **Recognises hybrids.** A classical library paired with a post-quantum one is marked for review, in line with the hybrid migration path NIST and the IETF advise.
|
|
20
|
+
- **A CBOM in one command.** `--cbom` writes CycloneDX 1.6, validated against the published schema in the test suite and reproducible byte for byte with `SOURCE_DATE_EPOCH` set.
|
|
21
|
+
- **Federal policy now names the CBOM.** [Executive Order 14412](https://www.federalregister.gov/documents/2026/06/25/2026-12909/securing-the-nation-against-advanced-cryptographic-attacks) s.5(d) directs CISA to publish minimum elements for a cryptographic bill of materials within 270 days, by 19 March 2027. [OMB M-26-15](https://www.whitehouse.gov/wp-content/uploads/2026/06/M-26-15-Execution-of-the-Migration-to-Post-Quantum-Cryptography.pdf) calls for automated inventory tools to populate a central CBOM, and `--cbom` writes one today.
|
|
22
|
+
- **Zero dependencies.** Nothing transitive to audit, and SLSA provenance on every release.
|
|
23
|
+
|
|
24
|
+
**The migration has dates.**
|
|
8
25
|
|
|
9
|
-
**
|
|
10
|
-
|
|
11
|
-
|
|
26
|
+
- **NIST** published [FIPS 203](https://csrc.nist.gov/pubs/fips/203/final), [FIPS 204](https://csrc.nist.gov/pubs/fips/204/final) and [FIPS 205](https://csrc.nist.gov/pubs/fips/205/final) in August 2024.
|
|
27
|
+
- **United States:** [Executive Order 14412](https://www.federalregister.gov/documents/2026/06/25/2026-12909/securing-the-nation-against-advanced-cryptographic-attacks), signed on 22 June 2026, moves federal high-value and high-impact systems to post-quantum key establishment by 31 December 2030 and to post-quantum signatures by 31 December 2031. [OMB M-26-15](https://www.whitehouse.gov/wp-content/uploads/2026/06/M-26-15-Execution-of-the-Migration-to-Post-Quantum-Cryptography.pdf) requires PQC-agile libraries for all new applications.
|
|
28
|
+
- **United Kingdom:** the [NCSC](https://www.ncsc.gov.uk/guidance/pqc-migration-timelines) sets 2028, 2031 and 2035 as its migration milestones.
|
|
29
|
+
|
|
30
|
+
[Quick start](#quick-start) · [As a CBOM](#as-a-cbom) · [For institutions](#for-institutions) · [Assessment notes](./ASSESSMENT.md) · [Changelog](./CHANGELOG.md) · [kxco.ai](https://kxco.ai)
|
|
31
|
+
|
|
32
|
+
## Quick start
|
|
12
33
|
|
|
13
34
|
```
|
|
14
35
|
npx kxco-pq-scan
|
|
@@ -20,15 +41,16 @@ and prints what it finds.
|
|
|
20
41
|
## What it actually tells you
|
|
21
42
|
|
|
22
43
|
```
|
|
23
|
-
typical-app:
|
|
44
|
+
typical-app: 24 packages installed
|
|
24
45
|
|
|
25
|
-
QUANTUM-VULNERABLE (
|
|
26
|
-
elliptic@6.6.1 ECDSA, ECDH
|
|
27
|
-
pulled in by: (root)
|
|
28
|
-
jws@4.0.1 RSA, ECDSA
|
|
29
|
-
pulled in by: jsonwebtoken
|
|
46
|
+
QUANTUM-VULNERABLE (5)
|
|
30
47
|
ecdsa-sig-formatter@1.0.11 ECDSA
|
|
31
48
|
pulled in by: jwa
|
|
49
|
+
elliptic@6.6.1 ECDSA, ECDH
|
|
50
|
+
pulled in by: (root)
|
|
51
|
+
jsonwebtoken@9.0.3 RSA, ECDSA
|
|
52
|
+
pulled in by: (root)
|
|
53
|
+
note: only when signing with RS*, PS* or ES*; HS* is HMAC and is not broken
|
|
32
54
|
...
|
|
33
55
|
|
|
34
56
|
NOT AFFECTED, symmetric and hashing (2)
|
|
@@ -42,12 +64,12 @@ transitive. You did not choose `ecdsa-sig-formatter`; `jsonwebtoken` did, three
|
|
|
42
64
|
levels down. Knowing that is the difference between a finding you can act on and
|
|
43
65
|
a list you file.
|
|
44
66
|
|
|
45
|
-
**It
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
67
|
+
**It keeps the count honest.** Grover's algorithm halves a symmetric key's
|
|
68
|
+
effective length and nothing else, so AES-256 stands at 128 bits and SHA-2
|
|
69
|
+
stands with it. They are named so you can see they were considered, and kept out
|
|
70
|
+
of the findings so the findings mean something.
|
|
49
71
|
|
|
50
|
-
## Hybrids
|
|
72
|
+
## Hybrids, recognised
|
|
51
73
|
|
|
52
74
|
The current advice from NIST and the IETF is to migrate through hybrids: a
|
|
53
75
|
post-quantum algorithm paired with a classical one, so a break in either leaves
|
|
@@ -75,6 +97,26 @@ Exit `0` when there is nothing to act on, `1` on findings, `2` when it could not
|
|
|
75
97
|
scan. `--strict` also fails on the review cases, for a policy that wants a human
|
|
76
98
|
to sign off on every hybrid.
|
|
77
99
|
|
|
100
|
+
## For institutions
|
|
101
|
+
|
|
102
|
+
The cryptography is free under Apache-2.0, works offline and needs nothing from
|
|
103
|
+
KXCO, now or in ten years. What KXCO sells is the part that has to be operated:
|
|
104
|
+
an answer about the present.
|
|
105
|
+
|
|
106
|
+
| Service | What you get |
|
|
107
|
+
|---|---|
|
|
108
|
+
| Hosted key registry | Whether a key is active, revoked or rotated, answered at verification time |
|
|
109
|
+
| Meta-transaction relay | KXCO validates your signed intent, pays the gas and submits it, so you never hold a token or run a node |
|
|
110
|
+
| On-chain anchoring | A timestamp on Armature L1 that the chain itself has verified |
|
|
111
|
+
| Live revocation | `anchored+live` verification, which confirms the signing key is still trusted now |
|
|
112
|
+
| Support and SLA | Availability commitments, an escalation path and a named contact |
|
|
113
|
+
|
|
114
|
+
Priced in USD, per seat, per year. No tokens, no nodes and no wallets. The line
|
|
115
|
+
between free and paid is set out in
|
|
116
|
+
[LICENCE-PRODUCT.md](https://github.com/KnightsbridgeAIQ/kxco-post-quantum/blob/main/LICENCE-PRODUCT.md).
|
|
117
|
+
|
|
118
|
+
**Talk to us: [admin@kxco.ai](mailto:admin@kxco.ai)** · [kxco.ai](https://kxco.ai)
|
|
119
|
+
|
|
78
120
|
## As a library
|
|
79
121
|
|
|
80
122
|
```js
|
|
@@ -110,52 +152,50 @@ Each library `provides` the algorithms it implements, in the CycloneDX sense of
|
|
|
110
152
|
the word, and every judgement the scan made travels with it: the classification,
|
|
111
153
|
the severity, the hybrid context, and which package pulled it in.
|
|
112
154
|
|
|
113
|
-
|
|
155
|
+
Every field it carries is exact:
|
|
114
156
|
|
|
115
|
-
- **
|
|
116
|
-
carries `2.16.840.1.101.3.4.3.18
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
- **
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
157
|
+
- **An OID only where one is registered for that exact parameter set.**
|
|
158
|
+
`ML-DSA-65` carries `2.16.840.1.101.3.4.3.18`, and a bare `ML-DSA` carries
|
|
159
|
+
none, because OIDs are assigned per parameter set. A consumer matches an OID
|
|
160
|
+
exactly, so exactness is the whole value.
|
|
161
|
+
- **A security level only where it is certain.** The classical asymmetric
|
|
162
|
+
algorithms carry `nistQuantumSecurityLevel: 0`, the schema's own value for
|
|
163
|
+
meeting none of the categories. Symmetric and hash algorithms carry none,
|
|
164
|
+
because AES-128 and AES-256 sit at different NIST categories and a package
|
|
165
|
+
name carries neither.
|
|
124
166
|
|
|
125
|
-
The
|
|
126
|
-
without the command that produced it.
|
|
167
|
+
The scan's scope travels inside the document as the `kxco:pq-scan:limits`
|
|
168
|
+
property, because a CBOM travels without the command that produced it.
|
|
127
169
|
|
|
128
170
|
The output is validated against the published CycloneDX 1.6 schema in the test
|
|
129
171
|
suite, together with six deliberately malformed documents that the validator has
|
|
130
|
-
to reject
|
|
131
|
-
|
|
132
|
-
## What it cannot see
|
|
133
|
-
|
|
134
|
-
Stated here rather than left for you to discover:
|
|
172
|
+
to reject, so the gate is proven able to fail.
|
|
135
173
|
|
|
136
|
-
|
|
137
|
-
- A library loaded through a computed `require()` or a dynamic import
|
|
138
|
-
- **Which algorithm your code actually selects**, where a package offers
|
|
139
|
-
several. `jsonwebtoken` signing with `HS256` is HMAC and is fine; the same
|
|
140
|
-
package signing with `RS256` is not. No static read of a lock file can tell
|
|
141
|
-
those apart, so the package is reported and the note says so
|
|
142
|
-
- Anything outside the JavaScript tree: your TLS terminator, your database
|
|
143
|
-
driver, the certificate on your load balancer, the firmware in your HSM
|
|
174
|
+
## What it reads
|
|
144
175
|
|
|
145
176
|
It reads a lock file rather than `package.json` on purpose, because the lock
|
|
146
177
|
file records what was installed rather than what was asked for, and the
|
|
147
178
|
classical cryptography is nearly always transitive.
|
|
148
179
|
|
|
149
|
-
|
|
180
|
+
It gives you the candidate list in seconds, which is the part that would
|
|
181
|
+
otherwise take a week, and it is the place to start the full inventory:
|
|
150
182
|
|
|
151
|
-
|
|
183
|
+
- **Where a package offers several algorithms**, the finding carries a note.
|
|
184
|
+
`jsonwebtoken` signing with `HS256` is HMAC and is fine, while `RS256` is
|
|
185
|
+
RSA, so check which one your code selects
|
|
186
|
+
- **For cryptography compiled into a native addon or a WebAssembly module**, or
|
|
187
|
+
loaded through a computed `require()` or a dynamic import, confirm it in the
|
|
188
|
+
code
|
|
189
|
+
- **For everything outside the JavaScript tree**, such as your TLS terminator,
|
|
190
|
+
your database driver, the certificate on your load balancer and the firmware
|
|
191
|
+
in your HSM, merge the CBOM with a scan of those hosts, certificates and key
|
|
192
|
+
stores
|
|
152
193
|
|
|
153
|
-
|
|
154
|
-
exception, and it is why a scan is the start of the work: for a great many
|
|
155
|
-
libraries the post-quantum replacement has not been written, and somebody
|
|
156
|
-
upstream has to write it.
|
|
194
|
+
## What to do with a finding
|
|
157
195
|
|
|
158
|
-
|
|
196
|
+
A finding is where the migration starts. Where the upstream library ships a
|
|
197
|
+
post-quantum release, move to it. Where you are building the replacement
|
|
198
|
+
yourself, the primitives are in
|
|
159
199
|
[`kxco-post-quantum`](https://www.npmjs.com/package/kxco-post-quantum):
|
|
160
200
|
ML-KEM-768/1024, ML-DSA-65/87 and SLH-DSA-SHA2-192s, on the OpenSSL 3.5
|
|
161
201
|
primitives where the runtime provides them.
|
|
@@ -172,15 +212,55 @@ primitives where the runtime provides them.
|
|
|
172
212
|
Classification is a curated list, not a guess from the package name, because
|
|
173
213
|
the name carries no signal: `@noble/curves` is elliptic-curve and breaks,
|
|
174
214
|
`@noble/ciphers` is AES and does not. It is a plain object in
|
|
175
|
-
[`src/catalogue.js`](./src/catalogue.js)
|
|
215
|
+
[`src/catalogue.js`](./src/catalogue.js): read it, disagree with it, open a
|
|
176
216
|
pull request.
|
|
177
217
|
|
|
178
|
-
|
|
218
|
+
To add a package you depend on, open an issue or a pull request.
|
|
219
|
+
|
|
220
|
+
## The KXCO post-quantum family
|
|
221
|
+
|
|
222
|
+
This finds the classical cryptography in a tree. The rest of the family
|
|
223
|
+
replaces it:
|
|
224
|
+
|
|
225
|
+
| You need to | Install |
|
|
226
|
+
|---|---|
|
|
227
|
+
| Put the whole stack in one install | [`kxco-pq`](https://www.npmjs.com/package/kxco-pq) |
|
|
228
|
+
| Use ML-DSA, ML-KEM and SLH-DSA directly | [`kxco-post-quantum`](https://www.npmjs.com/package/kxco-post-quantum) |
|
|
229
|
+
| Keep signing keys on the HSM you already run | [`kxco-pq-hsm`](https://www.npmjs.com/package/kxco-pq-hsm) |
|
|
230
|
+
| Sign a document or record anyone can verify offline | [`kxco-pq-attest`](https://www.npmjs.com/package/kxco-pq-attest) |
|
|
231
|
+
| Keep a tamper-evident audit trail | [`kxco-pq-audit`](https://www.npmjs.com/package/kxco-pq-audit) |
|
|
232
|
+
| Verify a signature in a browser, with no server | [`kxco-verify`](https://www.npmjs.com/package/kxco-verify) |
|
|
233
|
+
| Issue institution identity credentials | [`kxco-pq-sdk`](https://www.npmjs.com/package/kxco-pq-sdk) |
|
|
234
|
+
| Encrypt files and payloads to one or many recipients | [`kxco-pq-vault`](https://www.npmjs.com/package/kxco-pq-vault) |
|
|
235
|
+
| Encrypt Node streams and WebSockets | [`kxco-pq-tls`](https://www.npmjs.com/package/kxco-pq-tls) |
|
|
236
|
+
| Sign and verify webhooks | [`kxco-post-quantum-webhook`](https://www.npmjs.com/package/kxco-post-quantum-webhook) |
|
|
237
|
+
| Give an AI agent an identity a verified institution sponsors | [`kxco-pq-agent`](https://www.npmjs.com/package/kxco-pq-agent) |
|
|
238
|
+
| Have Armature L1 verify a signature in consensus | [`kxco-pq-chain`](https://www.npmjs.com/package/kxco-pq-chain) |
|
|
239
|
+
| Prove an envelope at three levels, offline to on-chain | [`kxco-pq-network`](https://www.npmjs.com/package/kxco-pq-network) |
|
|
240
|
+
| Generate and rotate keys from a terminal | [`kxco-pq-cli`](https://www.npmjs.com/package/kxco-pq-cli) |
|
|
241
|
+
| Find quantum-vulnerable cryptography in a dependency tree | [`kxco-pq-scan`](https://www.npmjs.com/package/kxco-pq-scan) |
|
|
242
|
+
| Fail the build when code reaches past the wrapper | [`eslint-plugin-kxco-pq`](https://www.npmjs.com/package/eslint-plugin-kxco-pq) |
|
|
243
|
+
|
|
244
|
+
## Release integrity
|
|
245
|
+
|
|
246
|
+
Each release carries a SLSA provenance attestation tying the published tarball to
|
|
247
|
+
the commit and workflow that built it: verify with `npm audit signatures`, or read
|
|
248
|
+
it from `registry.npmjs.org/-/npm/v1/attestations/kxco-pq-scan@<version>`. The
|
|
249
|
+
package has no runtime dependencies, so there is no transitive tree to audit, and
|
|
250
|
+
`npm run evidence` regenerates identity, the test run, the SBOM and registry
|
|
251
|
+
signature verification from source.
|
|
252
|
+
|
|
253
|
+
## Security
|
|
254
|
+
|
|
255
|
+
The scanner reads the files in the directory it is pointed at and writes a
|
|
256
|
+
report: no network, no state and no runtime dependencies.
|
|
257
|
+
|
|
258
|
+
To report a vulnerability, open a [private security advisory](https://github.com/KnightsbridgeAIQ/kxco-pq-scan/security/advisories/new) or email **security@kxco.ai**.
|
|
179
259
|
|
|
180
260
|
## License
|
|
181
261
|
|
|
182
|
-
Apache-2.0 © 2026 KXCO
|
|
262
|
+
Apache-2.0 © 2026 Knightsbridge Financial Ltd, trading as KXCO. See [LICENSE](./LICENSE) and [NOTICE](./NOTICE).
|
|
183
263
|
|
|
184
264
|
## Maintainers
|
|
185
265
|
|
|
186
|
-
Shayne Heffernan · John Heffernan
|
|
266
|
+
Shayne Heffernan · John Heffernan, [KXCO by Knightsbridge](https://kxco.ai)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kxco-pq-scan",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Find quantum-vulnerable cryptography in a JavaScript dependency tree. Separates what Shor's algorithm breaks from what Grover's only weakens, recognises hybrid constructions, and
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "Find quantum-vulnerable cryptography in a JavaScript dependency tree in seconds and emit a CycloneDX 1.6 CBOM. Separates what Shor's algorithm breaks from what Grover's only weakens, recognises hybrid constructions, and names who pulled each finding in.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"post-quantum",
|
|
7
7
|
"pqc",
|
|
@@ -18,7 +18,14 @@
|
|
|
18
18
|
"cyclonedx",
|
|
19
19
|
"crypto-inventory",
|
|
20
20
|
"quantum-readiness",
|
|
21
|
-
"cryptographic-bill-of-materials"
|
|
21
|
+
"cryptographic-bill-of-materials",
|
|
22
|
+
"pqc-migration",
|
|
23
|
+
"crypto-agility",
|
|
24
|
+
"cryptographic-inventory",
|
|
25
|
+
"dependency-scanner",
|
|
26
|
+
"security-scanner",
|
|
27
|
+
"lockfile",
|
|
28
|
+
"shor"
|
|
22
29
|
],
|
|
23
30
|
"type": "module",
|
|
24
31
|
"exports": {
|
|
@@ -35,10 +42,11 @@
|
|
|
35
42
|
"bin",
|
|
36
43
|
"README.md",
|
|
37
44
|
"LICENSE",
|
|
45
|
+
"NOTICE",
|
|
38
46
|
"ASSESSMENT.md"
|
|
39
47
|
],
|
|
40
48
|
"scripts": {
|
|
41
|
-
"test": "node --test test/scan.test.js test/cbom.test.js test/cbom.schema.test.js",
|
|
49
|
+
"test": "node --test test/scan.test.js test/cbom.test.js test/cbom.schema.test.js test/property.test.js",
|
|
42
50
|
"evidence": "node scripts/build-evidence.mjs"
|
|
43
51
|
},
|
|
44
52
|
"engines": {
|
|
@@ -57,6 +65,7 @@
|
|
|
57
65
|
},
|
|
58
66
|
"devDependencies": {
|
|
59
67
|
"ajv": "^8.20.0",
|
|
60
|
-
"ajv-formats": "^3.0.1"
|
|
68
|
+
"ajv-formats": "^3.0.1",
|
|
69
|
+
"fast-check": "4.10.2"
|
|
61
70
|
}
|
|
62
71
|
}
|
package/src/catalogue.js
CHANGED
|
@@ -66,7 +66,7 @@ export const CATALOGUE = {
|
|
|
66
66
|
note: 'X25519 is the classical half of a deliberate hybrid' },
|
|
67
67
|
'kxco-pq-attest': { classes: ['pq'], algorithms: ['ML-DSA-65'] },
|
|
68
68
|
'kxco-pq-hsm': { classes: ['pq'], algorithms: ['ML-DSA-65', 'ML-KEM-768'] },
|
|
69
|
-
'kxco-pq-sdk': { classes: ['pq'], algorithms: ['ML-DSA-65', 'ML-KEM-768'] },
|
|
69
|
+
'kxco-pq-sdk': { classes: ['pq'], algorithms: ['ML-DSA-65', 'ML-DSA-87', 'ML-KEM-768', 'ML-KEM-1024'] },
|
|
70
70
|
'liboqs-node': { classes: ['pq'], algorithms: ['ML-KEM', 'ML-DSA'] },
|
|
71
71
|
'pqclean': { classes: ['pq'], algorithms: ['ML-KEM', 'ML-DSA'] },
|
|
72
72
|
}
|
package/src/cbom.js
CHANGED
|
@@ -107,22 +107,46 @@ const ALGORITHMS = {
|
|
|
107
107
|
// FIPS 203, 204 and 205. The OIDs are the NIST CSOR registrations and are
|
|
108
108
|
// asserted only where the parameter set is named, because the OID is per
|
|
109
109
|
// parameter set: there is no OID for "ML-KEM" in the abstract.
|
|
110
|
+
//
|
|
111
|
+
// id-alg-ml-kem-512/768/1024 are { kems 1, 2, 3 } and id-ml-dsa-44/65/87 are
|
|
112
|
+
// { sigAlgs 17, 18, 19 }, under nistAlgorithms 2.16.840.1.101.3.4. The NIST
|
|
113
|
+
// security category is the one FIPS 203 and FIPS 204 assign each set.
|
|
110
114
|
'ML-KEM': {
|
|
111
115
|
primitive: 'kem', cryptoFunctions: ['keygen', 'encapsulate', 'decapsulate'],
|
|
112
116
|
},
|
|
117
|
+
'ML-KEM-512': {
|
|
118
|
+
primitive: 'kem', cryptoFunctions: ['keygen', 'encapsulate', 'decapsulate'],
|
|
119
|
+
parameterSetIdentifier: '512', oid: '2.16.840.1.101.3.4.4.1',
|
|
120
|
+
nistQuantumSecurityLevel: 1,
|
|
121
|
+
},
|
|
113
122
|
'ML-KEM-768': {
|
|
114
123
|
primitive: 'kem', cryptoFunctions: ['keygen', 'encapsulate', 'decapsulate'],
|
|
115
124
|
parameterSetIdentifier: '768', oid: '2.16.840.1.101.3.4.4.2',
|
|
116
125
|
nistQuantumSecurityLevel: 3,
|
|
117
126
|
},
|
|
127
|
+
'ML-KEM-1024': {
|
|
128
|
+
primitive: 'kem', cryptoFunctions: ['keygen', 'encapsulate', 'decapsulate'],
|
|
129
|
+
parameterSetIdentifier: '1024', oid: '2.16.840.1.101.3.4.4.3',
|
|
130
|
+
nistQuantumSecurityLevel: 5,
|
|
131
|
+
},
|
|
118
132
|
'ML-DSA': {
|
|
119
133
|
primitive: 'signature', cryptoFunctions: ['keygen', 'sign', 'verify'],
|
|
120
134
|
},
|
|
135
|
+
'ML-DSA-44': {
|
|
136
|
+
primitive: 'signature', cryptoFunctions: ['keygen', 'sign', 'verify'],
|
|
137
|
+
parameterSetIdentifier: '44', oid: '2.16.840.1.101.3.4.3.17',
|
|
138
|
+
nistQuantumSecurityLevel: 2,
|
|
139
|
+
},
|
|
121
140
|
'ML-DSA-65': {
|
|
122
141
|
primitive: 'signature', cryptoFunctions: ['keygen', 'sign', 'verify'],
|
|
123
142
|
parameterSetIdentifier: '65', oid: '2.16.840.1.101.3.4.3.18',
|
|
124
143
|
nistQuantumSecurityLevel: 3,
|
|
125
144
|
},
|
|
145
|
+
'ML-DSA-87': {
|
|
146
|
+
primitive: 'signature', cryptoFunctions: ['keygen', 'sign', 'verify'],
|
|
147
|
+
parameterSetIdentifier: '87', oid: '2.16.840.1.101.3.4.3.19',
|
|
148
|
+
nistQuantumSecurityLevel: 5,
|
|
149
|
+
},
|
|
126
150
|
'SLH-DSA': {
|
|
127
151
|
primitive: 'signature', cryptoFunctions: ['keygen', 'sign', 'verify'],
|
|
128
152
|
},
|