@quantakrypto/core 0.4.2 → 0.4.4
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/LICENSE +201 -0
- package/README.md +38 -10
- package/dist/agent-types.js.map +1 -1
- package/dist/baseline.js.map +1 -1
- package/dist/cache.js.map +1 -1
- package/dist/cbom-merge.d.ts +9 -0
- package/dist/cbom-merge.d.ts.map +1 -0
- package/dist/cbom-merge.js +99 -0
- package/dist/cbom-merge.js.map +1 -0
- package/dist/cbom.js.map +1 -1
- package/dist/changed.js.map +1 -1
- package/dist/codemods/config-toggle.js.map +1 -1
- package/dist/codemods/registry.js.map +1 -1
- package/dist/comments.d.ts +29 -2
- package/dist/comments.d.ts.map +1 -1
- package/dist/comments.js +178 -18
- package/dist/comments.js.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/cwe.js.map +1 -1
- package/dist/dependencies.d.ts +3 -2
- package/dist/dependencies.d.ts.map +1 -1
- package/dist/dependencies.js +138 -2
- package/dist/dependencies.js.map +1 -1
- package/dist/detect-utils.d.ts +19 -4
- package/dist/detect-utils.d.ts.map +1 -1
- package/dist/detect-utils.js +43 -6
- package/dist/detect-utils.js.map +1 -1
- package/dist/detectors/c.d.ts +4 -2
- package/dist/detectors/c.d.ts.map +1 -1
- package/dist/detectors/c.js +382 -3
- package/dist/detectors/c.js.map +1 -1
- package/dist/detectors/cicd.d.ts +27 -0
- package/dist/detectors/cicd.d.ts.map +1 -0
- package/dist/detectors/cicd.js +116 -0
- package/dist/detectors/cicd.js.map +1 -0
- package/dist/detectors/cloud-kms.d.ts +21 -0
- package/dist/detectors/cloud-kms.d.ts.map +1 -0
- package/dist/detectors/cloud-kms.js +57 -0
- package/dist/detectors/cloud-kms.js.map +1 -0
- package/dist/detectors/cloudformation.d.ts +30 -0
- package/dist/detectors/cloudformation.d.ts.map +1 -0
- package/dist/detectors/cloudformation.js +170 -0
- package/dist/detectors/cloudformation.js.map +1 -0
- package/dist/detectors/csharp.d.ts.map +1 -1
- package/dist/detectors/csharp.js +141 -3
- package/dist/detectors/csharp.js.map +1 -1
- package/dist/detectors/database.d.ts +17 -0
- package/dist/detectors/database.d.ts.map +1 -0
- package/dist/detectors/database.js +60 -0
- package/dist/detectors/database.js.map +1 -0
- package/dist/detectors/dnssec.d.ts +55 -0
- package/dist/detectors/dnssec.d.ts.map +1 -0
- package/dist/detectors/dnssec.js +107 -0
- package/dist/detectors/dnssec.js.map +1 -0
- package/dist/detectors/elixir.d.ts +20 -0
- package/dist/detectors/elixir.d.ts.map +1 -0
- package/dist/detectors/elixir.js +195 -0
- package/dist/detectors/elixir.js.map +1 -0
- package/dist/detectors/go.d.ts +5 -3
- package/dist/detectors/go.d.ts.map +1 -1
- package/dist/detectors/go.js +187 -3
- package/dist/detectors/go.js.map +1 -1
- package/dist/detectors/java.d.ts.map +1 -1
- package/dist/detectors/java.js +169 -4
- package/dist/detectors/java.js.map +1 -1
- package/dist/detectors/jose.d.ts +20 -0
- package/dist/detectors/jose.d.ts.map +1 -0
- package/dist/detectors/jose.js +62 -0
- package/dist/detectors/jose.js.map +1 -0
- package/dist/detectors/jwk.d.ts +25 -0
- package/dist/detectors/jwk.d.ts.map +1 -0
- package/dist/detectors/jwk.js +95 -0
- package/dist/detectors/jwk.js.map +1 -0
- package/dist/detectors/k8s.d.ts +17 -0
- package/dist/detectors/k8s.d.ts.map +1 -0
- package/dist/detectors/k8s.js +85 -0
- package/dist/detectors/k8s.js.map +1 -0
- package/dist/detectors/mesh.d.ts +35 -0
- package/dist/detectors/mesh.d.ts.map +1 -0
- package/dist/detectors/mesh.js +109 -0
- package/dist/detectors/mesh.js.map +1 -0
- package/dist/detectors/messaging.d.ts +16 -0
- package/dist/detectors/messaging.d.ts.map +1 -0
- package/dist/detectors/messaging.js +72 -0
- package/dist/detectors/messaging.js.map +1 -0
- package/dist/detectors/pem.d.ts.map +1 -1
- package/dist/detectors/pem.js +50 -2
- package/dist/detectors/pem.js.map +1 -1
- package/dist/detectors/php.d.ts +24 -0
- package/dist/detectors/php.d.ts.map +1 -0
- package/dist/detectors/php.js +167 -0
- package/dist/detectors/php.js.map +1 -0
- package/dist/detectors/python.d.ts.map +1 -1
- package/dist/detectors/python.js +144 -3
- package/dist/detectors/python.js.map +1 -1
- package/dist/detectors/ruby.d.ts +9 -5
- package/dist/detectors/ruby.d.ts.map +1 -1
- package/dist/detectors/ruby.js +122 -2
- package/dist/detectors/ruby.js.map +1 -1
- package/dist/detectors/rust.d.ts +8 -3
- package/dist/detectors/rust.d.ts.map +1 -1
- package/dist/detectors/rust.js +253 -3
- package/dist/detectors/rust.js.map +1 -1
- package/dist/detectors/secrets.d.ts +21 -0
- package/dist/detectors/secrets.d.ts.map +1 -0
- package/dist/detectors/secrets.js +79 -0
- package/dist/detectors/secrets.js.map +1 -0
- package/dist/detectors/source.d.ts.map +1 -1
- package/dist/detectors/source.js +305 -52
- package/dist/detectors/source.js.map +1 -1
- package/dist/detectors/stateful-hbs.d.ts +22 -0
- package/dist/detectors/stateful-hbs.d.ts.map +1 -0
- package/dist/detectors/stateful-hbs.js +142 -0
- package/dist/detectors/stateful-hbs.js.map +1 -0
- package/dist/detectors/terraform.d.ts +21 -0
- package/dist/detectors/terraform.d.ts.map +1 -0
- package/dist/detectors/terraform.js +123 -0
- package/dist/detectors/terraform.js.map +1 -0
- package/dist/detectors/vpn.d.ts +22 -0
- package/dist/detectors/vpn.d.ts.map +1 -0
- package/dist/detectors/vpn.js +99 -0
- package/dist/detectors/vpn.js.map +1 -0
- package/dist/errors.js.map +1 -1
- package/dist/evidence.d.ts +53 -0
- package/dist/evidence.d.ts.map +1 -0
- package/dist/evidence.js +81 -0
- package/dist/evidence.js.map +1 -0
- package/dist/index.d.ts +9 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -2
- package/dist/index.js.map +1 -1
- package/dist/inventory.d.ts +2 -0
- package/dist/inventory.d.ts.map +1 -1
- package/dist/inventory.js +27 -1
- package/dist/inventory.js.map +1 -1
- package/dist/parallel.js.map +1 -1
- package/dist/patch-policy.js.map +1 -1
- package/dist/policy.d.ts +67 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/policy.js +115 -0
- package/dist/policy.js.map +1 -0
- package/dist/redact.d.ts.map +1 -1
- package/dist/redact.js +39 -0
- package/dist/redact.js.map +1 -1
- package/dist/registry.d.ts +2 -2
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +34 -2
- package/dist/registry.js.map +1 -1
- package/dist/remediate-pipeline.d.ts +3 -0
- package/dist/remediate-pipeline.d.ts.map +1 -1
- package/dist/remediate-pipeline.js +71 -0
- package/dist/remediate-pipeline.js.map +1 -1
- package/dist/remediate-request.js.map +1 -1
- package/dist/remediation.d.ts +9 -3
- package/dist/remediation.d.ts.map +1 -1
- package/dist/remediation.js +17 -5
- package/dist/remediation.js.map +1 -1
- package/dist/report.d.ts +9 -0
- package/dist/report.d.ts.map +1 -1
- package/dist/report.js +38 -0
- package/dist/report.js.map +1 -1
- package/dist/scan-worker.js.map +1 -1
- package/dist/scan.d.ts.map +1 -1
- package/dist/scan.js +8 -1
- package/dist/scan.js.map +1 -1
- package/dist/severity.js.map +1 -1
- package/dist/standards.d.ts +96 -0
- package/dist/standards.d.ts.map +1 -0
- package/dist/standards.js +107 -0
- package/dist/standards.js.map +1 -0
- package/dist/triage.js.map +1 -1
- package/dist/types.d.ts +2 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/verify.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/dist/walk.js.map +1 -1
- package/dist/worktree.js.map +1 -1
- package/package.json +1 -1
- package/src/cbom-merge.ts +116 -0
- package/src/comments.ts +183 -18
- package/src/dependencies.ts +144 -4
- package/src/detect-utils.ts +47 -6
- package/src/detectors/c.ts +411 -5
- package/src/detectors/cicd.ts +158 -0
- package/src/detectors/cloud-kms.ts +87 -0
- package/src/detectors/cloudformation.ts +215 -0
- package/src/detectors/csharp.ts +154 -3
- package/src/detectors/database.ts +88 -0
- package/src/detectors/dnssec.ts +186 -0
- package/src/detectors/elixir.ts +237 -0
- package/src/detectors/go.ts +209 -6
- package/src/detectors/java.ts +191 -4
- package/src/detectors/jose.ts +94 -0
- package/src/detectors/jwk.ts +128 -0
- package/src/detectors/k8s.ts +112 -0
- package/src/detectors/mesh.ts +154 -0
- package/src/detectors/messaging.ts +98 -0
- package/src/detectors/pem.ts +54 -2
- package/src/detectors/php.ts +225 -0
- package/src/detectors/python.ts +153 -3
- package/src/detectors/ruby.ts +138 -7
- package/src/detectors/rust.ts +282 -7
- package/src/detectors/secrets.ts +114 -0
- package/src/detectors/source.ts +382 -72
- package/src/detectors/stateful-hbs.ts +180 -0
- package/src/detectors/terraform.ts +154 -0
- package/src/detectors/vpn.ts +131 -0
- package/src/evidence.ts +135 -0
- package/src/index.ts +15 -1
- package/src/inventory.ts +31 -1
- package/src/policy.ts +180 -0
- package/src/redact.ts +41 -0
- package/src/registry.ts +34 -2
- package/src/remediate-pipeline.ts +78 -0
- package/src/remediation.ts +23 -8
- package/src/report.ts +48 -2
- package/src/scan.ts +13 -1
- package/src/standards.ts +186 -0
- package/src/types.ts +3 -1
- package/src/version.ts +1 -1
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config detector: classical key exchange in network transport / VPN config —
|
|
3
|
+
* WireGuard, IPsec (strongSwan), and OpenSSH server config. These are the tunnels
|
|
4
|
+
* carrying "communication between things"; their key exchange is classical and so
|
|
5
|
+
* harvest-now-decrypt-later exposed (a recorded tunnel is decryptable once a CRQC
|
|
6
|
+
* exists).
|
|
7
|
+
*
|
|
8
|
+
* Covered (each gated so it only fires inside the relevant config):
|
|
9
|
+
* - **WireGuard** — `[Interface]`/`[Peer]` sections with `PrivateKey`/`PublicKey`.
|
|
10
|
+
* WireGuard's Noise handshake is Curve25519 with NO standard PQC option, so this
|
|
11
|
+
* is an especially sharp finding: it cannot be made quantum-safe without a
|
|
12
|
+
* tunnel-wrapping layer. The private key is treated as sensitive key material.
|
|
13
|
+
* - **IPsec / strongSwan** — IKE/ESP proposals naming classical DH groups
|
|
14
|
+
* (`modp*` = finite-field DH, `ecp*` = ECDH).
|
|
15
|
+
* - **sshd_config / ssh_config** — a `KexAlgorithms` line that offers no PQC hybrid
|
|
16
|
+
* KEX (`sntrup761x25519-*`, `mlkem768x25519-*`). If a PQC KEX IS listed the line
|
|
17
|
+
* is left alone, so a hardened server stays silent.
|
|
18
|
+
*/
|
|
19
|
+
import type { Detector } from "../types.js";
|
|
20
|
+
/** Detects classical key exchange in WireGuard / IPsec / sshd network config. */
|
|
21
|
+
export declare const vpnDetector: Detector;
|
|
22
|
+
//# sourceMappingURL=vpn.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vpn.d.ts","sourceRoot":"","sources":["../../src/detectors/vpn.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAqB,MAAM,aAAa,CAAC;AA2E/D,iFAAiF;AACjF,eAAO,MAAM,WAAW,EAAE,QAoCzB,CAAC"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { eachMatch, findingFromRule } from "../detect-utils.js";
|
|
2
|
+
import { CWE_BROKEN_CRYPTO } from "../cwe.js";
|
|
3
|
+
const RE_WG_KEY = /\b(?:PrivateKey|PublicKey)\s*=\s*[A-Za-z0-9+/]{42,}=/g;
|
|
4
|
+
const RE_IPSEC_MODP = /\bmodp\d+\b/gi;
|
|
5
|
+
const RE_IPSEC_ECP = /\becp\d+(?:bp)?\b/gi;
|
|
6
|
+
const RE_SSHD_KEX = /^[ \t]*KexAlgorithms[ \t]+([^\n]*)/gm;
|
|
7
|
+
const RULE_WG = {
|
|
8
|
+
id: "net-wireguard-x25519",
|
|
9
|
+
title: "WireGuard Curve25519 key",
|
|
10
|
+
description: "WireGuard [Interface]/[Peer] key — Curve25519 Noise handshake (no PQC option)",
|
|
11
|
+
category: "key-exchange",
|
|
12
|
+
severity: "high",
|
|
13
|
+
confidence: "high",
|
|
14
|
+
algorithm: "X25519",
|
|
15
|
+
hndl: true,
|
|
16
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
17
|
+
sensitive: true,
|
|
18
|
+
message: "WireGuard tunnel keyed by classical Curve25519 (Noise); WireGuard has no standard post-quantum KEM, so the tunnel is harvest-now-decrypt-later exposed until wrapped by a PQC layer.",
|
|
19
|
+
remediation: "Wrap the tunnel in a PQC-hybrid transport (e.g. a TLS 1.3 X25519MLKEM768 layer) or track WireGuard PQC proposals; rotate keys when available.",
|
|
20
|
+
};
|
|
21
|
+
const RULE_IPSEC_DH = {
|
|
22
|
+
id: "net-ipsec-modp-dh",
|
|
23
|
+
title: "IPsec classical DH group (modp)",
|
|
24
|
+
description: "IPsec/strongSwan IKE/ESP proposal names a finite-field DH group (modp*)",
|
|
25
|
+
category: "key-exchange",
|
|
26
|
+
severity: "medium",
|
|
27
|
+
confidence: "high",
|
|
28
|
+
algorithm: "DH",
|
|
29
|
+
hndl: true,
|
|
30
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
31
|
+
message: "IPsec proposal uses a classical finite-field Diffie-Hellman group (modp*); the tunnel key exchange is harvest-now-decrypt-later exposed.",
|
|
32
|
+
remediation: "Add a PQC/hybrid IKE proposal (ML-KEM) as your IPsec stack supports it.",
|
|
33
|
+
};
|
|
34
|
+
const RULE_IPSEC_EC = {
|
|
35
|
+
id: "net-ipsec-ecp-ecdh",
|
|
36
|
+
title: "IPsec classical ECDH group (ecp)",
|
|
37
|
+
description: "IPsec/strongSwan IKE/ESP proposal names an elliptic-curve DH group (ecp*)",
|
|
38
|
+
category: "key-exchange",
|
|
39
|
+
severity: "medium",
|
|
40
|
+
confidence: "high",
|
|
41
|
+
algorithm: "ECDH",
|
|
42
|
+
hndl: true,
|
|
43
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
44
|
+
message: "IPsec proposal uses a classical elliptic-curve Diffie-Hellman group (ecp*); the tunnel key exchange is harvest-now-decrypt-later exposed.",
|
|
45
|
+
remediation: "Add a PQC/hybrid IKE proposal (X25519MLKEM768 / ML-KEM) as your IPsec stack supports it.",
|
|
46
|
+
};
|
|
47
|
+
const RULE_SSHD_KEX = {
|
|
48
|
+
id: "net-sshd-classical-kex",
|
|
49
|
+
title: "SSH server offers no PQC key exchange",
|
|
50
|
+
description: "sshd_config KexAlgorithms lists only classical key exchange (no sntrup761/mlkem768)",
|
|
51
|
+
category: "key-exchange",
|
|
52
|
+
severity: "medium",
|
|
53
|
+
confidence: "high",
|
|
54
|
+
algorithm: "ECDH",
|
|
55
|
+
hndl: true,
|
|
56
|
+
cwe: CWE_BROKEN_CRYPTO,
|
|
57
|
+
message: "SSH server's KexAlgorithms offers only classical key exchange (no sntrup761x25519 / mlkem768x25519); sessions are harvest-now-decrypt-later exposed.",
|
|
58
|
+
remediation: "Add a PQC hybrid KEX: sntrup761x25519-sha512@openssh.com or mlkem768x25519-sha256.",
|
|
59
|
+
};
|
|
60
|
+
/** True when a KexAlgorithms value already offers a post-quantum hybrid KEX. */
|
|
61
|
+
function offersPqKex(kexLine) {
|
|
62
|
+
return /sntrup761x25519|mlkem768/.test(kexLine);
|
|
63
|
+
}
|
|
64
|
+
/** Detects classical key exchange in WireGuard / IPsec / sshd network config. */
|
|
65
|
+
export const vpnDetector = {
|
|
66
|
+
id: "network-transport-crypto",
|
|
67
|
+
description: "Classical key exchange in network transport / VPN config (WireGuard, IPsec, sshd)",
|
|
68
|
+
scope: "config",
|
|
69
|
+
language: "any",
|
|
70
|
+
rules: [RULE_WG, RULE_IPSEC_DH, RULE_IPSEC_EC, RULE_SSHD_KEX],
|
|
71
|
+
appliesTo: (f) => {
|
|
72
|
+
const lower = f.toLowerCase();
|
|
73
|
+
const base = lower.split("/").pop() ?? lower;
|
|
74
|
+
return lower.endsWith(".conf") || base === "sshd_config" || base === "ssh_config";
|
|
75
|
+
},
|
|
76
|
+
detect({ file, content }) {
|
|
77
|
+
const findings = [];
|
|
78
|
+
const push = (rule, index, length) => findings.push(findingFromRule(rule, { file, content, index, matchLength: length }));
|
|
79
|
+
// WireGuard: gated to a WireGuard config section.
|
|
80
|
+
if (content.includes("[Interface]") || content.includes("[Peer]")) {
|
|
81
|
+
eachMatch(RE_WG_KEY, content, (m) => push(RULE_WG, m.index, m[0].length));
|
|
82
|
+
}
|
|
83
|
+
// IPsec / strongSwan: gated to a proposal assignment.
|
|
84
|
+
if (/\b(?:ike|esp|proposals?|keyexchange)\s*=/i.test(content)) {
|
|
85
|
+
eachMatch(RE_IPSEC_MODP, content, (m) => push(RULE_IPSEC_DH, m.index, m[0].length));
|
|
86
|
+
eachMatch(RE_IPSEC_ECP, content, (m) => push(RULE_IPSEC_EC, m.index, m[0].length));
|
|
87
|
+
}
|
|
88
|
+
// sshd_config / ssh_config: KexAlgorithms line with no PQC hybrid offered.
|
|
89
|
+
const base = file.toLowerCase().split("/").pop() ?? "";
|
|
90
|
+
if (base === "sshd_config" || base === "ssh_config") {
|
|
91
|
+
eachMatch(RE_SSHD_KEX, content, (m) => {
|
|
92
|
+
if (!offersPqKex(m[1]))
|
|
93
|
+
push(RULE_SSHD_KEX, m.index, m[0].length);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
return findings;
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
//# sourceMappingURL=vpn.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vpn.js","sourceRoot":"","sources":["../../src/detectors/vpn.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Config detector: classical key exchange in network transport / VPN config —\n * WireGuard, IPsec (strongSwan), and OpenSSH server config. These are the tunnels\n * carrying \"communication between things\"; their key exchange is classical and so\n * harvest-now-decrypt-later exposed (a recorded tunnel is decryptable once a CRQC\n * exists).\n *\n * Covered (each gated so it only fires inside the relevant config):\n * - **WireGuard** — `[Interface]`/`[Peer]` sections with `PrivateKey`/`PublicKey`.\n * WireGuard's Noise handshake is Curve25519 with NO standard PQC option, so this\n * is an especially sharp finding: it cannot be made quantum-safe without a\n * tunnel-wrapping layer. The private key is treated as sensitive key material.\n * - **IPsec / strongSwan** — IKE/ESP proposals naming classical DH groups\n * (`modp*` = finite-field DH, `ecp*` = ECDH).\n * - **sshd_config / ssh_config** — a `KexAlgorithms` line that offers no PQC hybrid\n * KEX (`sntrup761x25519-*`, `mlkem768x25519-*`). If a PQC KEX IS listed the line\n * is left alone, so a hardened server stays silent.\n */\nimport type { Detector, Finding, RuleMeta } from \"../types.js\";\nimport { eachMatch, findingFromRule } from \"../detect-utils.js\";\nimport { CWE_BROKEN_CRYPTO } from \"../cwe.js\";\n\nconst RE_WG_KEY = /\\b(?:PrivateKey|PublicKey)\\s*=\\s*[A-Za-z0-9+/]{42,}=/g;\nconst RE_IPSEC_MODP = /\\bmodp\\d+\\b/gi;\nconst RE_IPSEC_ECP = /\\becp\\d+(?:bp)?\\b/gi;\nconst RE_SSHD_KEX = /^[ \\t]*KexAlgorithms[ \\t]+([^\\n]*)/gm;\n\nconst RULE_WG: RuleMeta = {\n id: \"net-wireguard-x25519\",\n title: \"WireGuard Curve25519 key\",\n description: \"WireGuard [Interface]/[Peer] key — Curve25519 Noise handshake (no PQC option)\",\n category: \"key-exchange\",\n severity: \"high\",\n confidence: \"high\",\n algorithm: \"X25519\",\n hndl: true,\n cwe: CWE_BROKEN_CRYPTO,\n sensitive: true,\n message:\n \"WireGuard tunnel keyed by classical Curve25519 (Noise); WireGuard has no standard post-quantum KEM, so the tunnel is harvest-now-decrypt-later exposed until wrapped by a PQC layer.\",\n remediation:\n \"Wrap the tunnel in a PQC-hybrid transport (e.g. a TLS 1.3 X25519MLKEM768 layer) or track WireGuard PQC proposals; rotate keys when available.\",\n};\nconst RULE_IPSEC_DH: RuleMeta = {\n id: \"net-ipsec-modp-dh\",\n title: \"IPsec classical DH group (modp)\",\n description: \"IPsec/strongSwan IKE/ESP proposal names a finite-field DH group (modp*)\",\n category: \"key-exchange\",\n severity: \"medium\",\n confidence: \"high\",\n algorithm: \"DH\",\n hndl: true,\n cwe: CWE_BROKEN_CRYPTO,\n message:\n \"IPsec proposal uses a classical finite-field Diffie-Hellman group (modp*); the tunnel key exchange is harvest-now-decrypt-later exposed.\",\n remediation: \"Add a PQC/hybrid IKE proposal (ML-KEM) as your IPsec stack supports it.\",\n};\nconst RULE_IPSEC_EC: RuleMeta = {\n id: \"net-ipsec-ecp-ecdh\",\n title: \"IPsec classical ECDH group (ecp)\",\n description: \"IPsec/strongSwan IKE/ESP proposal names an elliptic-curve DH group (ecp*)\",\n category: \"key-exchange\",\n severity: \"medium\",\n confidence: \"high\",\n algorithm: \"ECDH\",\n hndl: true,\n cwe: CWE_BROKEN_CRYPTO,\n message:\n \"IPsec proposal uses a classical elliptic-curve Diffie-Hellman group (ecp*); the tunnel key exchange is harvest-now-decrypt-later exposed.\",\n remediation:\n \"Add a PQC/hybrid IKE proposal (X25519MLKEM768 / ML-KEM) as your IPsec stack supports it.\",\n};\nconst RULE_SSHD_KEX: RuleMeta = {\n id: \"net-sshd-classical-kex\",\n title: \"SSH server offers no PQC key exchange\",\n description:\n \"sshd_config KexAlgorithms lists only classical key exchange (no sntrup761/mlkem768)\",\n category: \"key-exchange\",\n severity: \"medium\",\n confidence: \"high\",\n algorithm: \"ECDH\",\n hndl: true,\n cwe: CWE_BROKEN_CRYPTO,\n message:\n \"SSH server's KexAlgorithms offers only classical key exchange (no sntrup761x25519 / mlkem768x25519); sessions are harvest-now-decrypt-later exposed.\",\n remediation: \"Add a PQC hybrid KEX: sntrup761x25519-sha512@openssh.com or mlkem768x25519-sha256.\",\n};\n\n/** True when a KexAlgorithms value already offers a post-quantum hybrid KEX. */\nfunction offersPqKex(kexLine: string): boolean {\n return /sntrup761x25519|mlkem768/.test(kexLine);\n}\n\n/** Detects classical key exchange in WireGuard / IPsec / sshd network config. */\nexport const vpnDetector: Detector = {\n id: \"network-transport-crypto\",\n description: \"Classical key exchange in network transport / VPN config (WireGuard, IPsec, sshd)\",\n scope: \"config\",\n language: \"any\",\n rules: [RULE_WG, RULE_IPSEC_DH, RULE_IPSEC_EC, RULE_SSHD_KEX],\n appliesTo: (f) => {\n const lower = f.toLowerCase();\n const base = lower.split(\"/\").pop() ?? lower;\n return lower.endsWith(\".conf\") || base === \"sshd_config\" || base === \"ssh_config\";\n },\n detect({ file, content }): Finding[] {\n const findings: Finding[] = [];\n const push = (rule: RuleMeta, index: number, length: number) =>\n findings.push(findingFromRule(rule, { file, content, index, matchLength: length }));\n\n // WireGuard: gated to a WireGuard config section.\n if (content.includes(\"[Interface]\") || content.includes(\"[Peer]\")) {\n eachMatch(RE_WG_KEY, content, (m) => push(RULE_WG, m.index, m[0].length));\n }\n\n // IPsec / strongSwan: gated to a proposal assignment.\n if (/\\b(?:ike|esp|proposals?|keyexchange)\\s*=/i.test(content)) {\n eachMatch(RE_IPSEC_MODP, content, (m) => push(RULE_IPSEC_DH, m.index, m[0].length));\n eachMatch(RE_IPSEC_ECP, content, (m) => push(RULE_IPSEC_EC, m.index, m[0].length));\n }\n\n // sshd_config / ssh_config: KexAlgorithms line with no PQC hybrid offered.\n const base = file.toLowerCase().split(\"/\").pop() ?? \"\";\n if (base === \"sshd_config\" || base === \"ssh_config\") {\n eachMatch(RE_SSHD_KEX, content, (m) => {\n if (!offersPqKex(m[1])) push(RULE_SSHD_KEX, m.index, m[0].length);\n });\n }\n return findings;\n },\n};\n"]}
|
package/dist/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;GAIG;AACH,MAAM,OAAO,UAAW,SAAQ,KAAK;IACjB,IAAI,GAAG,YAAY,CAAC;IACtC,YAAY,OAAO,GAAG,uBAAuB;QAC3C,KAAK,CAAC,OAAO,CAAC,CAAC;IACjB,CAAC;CACF;AAED,mFAAmF;AACnF,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAC1B,IAAI,GAAG,qBAAqB,CAAC;IAC/C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;IACjB,CAAC;CACF"}
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;GAIG;AACH,MAAM,OAAO,UAAW,SAAQ,KAAK;IACjB,IAAI,GAAG,YAAY,CAAC;IACtC,YAAY,OAAO,GAAG,uBAAuB;QAC3C,KAAK,CAAC,OAAO,CAAC,CAAC;IACjB,CAAC;CACF;AAED,mFAAmF;AACnF,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAC1B,IAAI,GAAG,qBAAqB,CAAC;IAC/C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;IACjB,CAAC;CACF","sourcesContent":["/**\n * Error types thrown by {@link scan} when cooperative cancellation or a work\n * budget kicks in. Kept in their own module so every consumer (qScan, the MCP\n * server, the Action) can `instanceof`-check them without importing the scanner.\n */\n\n/**\n * Thrown when a scan is aborted via `ScanOptions.signal`. `name` is `\"AbortError\"`\n * to match the Web platform convention (`AbortController` / `DOMException`), so\n * callers that already special-case `err.name === \"AbortError\"` keep working.\n */\nexport class AbortError extends Error {\n override readonly name = \"AbortError\";\n constructor(message = \"The scan was aborted.\") {\n super(message);\n }\n}\n\n/** Thrown when a scan exceeds its `maxFiles` / `maxBytes` work budget mid-walk. */\nexport class BudgetExceededError extends Error {\n override readonly name = \"BudgetExceededError\";\n constructor(message: string) {\n super(message);\n }\n}\n"]}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { ScanResult } from "./types.js";
|
|
2
|
+
import type { CryptoPolicy, PolicyMapping } from "./policy.js";
|
|
3
|
+
/** Stable per-finding record for the evidence body (deterministic per commit). */
|
|
4
|
+
export interface EvidenceFinding {
|
|
5
|
+
ruleId: string;
|
|
6
|
+
algorithm?: string;
|
|
7
|
+
severity: string;
|
|
8
|
+
hndl: boolean;
|
|
9
|
+
file: string;
|
|
10
|
+
line: number;
|
|
11
|
+
}
|
|
12
|
+
export interface ReadinessReport {
|
|
13
|
+
reportType: "quantakrypto-readiness";
|
|
14
|
+
specVersion: 1;
|
|
15
|
+
subject: {
|
|
16
|
+
repository: string | null;
|
|
17
|
+
commit: string | null;
|
|
18
|
+
scannedRoot: string;
|
|
19
|
+
scanTimeUtc: string;
|
|
20
|
+
};
|
|
21
|
+
tool: {
|
|
22
|
+
name: "qScan";
|
|
23
|
+
version: string;
|
|
24
|
+
};
|
|
25
|
+
inventory: ScanResult["inventory"];
|
|
26
|
+
findings: EvidenceFinding[];
|
|
27
|
+
/** §4 policy verdicts, present only when a crypto policy was supplied. */
|
|
28
|
+
policyMapping?: PolicyMapping;
|
|
29
|
+
cbom: unknown;
|
|
30
|
+
attestation: {
|
|
31
|
+
/** sha256 over the canonicalized deterministic body (excludes scanTimeUtc). */
|
|
32
|
+
contentHash: string;
|
|
33
|
+
/** RFC-3161 / transparency-log token — filled by an external signer. */
|
|
34
|
+
timestamp: null;
|
|
35
|
+
/** Detached signature over `contentHash` — filled by an external signer. */
|
|
36
|
+
signature: null;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export interface ReadinessReportOptions {
|
|
40
|
+
/** Repository URL (e.g. from `GITHUB_REPOSITORY`); omitted → null. */
|
|
41
|
+
repository?: string;
|
|
42
|
+
/** Full commit SHA (e.g. from `GITHUB_SHA`); omitted → null. */
|
|
43
|
+
commit?: string;
|
|
44
|
+
/** Optional org cryptography policy — adds the §4 `policyMapping` verdicts. */
|
|
45
|
+
policy?: CryptoPolicy;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Build the A.8.24 readiness report for a scan result. The attestation's
|
|
49
|
+
* `contentHash` covers everything EXCEPT the scan timestamp and the attestation
|
|
50
|
+
* block itself, so re-running the same scan on the same commit is verifiable.
|
|
51
|
+
*/
|
|
52
|
+
export declare function buildReadinessReport(result: ScanResult, opts?: ReadinessReportOptions): ReadinessReport;
|
|
53
|
+
//# sourceMappingURL=evidence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evidence.d.ts","sourceRoot":"","sources":["../src/evidence.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI7C,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE/D,kFAAkF;AAClF,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,wBAAwB,CAAC;IACrC,WAAW,EAAE,CAAC,CAAC;IACf,OAAO,EAAE;QACP,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QACtB,WAAW,EAAE,MAAM,CAAC;QACpB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,IAAI,EAAE;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IACzC,SAAS,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC;IACnC,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,0EAA0E;IAC1E,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,IAAI,EAAE,OAAO,CAAC;IACd,WAAW,EAAE;QACX,+EAA+E;QAC/E,WAAW,EAAE,MAAM,CAAC;QACpB,wEAAwE;QACxE,SAAS,EAAE,IAAI,CAAC;QAChB,4EAA4E;QAC5E,SAAS,EAAE,IAAI,CAAC;KACjB,CAAC;CACH;AAeD,MAAM,WAAW,sBAAsB;IACrC,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gEAAgE;IAChE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+EAA+E;IAC/E,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,UAAU,EAClB,IAAI,GAAE,sBAA2B,GAChC,eAAe,CA2CjB"}
|
package/dist/evidence.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ISO/IEC 27001:2022 Annex A 8.24 evidence-chain export
|
|
3
|
+
* (docs/compliance/iso27001-a8.24-evidence.md).
|
|
4
|
+
*
|
|
5
|
+
* Emits a self-describing readiness report bundling the scan result, crypto
|
|
6
|
+
* inventory, and CycloneDX CBOM, plus an attestation carrying a DETERMINISTIC
|
|
7
|
+
* content hash — the same scan over the same commit + config yields the same
|
|
8
|
+
* hash (the volatile scan timestamp is deliberately excluded from the hashed
|
|
9
|
+
* body). Signing + RFC-3161 timestamping are left to an EXTERNAL, vetted signer
|
|
10
|
+
* (ADR-0004: this project performs no cryptography itself — it orchestrates a
|
|
11
|
+
* signer, it does not implement one). SHA-256 here is an integrity hash (a Node
|
|
12
|
+
* built-in), not an asymmetric primitive.
|
|
13
|
+
*
|
|
14
|
+
* Honesty boundary: this artifact is EVIDENCE for A.8.24, not the control. The
|
|
15
|
+
* organization still owns the cryptography policy, key management, and the
|
|
16
|
+
* conformance judgment. A clean scan is the absence of detected candidates, not
|
|
17
|
+
* proof of quantum-safety (qScan is lexical). See docs/COMPLIANCE.md §3.
|
|
18
|
+
*/
|
|
19
|
+
import { createHash } from "node:crypto";
|
|
20
|
+
import { toCbom } from "./cbom.js";
|
|
21
|
+
import { VERSION } from "./version.js";
|
|
22
|
+
import { buildPolicyMapping } from "./policy.js";
|
|
23
|
+
/** Canonical JSON: object keys sorted recursively, so the hash is reproducible. */
|
|
24
|
+
function canonicalize(value) {
|
|
25
|
+
if (Array.isArray(value))
|
|
26
|
+
return value.map(canonicalize);
|
|
27
|
+
if (value && typeof value === "object") {
|
|
28
|
+
const out = {};
|
|
29
|
+
for (const k of Object.keys(value).sort()) {
|
|
30
|
+
out[k] = canonicalize(value[k]);
|
|
31
|
+
}
|
|
32
|
+
return out;
|
|
33
|
+
}
|
|
34
|
+
return value;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Build the A.8.24 readiness report for a scan result. The attestation's
|
|
38
|
+
* `contentHash` covers everything EXCEPT the scan timestamp and the attestation
|
|
39
|
+
* block itself, so re-running the same scan on the same commit is verifiable.
|
|
40
|
+
*/
|
|
41
|
+
export function buildReadinessReport(result, opts = {}) {
|
|
42
|
+
const findings = result.findings.map((f) => ({
|
|
43
|
+
ruleId: f.ruleId,
|
|
44
|
+
...(f.algorithm ? { algorithm: f.algorithm } : {}),
|
|
45
|
+
severity: f.severity,
|
|
46
|
+
hndl: f.hndl,
|
|
47
|
+
file: f.location.file,
|
|
48
|
+
line: f.location.line,
|
|
49
|
+
}));
|
|
50
|
+
// The CBOM is a deterministic *view* of the (hashed) findings + inventory, but
|
|
51
|
+
// its CycloneDX envelope carries a volatile timestamp/serial — so it is
|
|
52
|
+
// EXCLUDED from the hashed body (its integrity follows from its hashed inputs)
|
|
53
|
+
// to keep the content hash reproducible across scan runs on the same commit.
|
|
54
|
+
// §4: if the org supplied a crypto policy, attest the per-finding verdicts too.
|
|
55
|
+
// Deterministic (same findings + policy → same mapping), so it is hashed.
|
|
56
|
+
const policyMapping = opts.policy ? buildPolicyMapping(result.findings, opts.policy) : undefined;
|
|
57
|
+
const hashableBody = {
|
|
58
|
+
reportType: "quantakrypto-readiness",
|
|
59
|
+
specVersion: 1,
|
|
60
|
+
subject: {
|
|
61
|
+
repository: opts.repository ?? null,
|
|
62
|
+
commit: opts.commit ?? null,
|
|
63
|
+
scannedRoot: result.root,
|
|
64
|
+
},
|
|
65
|
+
tool: { name: "qScan", version: VERSION },
|
|
66
|
+
inventory: result.inventory,
|
|
67
|
+
findings,
|
|
68
|
+
...(policyMapping ? { policyMapping } : {}),
|
|
69
|
+
};
|
|
70
|
+
const contentHash = "sha256:" +
|
|
71
|
+
createHash("sha256")
|
|
72
|
+
.update(JSON.stringify(canonicalize(hashableBody)))
|
|
73
|
+
.digest("hex");
|
|
74
|
+
return {
|
|
75
|
+
...hashableBody,
|
|
76
|
+
subject: { ...hashableBody.subject, scanTimeUtc: result.finishedAt },
|
|
77
|
+
cbom: toCbom(result),
|
|
78
|
+
attestation: { contentHash, timestamp: null, signature: null },
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=evidence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evidence.js","sourceRoot":"","sources":["../src/evidence.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * ISO/IEC 27001:2022 Annex A 8.24 evidence-chain export\n * (docs/compliance/iso27001-a8.24-evidence.md).\n *\n * Emits a self-describing readiness report bundling the scan result, crypto\n * inventory, and CycloneDX CBOM, plus an attestation carrying a DETERMINISTIC\n * content hash — the same scan over the same commit + config yields the same\n * hash (the volatile scan timestamp is deliberately excluded from the hashed\n * body). Signing + RFC-3161 timestamping are left to an EXTERNAL, vetted signer\n * (ADR-0004: this project performs no cryptography itself — it orchestrates a\n * signer, it does not implement one). SHA-256 here is an integrity hash (a Node\n * built-in), not an asymmetric primitive.\n *\n * Honesty boundary: this artifact is EVIDENCE for A.8.24, not the control. The\n * organization still owns the cryptography policy, key management, and the\n * conformance judgment. A clean scan is the absence of detected candidates, not\n * proof of quantum-safety (qScan is lexical). See docs/COMPLIANCE.md §3.\n */\nimport { createHash } from \"node:crypto\";\n\nimport type { ScanResult } from \"./types.js\";\nimport { toCbom } from \"./cbom.js\";\nimport { VERSION } from \"./version.js\";\nimport { buildPolicyMapping } from \"./policy.js\";\nimport type { CryptoPolicy, PolicyMapping } from \"./policy.js\";\n\n/** Stable per-finding record for the evidence body (deterministic per commit). */\nexport interface EvidenceFinding {\n ruleId: string;\n algorithm?: string;\n severity: string;\n hndl: boolean;\n file: string;\n line: number;\n}\n\nexport interface ReadinessReport {\n reportType: \"quantakrypto-readiness\";\n specVersion: 1;\n subject: {\n repository: string | null;\n commit: string | null;\n scannedRoot: string;\n scanTimeUtc: string;\n };\n tool: { name: \"qScan\"; version: string };\n inventory: ScanResult[\"inventory\"];\n findings: EvidenceFinding[];\n /** §4 policy verdicts, present only when a crypto policy was supplied. */\n policyMapping?: PolicyMapping;\n cbom: unknown;\n attestation: {\n /** sha256 over the canonicalized deterministic body (excludes scanTimeUtc). */\n contentHash: string;\n /** RFC-3161 / transparency-log token — filled by an external signer. */\n timestamp: null;\n /** Detached signature over `contentHash` — filled by an external signer. */\n signature: null;\n };\n}\n\n/** Canonical JSON: object keys sorted recursively, so the hash is reproducible. */\nfunction canonicalize(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(canonicalize);\n if (value && typeof value === \"object\") {\n const out: Record<string, unknown> = {};\n for (const k of Object.keys(value as Record<string, unknown>).sort()) {\n out[k] = canonicalize((value as Record<string, unknown>)[k]);\n }\n return out;\n }\n return value;\n}\n\nexport interface ReadinessReportOptions {\n /** Repository URL (e.g. from `GITHUB_REPOSITORY`); omitted → null. */\n repository?: string;\n /** Full commit SHA (e.g. from `GITHUB_SHA`); omitted → null. */\n commit?: string;\n /** Optional org cryptography policy — adds the §4 `policyMapping` verdicts. */\n policy?: CryptoPolicy;\n}\n\n/**\n * Build the A.8.24 readiness report for a scan result. The attestation's\n * `contentHash` covers everything EXCEPT the scan timestamp and the attestation\n * block itself, so re-running the same scan on the same commit is verifiable.\n */\nexport function buildReadinessReport(\n result: ScanResult,\n opts: ReadinessReportOptions = {},\n): ReadinessReport {\n const findings: EvidenceFinding[] = result.findings.map((f) => ({\n ruleId: f.ruleId,\n ...(f.algorithm ? { algorithm: f.algorithm } : {}),\n severity: f.severity,\n hndl: f.hndl,\n file: f.location.file,\n line: f.location.line,\n }));\n\n // The CBOM is a deterministic *view* of the (hashed) findings + inventory, but\n // its CycloneDX envelope carries a volatile timestamp/serial — so it is\n // EXCLUDED from the hashed body (its integrity follows from its hashed inputs)\n // to keep the content hash reproducible across scan runs on the same commit.\n // §4: if the org supplied a crypto policy, attest the per-finding verdicts too.\n // Deterministic (same findings + policy → same mapping), so it is hashed.\n const policyMapping = opts.policy ? buildPolicyMapping(result.findings, opts.policy) : undefined;\n\n const hashableBody = {\n reportType: \"quantakrypto-readiness\",\n specVersion: 1,\n subject: {\n repository: opts.repository ?? null,\n commit: opts.commit ?? null,\n scannedRoot: result.root,\n },\n tool: { name: \"qScan\", version: VERSION },\n inventory: result.inventory,\n findings,\n ...(policyMapping ? { policyMapping } : {}),\n };\n const contentHash =\n \"sha256:\" +\n createHash(\"sha256\")\n .update(JSON.stringify(canonicalize(hashableBody)))\n .digest(\"hex\");\n\n return {\n ...hashableBody,\n subject: { ...hashableBody.subject, scanTimeUtc: result.finishedAt },\n cbom: toCbom(result),\n attestation: { contentHash, timestamp: null, signature: null },\n } as ReadinessReport;\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -42,11 +42,18 @@ export { isAnalyzableSource, ANALYZABLE_SOURCE_EXTENSIONS, ANALYZABLE_LANGUAGES_
|
|
|
42
42
|
export { buildInventory } from "./inventory.js";
|
|
43
43
|
export { vulnerableDependencies, DEP_VULNERABLE_RULE, isManifestFile } from "./dependencies.js";
|
|
44
44
|
export { SEVERITY_ORDER, severityRank, meetsThreshold, sarifLevel } from "./severity.js";
|
|
45
|
-
export { toSarif, toJson, formatSummary } from "./report.js";
|
|
45
|
+
export { toSarif, toJson, formatSummary, formatTierGuidance } from "./report.js";
|
|
46
46
|
export type { ReportOptions } from "./report.js";
|
|
47
47
|
export { toCbom } from "./cbom.js";
|
|
48
48
|
export type { CycloneDxBom, CbomComponent } from "./cbom.js";
|
|
49
|
-
export {
|
|
49
|
+
export { mergeCboms } from "./cbom-merge.js";
|
|
50
|
+
export { buildReadinessReport } from "./evidence.js";
|
|
51
|
+
export type { ReadinessReport, EvidenceFinding, ReadinessReportOptions } from "./evidence.js";
|
|
52
|
+
export { buildPolicyMapping, parseCryptoPolicy, verdictForAlgorithm } from "./policy.js";
|
|
53
|
+
export type { CryptoPolicy, PolicyVerdict, PolicyMapping, PolicyFindingVerdict } from "./policy.js";
|
|
54
|
+
export { remediationFor, remediationForTier, TIER_PARAMS, STATEFUL_HBS_NOTE, PQC_TRANSITION_NOTE, statefulHbsApplies, } from "./remediation.js";
|
|
50
55
|
export type { SecurityTier } from "./remediation.js";
|
|
56
|
+
export { PQC_STANDARDS, standardsReviewStatus } from "./standards.js";
|
|
57
|
+
export type { PqcStandards, StandardsCitation, StandardsReviewStatus } from "./standards.js";
|
|
51
58
|
export { CWE_BROKEN_CRYPTO, CWE_WEAK_STRENGTH, CWE_CERT_VALIDATION, CWE_HARDCODED_KEY, CWE_RISKY_PRIMITIVE, } from "./cwe.js";
|
|
52
59
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -47,11 +47,19 @@ export { vulnerableDependencies, DEP_VULNERABLE_RULE, isManifestFile } from "./d
|
|
|
47
47
|
// Severity utilities (ordering, threshold, SARIF level) — shared across tools.
|
|
48
48
|
export { SEVERITY_ORDER, severityRank, meetsThreshold, sarifLevel } from "./severity.js";
|
|
49
49
|
// Reporters.
|
|
50
|
-
export { toSarif, toJson, formatSummary } from "./report.js";
|
|
50
|
+
export { toSarif, toJson, formatSummary, formatTierGuidance } from "./report.js";
|
|
51
51
|
// CycloneDX 1.6 cryptographic bill of materials (CBOM) export.
|
|
52
52
|
export { toCbom } from "./cbom.js";
|
|
53
|
+
// Merge multiple CBOMs (code + infra + live endpoints) into one combined BOM.
|
|
54
|
+
export { mergeCboms } from "./cbom-merge.js";
|
|
55
|
+
// ISO/IEC 27001 A.8.24 evidence-chain readiness report.
|
|
56
|
+
export { buildReadinessReport } from "./evidence.js";
|
|
57
|
+
// Cryptography policy → per-finding verdicts (A.8.24 evidence §4).
|
|
58
|
+
export { buildPolicyMapping, parseCryptoPolicy, verdictForAlgorithm } from "./policy.js";
|
|
53
59
|
// Remediation lookup (family + tier-aware) and stateful-HBS guidance.
|
|
54
|
-
export { remediationFor, remediationForTier, TIER_PARAMS, STATEFUL_HBS_NOTE, statefulHbsApplies, } from "./remediation.js";
|
|
60
|
+
export { remediationFor, remediationForTier, TIER_PARAMS, STATEFUL_HBS_NOTE, PQC_TRANSITION_NOTE, statefulHbsApplies, } from "./remediation.js";
|
|
61
|
+
// Post-quantum standards source of truth + review cadence.
|
|
62
|
+
export { PQC_STANDARDS, standardsReviewStatus } from "./standards.js";
|
|
55
63
|
// CWE identifier constants.
|
|
56
64
|
export { CWE_BROKEN_CRYPTO, CWE_WEAK_STRENGTH, CWE_CERT_VALIDATION, CWE_HARDCODED_KEY, CWE_RISKY_PRIMITIVE, } from "./cwe.js";
|
|
57
65
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,cAAc,YAAY,CAAC;AAE3B,qEAAqE;AACrE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAKvC,8CAA8C;AAC9C,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEzE,2EAA2E;AAC3E,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAW7D,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEvF,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAErE,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAQ5D,0CAA0C;AAC1C,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAE9D,sEAAsE;AACtE,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAG9E,iEAAiE;AACjE,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAGjF,qDAAqD;AACrD,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,gBAAgB,GACjB,MAAM,eAAe,CAAC;AAGvB,oEAAoE;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,yEAAyE;AACzE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGvE,kFAAkF;AAClF,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAEpF,8EAA8E;AAC9E,OAAO,EACL,kBAAkB,EAClB,4BAA4B,EAC5B,0BAA0B,GAC3B,MAAM,mBAAmB,CAAC;AAE3B,+BAA+B;AAC/B,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD,sFAAsF;AACtF,6EAA6E;AAC7E,gFAAgF;AAChF,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEhG,+EAA+E;AAC/E,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEzF,aAAa;AACb,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @quantakrypto/core — public API (LOCKED CONTRACT).\n *\n * The exported NAMES and SIGNATURES below are the stable contract that\n * @quantakrypto/qscan, @quantakrypto/mcp and the GitHub Action depend on — do not change\n * them without updating all consumers. The implementations live in focused\n * modules under src/ and are re-exported here; the public surface is identical\n * to the original stub file.\n */\nexport * from \"./types.js\";\n\n// Tool version, surfaced in reports. Keep in sync with package.json.\nexport { VERSION } from \"./version.js\";\n\n// Minimal SARIF 2.1.0 log shape, defined alongside the reporters.\nexport type { SarifLog } from \"./report.js\";\n\n// Core orchestration + built-in detector set.\nexport { scan, detectors, detectFile, compareFindings } from \"./scan.js\";\n\n// Snippet-level fix verification (shared by MCP verify_fix + remediation).\nexport { verifyFix, languageToExtension } from \"./verify.js\";\nexport type { VerifyResult } from \"./verify.js\";\n\n// Agent-plane shared types + the context redactor (offline; reused by MCP).\nexport type {\n ContextLevel,\n RedactedContext,\n TriageVerdict,\n Patch,\n FixProposal,\n} from \"./agent-types.js\";\nexport { buildContext, renderPreflight } from \"./redact.js\";\nexport { TRIAGE_RUBRIC, TRIAGE_VERDICT_SCHEMA, buildTriageRequest } from \"./triage.js\";\nexport type { TriageRequest } from \"./triage.js\";\nexport {\n REMEDIATE_RUBRIC,\n FIX_REQUEST_SCHEMA,\n buildRemediateRequest,\n} from \"./remediate-request.js\";\nexport type { RemediateRequest } from \"./remediate-request.js\";\nexport { checkPatchPolicy } from \"./patch-policy.js\";\nexport type { PolicyContext, PolicyDecision } from \"./patch-policy.js\";\nexport { withWorktree } from \"./worktree.js\";\nexport { codemodRegistry, codemodFor } from \"./codemods/registry.js\";\nexport type { Codemod } from \"./codemods/registry.js\";\nexport { configToggleCodemod } from \"./codemods/config-toggle.js\";\nexport { remediateFindings } from \"./remediate-pipeline.js\";\nexport type {\n RemediateOptions,\n RemediationResult,\n VerifiedPatch,\n RejectedPatch,\n} from \"./remediate-pipeline.js\";\n\n// Scan cancellation / work-budget errors.\nexport { AbortError, BudgetExceededError } from \"./errors.js\";\n\n// Parallel scanning (worker_threads pool) + pure merge/chunk helpers.\nexport { scanParallel, mergeChunkResults, chunkByBytes } from \"./parallel.js\";\nexport type { ScanChunk, ChunkResult, SizedFile } from \"./parallel.js\";\n\n// Detector registry (plugin point) + helpers + the rule catalog.\nexport { DetectorRegistry, defaultRegistry, detectorScope } from \"./registry.js\";\nexport type { RuleCatalogEntry } from \"./registry.js\";\n\n// Canonical baseline (shared by qScan + the Action).\nexport {\n fingerprintFinding,\n baselineFromFindings,\n applyBaseline,\n loadBaseline,\n saveBaseline,\n BASELINE_VERSION,\n} from \"./baseline.js\";\nexport type { Baseline } from \"./baseline.js\";\n\n// Incremental scanning: changed-files helper (git-aware, tolerant).\nexport { changedFiles } from \"./changed.js\";\n\n// Optional `quantakrypto.config.json` loader (P2-9; see docs/CONFIG.md).\nexport { loadConfig, ConfigError, CONFIG_FILENAME } from \"./config.js\";\nexport type { QuantakryptoFileConfig, LoadConfigResult } from \"./config.js\";\n\n// Filesystem walker (relative POSIX paths, default ignores, size/binary filters).\nexport { walkFiles, isBinaryPath, isGeneratedPath, looksMinified } from \"./walk.js\";\n\n// Analyzable-language coverage (which source languages the scanner inspects).\nexport {\n isAnalyzableSource,\n ANALYZABLE_SOURCE_EXTENSIONS,\n ANALYZABLE_LANGUAGES_LABEL,\n} from \"./detect-utils.js\";\n\n// Inventory + readiness score.\nexport { buildInventory } from \"./inventory.js\";\n\n// Vulnerable-dependency database (the manifest scanner is used internally by scan()).\n// `DEP_VULNERABLE_RULE` is the generic catalog entry for dependency findings\n// (which don't come from a Detector, so aren't in the registry's rule catalog).\nexport { vulnerableDependencies, DEP_VULNERABLE_RULE, isManifestFile } from \"./dependencies.js\";\n\n// Severity utilities (ordering, threshold, SARIF level) — shared across tools.\nexport { SEVERITY_ORDER, severityRank, meetsThreshold, sarifLevel } from \"./severity.js\";\n\n// Reporters.\nexport { toSarif, toJson, formatSummary, formatTierGuidance } from \"./report.js\";\nexport type { ReportOptions } from \"./report.js\";\n\n// CycloneDX 1.6 cryptographic bill of materials (CBOM) export.\nexport { toCbom } from \"./cbom.js\";\nexport type { CycloneDxBom, CbomComponent } from \"./cbom.js\";\n// Merge multiple CBOMs (code + infra + live endpoints) into one combined BOM.\nexport { mergeCboms } from \"./cbom-merge.js\";\n// ISO/IEC 27001 A.8.24 evidence-chain readiness report.\nexport { buildReadinessReport } from \"./evidence.js\";\nexport type { ReadinessReport, EvidenceFinding, ReadinessReportOptions } from \"./evidence.js\";\n\n// Cryptography policy → per-finding verdicts (A.8.24 evidence §4).\nexport { buildPolicyMapping, parseCryptoPolicy, verdictForAlgorithm } from \"./policy.js\";\nexport type { CryptoPolicy, PolicyVerdict, PolicyMapping, PolicyFindingVerdict } from \"./policy.js\";\n\n// Remediation lookup (family + tier-aware) and stateful-HBS guidance.\nexport {\n remediationFor,\n remediationForTier,\n TIER_PARAMS,\n STATEFUL_HBS_NOTE,\n PQC_TRANSITION_NOTE,\n statefulHbsApplies,\n} from \"./remediation.js\";\nexport type { SecurityTier } from \"./remediation.js\";\n\n// Post-quantum standards source of truth + review cadence.\nexport { PQC_STANDARDS, standardsReviewStatus } from \"./standards.js\";\nexport type { PqcStandards, StandardsCitation, StandardsReviewStatus } from \"./standards.js\";\n\n// CWE identifier constants.\nexport {\n CWE_BROKEN_CRYPTO,\n CWE_WEAK_STRENGTH,\n CWE_CERT_VALIDATION,\n CWE_HARDCODED_KEY,\n CWE_RISKY_PRIMITIVE,\n} from \"./cwe.js\";\n"]}
|
package/dist/inventory.d.ts
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* and a 0–100 readiness score.
|
|
5
5
|
*/
|
|
6
6
|
import type { CryptoInventory, Finding } from "./types.js";
|
|
7
|
+
/** True when a finding's file path is test / fixture / example / documentation. */
|
|
8
|
+
export declare function isTestOrFixturePath(file: string): boolean;
|
|
7
9
|
/**
|
|
8
10
|
* Compute a 0–100 readiness score. 100 means no classical asymmetric crypto was
|
|
9
11
|
* found. Findings accrue a severity-weighted penalty (with per-bucket diminishing
|
package/dist/inventory.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inventory.d.ts","sourceRoot":"","sources":["../src/inventory.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAEV,eAAe,EACf,OAAO,EAGR,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"inventory.d.ts","sourceRoot":"","sources":["../src/inventory.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAEV,eAAe,EACf,OAAO,EAGR,MAAM,YAAY,CAAC;AAsCpB,mFAAmF;AACnF,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAczD;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,CAoB1D;AAED,+EAA+E;AAC/E,wBAAgB,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,eAAe,CAgCnE"}
|
package/dist/inventory.js
CHANGED
|
@@ -19,6 +19,31 @@ function penaltyFor(weight, occurrence) {
|
|
|
19
19
|
}
|
|
20
20
|
/** Decay constant for the readiness score (larger = more forgiving). */
|
|
21
21
|
const SCORE_SCALE = 100;
|
|
22
|
+
/**
|
|
23
|
+
* Fraction of the normal penalty a finding in test/fixture/example/doc code
|
|
24
|
+
* contributes to the readiness score. Such findings are almost always test
|
|
25
|
+
* vectors, sample keys, or the library's own algorithm enumerations — accurate
|
|
26
|
+
* detections, but not the deployed crypto whose migration the score is meant to
|
|
27
|
+
* track. Real-repo runs showed 60–77% of findings live in these paths, which
|
|
28
|
+
* dragged the score of no-real-crypto codebases down unfairly. They still appear
|
|
29
|
+
* in the inventory counts in full; only their *score* weight is reduced.
|
|
30
|
+
*/
|
|
31
|
+
const TEST_PATH_WEIGHT = 0.15;
|
|
32
|
+
/** True when a finding's file path is test / fixture / example / documentation. */
|
|
33
|
+
export function isTestOrFixturePath(file) {
|
|
34
|
+
const f = file.toLowerCase().replace(/\\/g, "/");
|
|
35
|
+
if (/(?:^|\/)(?:tests?|__tests__|testdata|test-data|fixtures?|examples?|demos?|samples?|specs?|mocks?|docs?|benchmarks?|e2e)\//.test(f)) {
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
const base = f.slice(f.lastIndexOf("/") + 1);
|
|
39
|
+
if (/(?:^|[_.-])(?:test|spec)\.[a-z0-9]+$/.test(base))
|
|
40
|
+
return true; // test.go, foo_test.go, foo.test.ts
|
|
41
|
+
if (/^test_[^/]+\.py$/.test(base))
|
|
42
|
+
return true; // python test_foo.py
|
|
43
|
+
if (/^changelog/.test(base) || /\.(?:md|markdown|rst|adoc|asciidoc)$/.test(base))
|
|
44
|
+
return true;
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
22
47
|
/**
|
|
23
48
|
* Compute a 0–100 readiness score. 100 means no classical asymmetric crypto was
|
|
24
49
|
* found. Findings accrue a severity-weighted penalty (with per-bucket diminishing
|
|
@@ -40,7 +65,8 @@ export function readinessScore(findings) {
|
|
|
40
65
|
let penalty = 0;
|
|
41
66
|
for (const f of findings) {
|
|
42
67
|
seen[f.severity] += 1;
|
|
43
|
-
|
|
68
|
+
const weight = SEVERITY_WEIGHT[f.severity] * (isTestOrFixturePath(f.location.file) ? TEST_PATH_WEIGHT : 1);
|
|
69
|
+
penalty += penaltyFor(weight, seen[f.severity]);
|
|
44
70
|
}
|
|
45
71
|
return Math.max(0, Math.min(100, Math.round(100 * Math.exp(-penalty / SCORE_SCALE))));
|
|
46
72
|
}
|
package/dist/inventory.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inventory.js","sourceRoot":"","sources":["../src/inventory.ts"],"names":[],"mappings":"AAaA,4EAA4E;AAC5E,MAAM,UAAU,GAAe,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;AAE7E,uFAAuF;AACvF,MAAM,eAAe,GAA6B;IAChD,QAAQ,EAAE,EAAE;IACZ,IAAI,EAAE,EAAE;IACR,MAAM,EAAE,CAAC;IACT,GAAG,EAAE,CAAC;IACN,IAAI,EAAE,CAAC;CACR,CAAC;AAEF;;;;;GAKG;AACH,SAAS,UAAU,CAAC,MAAc,EAAE,UAAkB;IACpD,OAAO,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AACxC,CAAC;AAED,wEAAwE;AACxE,MAAM,WAAW,GAAG,GAAG,CAAC;AAExB;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,QAAmB;IAChD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC;IAEtC,MAAM,IAAI,GAA6B;QACrC,QAAQ,EAAE,CAAC;QACX,IAAI,EAAE,CAAC;QACP,MAAM,EAAE,CAAC;QACT,GAAG,EAAE,CAAC;QACN,IAAI,EAAE,CAAC;KACR,CAAC;IAEF,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACtB,
|
|
1
|
+
{"version":3,"file":"inventory.js","sourceRoot":"","sources":["../src/inventory.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Aggregates findings into a {@link CryptoInventory}: per-algorithm,\n * per-category and per-severity counts, the harvest-now-decrypt-later count,\n * and a 0–100 readiness score.\n */\nimport type {\n AlgorithmFamily,\n CryptoInventory,\n Finding,\n FindingCategory,\n Severity,\n} from \"./types.js\";\n\n/** All severities, most → least severe (used to seed the counts record). */\nconst SEVERITIES: Severity[] = [\"critical\", \"high\", \"medium\", \"low\", \"info\"];\n\n/** Base penalty applied to the readiness score for the first finding of a severity. */\nconst SEVERITY_WEIGHT: Record<Severity, number> = {\n critical: 30,\n high: 18,\n medium: 8,\n low: 3,\n info: 1,\n};\n\n/**\n * Apply diminishing returns to repeated findings of the same severity: the Nth\n * finding contributes `weight / sqrt(N)`. This keeps a single critical hit very\n * impactful while a codebase with hundreds of medium findings doesn't underflow\n * past zero on the first few — the score still saturates toward 0 sensibly.\n */\nfunction penaltyFor(weight: number, occurrence: number): number {\n return weight / Math.sqrt(occurrence);\n}\n\n/** Decay constant for the readiness score (larger = more forgiving). */\nconst SCORE_SCALE = 100;\n\n/**\n * Fraction of the normal penalty a finding in test/fixture/example/doc code\n * contributes to the readiness score. Such findings are almost always test\n * vectors, sample keys, or the library's own algorithm enumerations — accurate\n * detections, but not the deployed crypto whose migration the score is meant to\n * track. Real-repo runs showed 60–77% of findings live in these paths, which\n * dragged the score of no-real-crypto codebases down unfairly. They still appear\n * in the inventory counts in full; only their *score* weight is reduced.\n */\nconst TEST_PATH_WEIGHT = 0.15;\n\n/** True when a finding's file path is test / fixture / example / documentation. */\nexport function isTestOrFixturePath(file: string): boolean {\n const f = file.toLowerCase().replace(/\\\\/g, \"/\");\n if (\n /(?:^|\\/)(?:tests?|__tests__|testdata|test-data|fixtures?|examples?|demos?|samples?|specs?|mocks?|docs?|benchmarks?|e2e)\\//.test(\n f,\n )\n ) {\n return true;\n }\n const base = f.slice(f.lastIndexOf(\"/\") + 1);\n if (/(?:^|[_.-])(?:test|spec)\\.[a-z0-9]+$/.test(base)) return true; // test.go, foo_test.go, foo.test.ts\n if (/^test_[^/]+\\.py$/.test(base)) return true; // python test_foo.py\n if (/^changelog/.test(base) || /\\.(?:md|markdown|rst|adoc|asciidoc)$/.test(base)) return true;\n return false;\n}\n\n/**\n * Compute a 0–100 readiness score. 100 means no classical asymmetric crypto was\n * found. Findings accrue a severity-weighted penalty (with per-bucket diminishing\n * returns), then the score is `100 * e^(-penalty/scale)`. Exponential decay keeps\n * the score responsive across the whole range — fixing findings always raises it,\n * and a large legacy repo lands low without pinning flat at 0 (which made progress\n * invisible under the old linear model). Tuned so one low ~97, one critical ~74.\n */\nexport function readinessScore(findings: Finding[]): number {\n if (findings.length === 0) return 100;\n\n const seen: Record<Severity, number> = {\n critical: 0,\n high: 0,\n medium: 0,\n low: 0,\n info: 0,\n };\n\n let penalty = 0;\n for (const f of findings) {\n seen[f.severity] += 1;\n const weight =\n SEVERITY_WEIGHT[f.severity] * (isTestOrFixturePath(f.location.file) ? TEST_PATH_WEIGHT : 1);\n penalty += penaltyFor(weight, seen[f.severity]);\n }\n\n return Math.max(0, Math.min(100, Math.round(100 * Math.exp(-penalty / SCORE_SCALE))));\n}\n\n/** Build the full inventory (counts + HNDL + score) from a set of findings. */\nexport function buildInventory(findings: Finding[]): CryptoInventory {\n const byAlgorithm: Partial<Record<AlgorithmFamily, number>> = {};\n const byCategory: Partial<Record<FindingCategory, number>> = {};\n const bySeverity: Record<Severity, number> = {\n critical: 0,\n high: 0,\n medium: 0,\n low: 0,\n info: 0,\n };\n let hndlCount = 0;\n\n for (const f of findings) {\n if (f.algorithm) {\n byAlgorithm[f.algorithm] = (byAlgorithm[f.algorithm] ?? 0) + 1;\n }\n byCategory[f.category] = (byCategory[f.category] ?? 0) + 1;\n bySeverity[f.severity] += 1;\n if (f.hndl) hndlCount += 1;\n }\n\n // Ensure all severities are present (seeded above to 0). SEVERITIES is the\n // canonical ordering and guards against missing keys if the type changes.\n void SEVERITIES;\n\n return {\n byAlgorithm,\n byCategory,\n bySeverity,\n hndlCount,\n readinessScore: readinessScore(findings),\n };\n}\n"]}
|
package/dist/parallel.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parallel.js","sourceRoot":"","sources":["../src/parallel.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"parallel.js","sourceRoot":"","sources":["../src/parallel.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Parallel scanning over a worker-thread pool (P2-1). The scan is embarrassingly\n * parallel: each file is read and regex-scanned independently, and the merge is\n * a concatenation + the existing deterministic sort. `Finding` is plain\n * structured-cloneable data, so it crosses the worker boundary cleanly.\n *\n * The merge and chunking logic are pure and exported for direct unit testing.\n * `scanParallel` falls back to the in-process serial path below the crossover\n * (small file counts / small total bytes) and whenever workers are unavailable.\n */\nimport { stat } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport type { Worker as NodeWorker } from \"node:worker_threads\";\n\nimport type { Finding, ParallelScanOptions, ScanResult } from \"./types.js\";\nimport { walkFiles } from \"./walk.js\";\nimport { isAnalyzableSource } from \"./detect-utils.js\";\nimport { buildInventory } from \"./inventory.js\";\nimport { compareFindings, filterExplicitFileList, scan } from \"./scan.js\";\nimport { AbortError, BudgetExceededError } from \"./errors.js\";\nimport { VERSION } from \"./version.js\";\n\n/** One unit of work dispatched to a worker. */\nexport interface ScanChunk {\n files: string[];\n}\n\n/** What a worker returns for a chunk. */\nexport interface ChunkResult {\n findings: Finding[];\n filesScanned: number;\n /** Files that couldn't be read in this chunk (optional; older workers omit it). */\n unreadable?: number;\n /** Files skipped as minified in this chunk (optional; older workers omit it). */\n skippedMinified?: number;\n}\n\nconst DEFAULT_PARALLEL_THRESHOLD_BYTES = 2 * 1024 * 1024;\nconst DEFAULT_PARALLEL_FILE_THRESHOLD = 200;\nconst DEFAULT_CHUNK_BYTES = 4 * 1024 * 1024;\n\n/** A file plus its byte size, used for byte-balanced chunking. */\nexport interface SizedFile {\n rel: string;\n size: number;\n}\n\n/**\n * Bucket files into chunks of roughly `chunkBytes` total bytes each, so one\n * large file doesn't starve a worker holding many tiny files. Pure +\n * deterministic: input order is preserved within and across chunks.\n */\nexport function chunkByBytes(files: readonly SizedFile[], chunkBytes: number): ScanChunk[] {\n const limit = Math.max(1, chunkBytes);\n const chunks: ScanChunk[] = [];\n let current: string[] = [];\n let currentBytes = 0;\n for (const f of files) {\n if (current.length > 0 && currentBytes + f.size > limit) {\n chunks.push({ files: current });\n current = [];\n currentBytes = 0;\n }\n current.push(f.rel);\n currentBytes += f.size;\n }\n if (current.length > 0) chunks.push({ files: current });\n return chunks;\n}\n\n/**\n * Merge per-chunk results into a single ordered finding set + total file count.\n * Pure: applies the SAME comparator as the serial scan, so the result is\n * byte-identical regardless of chunk completion order. Exported for unit tests.\n */\nexport function mergeChunkResults(results: readonly ChunkResult[]): ChunkResult {\n const findings: Finding[] = [];\n let filesScanned = 0;\n let unreadable = 0;\n let skippedMinified = 0;\n for (const r of results) {\n for (const f of r.findings) findings.push(f);\n filesScanned += r.filesScanned;\n unreadable += r.unreadable ?? 0;\n skippedMinified += r.skippedMinified ?? 0;\n }\n findings.sort(compareFindings);\n return { findings, filesScanned, unreadable, skippedMinified };\n}\n\n/** Resolve the worker count (>= 1). */\nfunction resolveConcurrency(options: ParallelScanOptions): number {\n const raw = options.concurrency;\n if (typeof raw === \"number\" && raw >= 1) return Math.floor(raw);\n const avail =\n typeof os.availableParallelism === \"function\" ? os.availableParallelism() : os.cpus().length;\n return Math.max(1, avail);\n}\n\n/** Decide whether the workload is large enough to justify spawning workers. */\nfunction shouldParallelize(options: ParallelScanOptions, files: SizedFile[]): boolean {\n const totalBytes = files.reduce((acc, f) => acc + f.size, 0);\n const byteFloor = options.parallelThresholdBytes ?? DEFAULT_PARALLEL_THRESHOLD_BYTES;\n const fileFloor = options.parallelFileThreshold ?? DEFAULT_PARALLEL_FILE_THRESHOLD;\n if (resolveConcurrency(options) <= 1) return false;\n return totalBytes >= byteFloor && files.length >= fileFloor;\n}\n\n/**\n * Enumerate the files to scan (relative POSIX paths + sizes), honouring an\n * explicit `files` list or the walker. Sizes power byte-balanced chunking.\n */\nasync function enumerateFiles(options: ParallelScanOptions, baseDir: string): Promise<SizedFile[]> {\n const rels: string[] = [];\n if (options.files) {\n // Apply the SAME include/exclude/binary filtering the serial path uses via\n // `filterExplicitFiles`, so `--parallel` is byte-for-byte identical to serial.\n for (const rel of filterExplicitFileList(options.files, options)) rels.push(rel);\n } else {\n for await (const rel of walkFiles(options.root, {\n include: options.include,\n exclude: options.exclude,\n noDefaultIgnores: options.noDefaultIgnores,\n maxFileSize: options.maxFileSize,\n })) {\n rels.push(rel);\n }\n }\n\n const sized: SizedFile[] = [];\n for (const rel of rels) {\n let size = 0;\n try {\n size = (await stat(path.join(baseDir, ...rel.split(\"/\")))).size;\n } catch {\n // Unreadable now; keep with size 0 — worker read will skip if it's gone.\n }\n sized.push({ rel, size });\n }\n return sized;\n}\n\n/**\n * Resolve the worker entry next to this module. In a normal build it's\n * `dist/scan-worker.js`. When running from source under a TypeScript loader\n * (tsx) the built JS doesn't exist, so fall back to `scan-worker.ts` and tell\n * the worker to load tsx as well — so the parallel scanner works in dev/source\n * mode (and is exercisable by tests), not only after a build.\n */\nfunction workerEntry(): { entry: string; execArgv?: string[] } {\n const here = fileURLToPath(import.meta.url);\n const dir = path.dirname(here);\n const js = path.join(dir, \"scan-worker.js\");\n if (existsSync(js)) return { entry: js };\n const ts = path.join(dir, \"scan-worker.ts\");\n if (existsSync(ts)) return { entry: ts, execArgv: [\"--import\", \"tsx\"] };\n return { entry: js }; // neither present: let Worker surface a clear ENOENT\n}\n\n/**\n * Scan in parallel across a worker-thread pool, falling back to the in-process\n * serial {@link scan} for small workloads or when workers can't be used. The\n * result is deterministic and identical to the serial path.\n */\nexport async function scanParallel(options: ParallelScanOptions): Promise<ScanResult> {\n const startedAt = new Date();\n\n const rootStat = await stat(options.root);\n const baseDir = rootStat.isFile() ? path.dirname(options.root) : options.root;\n\n // Single-file roots, the override-detectors path, and the scan cache always\n // run serially: detectors may not be structured-cloneable across the worker\n // boundary, and the cache read/write is owned by the in-process `scan()`.\n if (rootStat.isFile() || options.detectors || options.cacheFile) {\n return scan(options);\n }\n\n const files = await enumerateFiles(options, baseDir);\n\n // Budget + cancellation parity with the serial path. The parallel path\n // enumerates upfront, so budgets are enforced against the whole file set\n // before any worker is dispatched.\n if (options.signal?.aborted) throw new AbortError();\n if (typeof options.maxFiles === \"number\" && files.length > options.maxFiles) {\n throw new BudgetExceededError(`maxFiles budget exceeded (limit: ${options.maxFiles}).`);\n }\n if (typeof options.maxBytes === \"number\") {\n const totalBytes = files.reduce((n, f) => n + f.size, 0);\n if (totalBytes > options.maxBytes) {\n throw new BudgetExceededError(`maxBytes budget exceeded (limit: ${options.maxBytes}).`);\n }\n }\n\n if (!shouldParallelize(options, files)) {\n // In-process: reuse the exact serial path over the same file list.\n return scan({ ...options, files: files.map((f) => f.rel) });\n }\n\n let WorkerCtor: typeof import(\"node:worker_threads\").Worker;\n try {\n ({ Worker: WorkerCtor } = await import(\"node:worker_threads\"));\n } catch {\n return scan({ ...options, files: files.map((f) => f.rel) });\n }\n\n const chunks = chunkByBytes(files, options.chunkBytes ?? DEFAULT_CHUNK_BYTES);\n const concurrency = Math.min(resolveConcurrency(options), chunks.length);\n const { entry, execArgv } = workerEntry();\n\n const toggles = {\n source: options.source !== false,\n config: options.config !== false,\n deps: options.dependencies !== false,\n scanMinified: options.scanMinified === true,\n // Plain string array — structured-cloneable, so it crosses the worker boundary.\n disabledRules: options.disabledRules,\n };\n\n let results: ChunkResult[];\n try {\n results = await runPool(\n WorkerCtor,\n entry,\n execArgv,\n baseDir,\n toggles,\n chunks,\n concurrency,\n options.onFile,\n options.signal,\n );\n } catch (err) {\n // Cancellation / budget overflow must propagate, not silently degrade.\n if (err instanceof AbortError || err instanceof BudgetExceededError) throw err;\n // Any other worker failure → safe fallback to the serial path.\n return scan({ ...options, files: files.map((f) => f.rel) });\n }\n\n const merged = mergeChunkResults(results);\n const inventory = buildInventory(merged.findings);\n const finishedAt = new Date();\n\n // Coverage: count analyzable-source files in the enumerated set. Computed from\n // the file list (not per-worker) to avoid worker-boundary plumbing; on the\n // parallel path this can include a minified analyzable file the workers\n // skipped, but that is vanishingly rare and never under-reports coverage.\n const analyzedFiles = files.reduce((n, f) => (isAnalyzableSource(f.rel) ? n + 1 : n), 0);\n\n return {\n root: options.root,\n findings: merged.findings,\n filesScanned: merged.filesScanned,\n analyzedFiles,\n diagnostics: {\n unreadable: merged.unreadable ?? 0,\n skippedMinified: merged.skippedMinified ?? 0,\n },\n inventory,\n startedAt: startedAt.toISOString(),\n finishedAt: finishedAt.toISOString(),\n toolVersion: VERSION,\n };\n}\n\n/** Worker-pool driver: at most `concurrency` workers, each pulls chunks. */\nfunction runPool(\n WorkerCtor: typeof import(\"node:worker_threads\").Worker,\n entry: string,\n execArgv: string[] | undefined,\n baseDir: string,\n toggles: {\n source: boolean;\n config: boolean;\n deps: boolean;\n scanMinified: boolean;\n disabledRules?: string[];\n },\n chunks: ScanChunk[],\n concurrency: number,\n onFile?: (file: string) => void,\n signal?: AbortSignal,\n): Promise<ChunkResult[]> {\n return new Promise((resolve, reject) => {\n const results: ChunkResult[] = new Array(chunks.length);\n let next = 0;\n let done = 0;\n let failed = false;\n const workers: Array<NodeWorker> = [];\n\n const onAbort = (): void => {\n if (failed) return;\n failed = true;\n cleanup();\n reject(new AbortError());\n };\n\n const cleanup = () => {\n if (signal) signal.removeEventListener(\"abort\", onAbort);\n for (const w of workers) void w.terminate();\n };\n\n // Cooperative cancellation: stop dispatching and tear down on abort.\n if (signal) {\n if (signal.aborted) {\n reject(new AbortError());\n return;\n }\n signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n\n // Workers we intentionally terminate (no more chunks / on cleanup). Their\n // `exit` event is expected and must NOT be treated as a crash.\n const retired = new WeakSet<NodeWorker>();\n\n const dispatch = (w: NodeWorker): void => {\n if (failed) return;\n if (next >= chunks.length) {\n retired.add(w);\n void w.terminate();\n return;\n }\n const idx = next++;\n w.postMessage({ index: idx, files: chunks[idx].files });\n };\n\n const spawn = (): NodeWorker => {\n const w = new WorkerCtor(entry, {\n workerData: { baseDir, toggles },\n ...(execArgv ? { execArgv } : {}),\n });\n w.on(\n \"message\",\n (msg: { index: number; result?: ChunkResult; files?: string[]; error?: string }) => {\n if (msg.error) {\n if (!failed) {\n failed = true;\n cleanup();\n reject(new Error(msg.error));\n }\n return;\n }\n if (msg.files && onFile) for (const f of msg.files) onFile(f);\n if (msg.result) {\n results[msg.index] = msg.result;\n done++;\n if (done === chunks.length) {\n cleanup();\n resolve(results);\n return;\n }\n dispatch(w);\n }\n },\n );\n w.on(\"error\", (err) => {\n if (!failed) {\n failed = true;\n cleanup();\n reject(err);\n }\n });\n // A worker that dies WITHOUT an `error` or `message` (e.g. a `process.exit`\n // in loaded code) would otherwise leave the pool pending forever. Reject so\n // scanParallel falls back to the serial path (audit: arch #5). Expected\n // exits (retired workers, post-completion cleanup) are ignored.\n w.on(\"exit\", (code) => {\n if (failed || retired.has(w) || done === chunks.length) return;\n failed = true;\n cleanup();\n reject(new Error(`scan worker exited early (code ${code}) before completing its chunk`));\n });\n return w;\n };\n\n const n = Math.max(1, Math.min(concurrency, chunks.length));\n for (let i = 0; i < n; i++) {\n const w = spawn();\n workers.push(w);\n dispatch(w);\n }\n });\n}\n"]}
|
package/dist/patch-policy.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"patch-policy.js","sourceRoot":"","sources":["../src/patch-policy.ts"],"names":[],"mappings":"AAiBA;;;GAGG;AACH,MAAM,OAAO,GACX,kLAAkL,CAAC;AAOrL,yDAAyD;AACzD,MAAM,UAAU,gBAAgB,CAAC,KAAY,EAAE,GAAkB;IAC/D,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACzC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACpB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,mCAAmC,CAAC,GAAG,EAAE,CAAC;IAC7E,CAAC;IACD,IAAI,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACtD,IAAI,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACvD,OAAO;QACL,OAAO,EAAE,KAAK;QACd,MAAM,EAAE,eAAe,CAAC,yDAAyD;KAClF,CAAC;AACJ,CAAC"}
|
|
1
|
+
{"version":3,"file":"patch-policy.js","sourceRoot":"","sources":["../src/patch-policy.ts"],"names":[],"mappings":"AAiBA;;;GAGG;AACH,MAAM,OAAO,GACX,kLAAkL,CAAC;AAOrL,yDAAyD;AACzD,MAAM,UAAU,gBAAgB,CAAC,KAAY,EAAE,GAAkB;IAC/D,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACzC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACpB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,mCAAmC,CAAC,GAAG,EAAE,CAAC;IAC7E,CAAC;IACD,IAAI,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACtD,IAAI,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACvD,OAAO;QACL,OAAO,EAAE,KAAK;QACd,MAAM,EAAE,eAAe,CAAC,yDAAyD;KAClF,CAAC;AACJ,CAAC","sourcesContent":["/**\n * Patch-policy allowlist. A remediation patch may only edit a file that already\n * has a finding, or add dependencies to a manifest. Everything else — CI config,\n * lockfiles, env/secret files, unrelated source — is denied. This is the second\n * safety gate (the first is `verify_fix`): even a \"verified\" patch is dropped if\n * it strays outside the sanctioned surface.\n */\nimport type { Patch } from \"./agent-types.js\";\n\n/** Files a remediation may write to. */\nexport interface PolicyContext {\n /** Relative paths (posix) that contain at least one finding. */\n findingFiles: Set<string>;\n /** Relative manifest paths (package.json, requirements.txt, …). */\n manifestFiles: Set<string>;\n}\n\n/**\n * Paths a patch may NEVER touch, regardless of anything else: version control,\n * CI, dependency lockfiles, and anything that looks like a secret/env file.\n */\nconst DENY_RE =\n /(^|\\/)(\\.github|\\.git|node_modules)\\/|(^|\\/)(package-lock\\.json|yarn\\.lock|pnpm-lock\\.yaml|Cargo\\.lock|Gemfile\\.lock|poetry\\.lock)$|(^|\\/)\\.env(\\.[^/]*)?$|\\.(pem|key|p12|pfx)$/i;\n\nexport interface PolicyDecision {\n allowed: boolean;\n reason?: string;\n}\n\n/** Decide whether `patch` may be applied under `ctx`. */\nexport function checkPatchPolicy(patch: Patch, ctx: PolicyContext): PolicyDecision {\n const p = patch.path.replace(/\\\\/g, \"/\");\n if (DENY_RE.test(p)) {\n return { allowed: false, reason: `patch touches a protected path (${p})` };\n }\n if (ctx.findingFiles.has(p)) return { allowed: true };\n if (ctx.manifestFiles.has(p)) return { allowed: true };\n return {\n allowed: false,\n reason: `patch edits ${p}, which has no finding and is not a dependency manifest`,\n };\n}\n"]}
|