@blamejs/exceptd-skills 0.10.0 → 0.10.2
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/AGENTS.md +51 -0
- package/CHANGELOG.md +95 -0
- package/bin/exceptd.js +445 -12
- package/data/_indexes/_meta.json +2 -2
- package/data/playbooks/ai-api.json +400 -90
- package/data/playbooks/containers.json +406 -94
- package/data/playbooks/cred-stores.json +374 -89
- package/data/playbooks/crypto-codebase.json +1387 -0
- package/data/playbooks/crypto.json +369 -87
- package/data/playbooks/framework.json +376 -86
- package/data/playbooks/hardening.json +357 -84
- package/data/playbooks/kernel.json +325 -78
- package/data/playbooks/library-author.json +1792 -0
- package/data/playbooks/mcp.json +407 -92
- package/data/playbooks/runtime.json +345 -81
- package/data/playbooks/sbom.json +497 -111
- package/data/playbooks/secrets.json +352 -83
- package/lib/framework-gap.js +17 -1
- package/lib/playbook-runner.js +126 -11
- package/lib/schemas/playbook.schema.json +5 -0
- package/manifest-snapshot.json +1 -1
- package/manifest.json +39 -39
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
|
@@ -0,0 +1,1387 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_meta": {
|
|
3
|
+
"id": "crypto-codebase",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"last_threat_review": "2026-05-12",
|
|
6
|
+
"threat_currency_score": 95,
|
|
7
|
+
"changelog": [
|
|
8
|
+
{
|
|
9
|
+
"version": "1.0.0",
|
|
10
|
+
"date": "2026-05-12",
|
|
11
|
+
"summary": "Initial seven-phase code-walk crypto audit playbook for library / SDK / framework / CLI / language-runtime / build-tool authors who ship cryptographic primitives to downstream consumers. Complements the host-side `crypto` playbook (which probes OpenSSL / sshd / certificate store on the running host). Where `crypto` asks 'is the host PQC-ready?', `crypto-codebase` asks 'are the crypto choices we ship in our source tree HNDL-safe, FIPS-claim-honest, and downstream-consumer-safe?'. Walks the repo with Glob/Grep/Read, surfacing weak hash usage (MD5/SHA1), deprecated KEX (DH-1024, RSA-1024), insecure RNG (Math.random in security context), under-iterated KDFs (PBKDF2 < 600k post-OWASP 2023), bare ECDSA/RSA where ML-DSA hybrid is feasible, hardcoded curve choices, and vendored PQC implementations of dubious provenance. Theater detection focuses on FIPS-validated-claim mismatches and 'PQC-ready' feature-flag fictions.",
|
|
12
|
+
"cves_added": [],
|
|
13
|
+
"framework_gaps_updated": [
|
|
14
|
+
"nist-800-53-SC-13",
|
|
15
|
+
"iso-27001-2022-A.8.24",
|
|
16
|
+
"iso-27001-2022-A.8.28",
|
|
17
|
+
"pci-dss-4-3.6",
|
|
18
|
+
"eu-cra-annex-I-1",
|
|
19
|
+
"nis2-art21-2g"
|
|
20
|
+
]
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"owner": "@blamejs/platform-security",
|
|
24
|
+
"air_gap_mode": false,
|
|
25
|
+
"scope": "code",
|
|
26
|
+
"preconditions": [
|
|
27
|
+
{
|
|
28
|
+
"id": "filesystem-read-repo",
|
|
29
|
+
"description": "Agent must be able to walk the working directory tree, read source files, and read package/lock manifests.",
|
|
30
|
+
"check": "agent_has_filesystem_read == true",
|
|
31
|
+
"on_fail": "halt"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"id": "repo-has-source-tree",
|
|
35
|
+
"description": "Working directory must contain a recognizable source tree (package.json, pyproject.toml, go.mod, Cargo.toml, pom.xml, build.gradle, src/, lib/, or comparable). A repo with no source files has no shipped crypto surface.",
|
|
36
|
+
"check": "exists_any(['package.json','pyproject.toml','go.mod','Cargo.toml','pom.xml','build.gradle','src','lib','crates']) == true",
|
|
37
|
+
"on_fail": "warn"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"id": "publishable-or-distributed",
|
|
41
|
+
"description": "Playbook is targeted at library / SDK / framework / CLI / runtime / build-tool authors who SHIP code to downstream consumers. Internal-only application repos may still benefit but findings carry lower blast radius.",
|
|
42
|
+
"check": "repo_is_published_artifact == true OR repo_distributes_to_external_consumers == true",
|
|
43
|
+
"on_fail": "warn"
|
|
44
|
+
}
|
|
45
|
+
],
|
|
46
|
+
"mutex": [],
|
|
47
|
+
"feeds_into": [
|
|
48
|
+
{
|
|
49
|
+
"playbook_id": "sbom",
|
|
50
|
+
"condition": "analyze.blast_radius_score >= 3 OR finding.severity == 'critical'"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"playbook_id": "framework",
|
|
54
|
+
"condition": "analyze.compliance_theater_check.verdict == 'theater'"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"playbook_id": "secrets",
|
|
58
|
+
"condition": "detect.indicators contains 'hardcoded-key-material'"
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
},
|
|
62
|
+
"domain": {
|
|
63
|
+
"name": "Library-author / SDK-author crypto posture (shipped-code audit)",
|
|
64
|
+
"attack_class": "pqc-exposure",
|
|
65
|
+
"atlas_refs": [],
|
|
66
|
+
"attack_refs": [
|
|
67
|
+
"T1040",
|
|
68
|
+
"T1552",
|
|
69
|
+
"T1573",
|
|
70
|
+
"T1600"
|
|
71
|
+
],
|
|
72
|
+
"cve_refs": [],
|
|
73
|
+
"cwe_refs": [
|
|
74
|
+
"CWE-310",
|
|
75
|
+
"CWE-326",
|
|
76
|
+
"CWE-327",
|
|
77
|
+
"CWE-328",
|
|
78
|
+
"CWE-329",
|
|
79
|
+
"CWE-330",
|
|
80
|
+
"CWE-331",
|
|
81
|
+
"CWE-338",
|
|
82
|
+
"CWE-759",
|
|
83
|
+
"CWE-760",
|
|
84
|
+
"CWE-916"
|
|
85
|
+
],
|
|
86
|
+
"d3fend_refs": [
|
|
87
|
+
"D3-FE",
|
|
88
|
+
"D3-MENCR",
|
|
89
|
+
"D3-CH"
|
|
90
|
+
],
|
|
91
|
+
"frameworks_in_scope": [
|
|
92
|
+
"nist-800-53",
|
|
93
|
+
"nist-csf-2",
|
|
94
|
+
"iso-27001-2022",
|
|
95
|
+
"soc2",
|
|
96
|
+
"pci-dss-4",
|
|
97
|
+
"nis2",
|
|
98
|
+
"dora",
|
|
99
|
+
"eu-cra",
|
|
100
|
+
"eu-ai-act",
|
|
101
|
+
"uk-caf",
|
|
102
|
+
"au-essential-8",
|
|
103
|
+
"au-ism",
|
|
104
|
+
"cmmc"
|
|
105
|
+
]
|
|
106
|
+
},
|
|
107
|
+
"phases": {
|
|
108
|
+
"govern": {
|
|
109
|
+
"jurisdiction_obligations": [
|
|
110
|
+
{
|
|
111
|
+
"jurisdiction": "EU",
|
|
112
|
+
"regulation": "EU CRA Art.14",
|
|
113
|
+
"obligation": "notify_csirt_exploited_vuln_in_published_product",
|
|
114
|
+
"window_hours": 24,
|
|
115
|
+
"clock_starts": "detect_confirmed",
|
|
116
|
+
"evidence_required": [
|
|
117
|
+
"affected_product_versions",
|
|
118
|
+
"vulnerability_description",
|
|
119
|
+
"mitigation_status",
|
|
120
|
+
"downstream_consumer_notification_plan"
|
|
121
|
+
]
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"jurisdiction": "EU",
|
|
125
|
+
"regulation": "EU CRA Art.13",
|
|
126
|
+
"obligation": "publish_sbom_and_crypto_attributes",
|
|
127
|
+
"window_hours": 720,
|
|
128
|
+
"clock_starts": "manual",
|
|
129
|
+
"evidence_required": [
|
|
130
|
+
"product_sbom",
|
|
131
|
+
"cryptographic_attribute_disclosure",
|
|
132
|
+
"vulnerability_handling_policy"
|
|
133
|
+
]
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"jurisdiction": "EU",
|
|
137
|
+
"regulation": "NIS2 Art.23",
|
|
138
|
+
"obligation": "notify_regulator_critical_product_vuln",
|
|
139
|
+
"window_hours": 24,
|
|
140
|
+
"clock_starts": "detect_confirmed",
|
|
141
|
+
"evidence_required": [
|
|
142
|
+
"essential_entity_consumer_count",
|
|
143
|
+
"exploitation_status_assessment",
|
|
144
|
+
"interim_mitigation_record"
|
|
145
|
+
]
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"jurisdiction": "US",
|
|
149
|
+
"regulation": "CISA Secure-By-Design Self-Attestation (M-23-02 / EO 14028)",
|
|
150
|
+
"obligation": "annual_secure_by_design_attestation_for_federal_use",
|
|
151
|
+
"window_hours": 8760,
|
|
152
|
+
"clock_starts": "manual",
|
|
153
|
+
"evidence_required": [
|
|
154
|
+
"secure_by_design_attestation",
|
|
155
|
+
"vendor_pqc_migration_inventory",
|
|
156
|
+
"cryptographic_provenance_statement"
|
|
157
|
+
]
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"jurisdiction": "AU",
|
|
161
|
+
"regulation": "ASD ISM (vendor-shipped cryptography requirements)",
|
|
162
|
+
"obligation": "publish_cryptographic_implementation_disclosure",
|
|
163
|
+
"window_hours": 8760,
|
|
164
|
+
"clock_starts": "manual",
|
|
165
|
+
"evidence_required": [
|
|
166
|
+
"approved_cryptographic_algorithm_list",
|
|
167
|
+
"vendor_attested_implementation_evidence"
|
|
168
|
+
]
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
"jurisdiction": "UK",
|
|
172
|
+
"regulation": "UK PSTI Act / CAF C.5",
|
|
173
|
+
"obligation": "publish_vulnerability_disclosure_policy_for_connected_products",
|
|
174
|
+
"window_hours": 720,
|
|
175
|
+
"clock_starts": "manual",
|
|
176
|
+
"evidence_required": [
|
|
177
|
+
"vdp_published",
|
|
178
|
+
"minimum_security_period_declared"
|
|
179
|
+
]
|
|
180
|
+
}
|
|
181
|
+
],
|
|
182
|
+
"theater_fingerprints": [
|
|
183
|
+
{
|
|
184
|
+
"pattern_id": "pqc-ready-feature-flag-without-ml-kem",
|
|
185
|
+
"claim": "Our library is 'PQC-ready' / ships 'pqc-first' / has a 'post-quantum' configuration switch.",
|
|
186
|
+
"fast_detection_test": "Grep the entire source tree for actual ML-KEM / ML-DSA / SLH-DSA / Kyber / Dilithium / SPHINCS+ implementation references: `rg -i 'ml[-_]?kem|ml[-_]?dsa|slh[-_]?dsa|kyber|dilithium|sphincs'` AND verify they resolve to concrete cryptographic operations (encapsulate/decapsulate/sign/verify) rather than configuration strings, feature-flag names, or documentation comments. A 'pqc-ready' switch with zero ML-KEM call sites is a marketing toggle, not a primitive.",
|
|
187
|
+
"implicated_controls": [
|
|
188
|
+
"nist-800-53-SC-13",
|
|
189
|
+
"iso-27001-2022-A.8.24",
|
|
190
|
+
"eu-cra-annex-I-1"
|
|
191
|
+
]
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
"pattern_id": "fips-validated-by-linking-openssl",
|
|
195
|
+
"claim": "Our product is FIPS-validated / FIPS-compliant because we link against OpenSSL 3.x (or BoringSSL, or NSS).",
|
|
196
|
+
"fast_detection_test": "FIPS validation is a runtime provider state, not a link-time fact. Grep the source for: (a) explicit FIPS-provider activation (`OSSL_PROVIDER_load(ctx, \"fips\")` in C, `crypto.setFips(true)` in Node, `OpenSSL::Provider.load(\"fips\")` in Ruby, equivalent in other bindings), (b) a runtime check that the FIPS provider is actually selected before performing crypto, (c) absence of non-FIPS provider config in the shipped openssl.cnf / equivalent. If the library never activates the FIPS provider and never asserts it is selected at runtime, the 'FIPS-validated' claim is link-time theater and downstream consumers running the library against a non-FIPS provider config (the default) get classical, non-FIPS-validated crypto.",
|
|
197
|
+
"implicated_controls": [
|
|
198
|
+
"nist-800-53-SC-13",
|
|
199
|
+
"fips-140-3",
|
|
200
|
+
"cmmc-l3-sc-l1-3.13.11"
|
|
201
|
+
]
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
"pattern_id": "weak-hash-in-non-security-context-defense",
|
|
205
|
+
"claim": "Yes we ship MD5 / SHA1 — but only as a non-security hash (cache key, ETag, fingerprint, deduplication).",
|
|
206
|
+
"fast_detection_test": "Walk every MD5 / SHA1 call site. For each, trace the output's downstream usage: does it ever feed (a) a signature, (b) a MAC, (c) an integrity check, (d) a password-derivation routine, (e) a tamper-evident log, (f) a content-addressed identity used for authorization? If the hash output crosses ANY security boundary the 'non-security' defense fails. Acceptable usage requires (i) inline comment justifying non-security usage AND (ii) static-analysis annotation suppressing the warning AND (iii) no transitive flow into authorization/integrity code paths.",
|
|
207
|
+
"implicated_controls": [
|
|
208
|
+
"nist-800-53-SC-13",
|
|
209
|
+
"iso-27001-2022-A.8.24",
|
|
210
|
+
"pci-dss-4-3.6"
|
|
211
|
+
]
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
"pattern_id": "math-random-in-security-by-accident",
|
|
215
|
+
"claim": "We use crypto-grade RNG throughout — Math.random() / random.random() / rand() only appears in test fixtures and non-security paths.",
|
|
216
|
+
"fast_detection_test": "Grep `Math.random(`, `random.random(`, `random.randint(`, `rand(`, `srand(`, `mt_rand(` in the production source set (exclude test/spec/fixture directories with explicit allowlist). For each hit, trace whether the output is ever used as: a key, nonce, IV, salt, session token, password reset token, OAuth state, CSRF token, jti claim, or shuffled in a security-sensitive ordering (e.g. shuffling encrypted shards). Any single such path is a hard fail — CWE-338 — regardless of how local-looking the code is.",
|
|
217
|
+
"implicated_controls": [
|
|
218
|
+
"nist-800-53-SC-13",
|
|
219
|
+
"iso-27001-2022-A.8.24",
|
|
220
|
+
"pci-dss-4-3.6"
|
|
221
|
+
]
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
"pattern_id": "pbkdf2-iterations-set-in-2015",
|
|
225
|
+
"claim": "Our password hashing uses PBKDF2 with industry-standard parameters.",
|
|
226
|
+
"fast_detection_test": "Grep `pbkdf2`, `PBKDF2`, `derive_key`, `password_hash`, `hash_password`. For each call site, extract the iterations parameter (or its default if implicit). OWASP 2023 published minimum for PBKDF2-HMAC-SHA256 = 600,000 iterations; PBKDF2-HMAC-SHA512 = 210,000; PBKDF2-HMAC-SHA1 (which itself is deprecated for new use) = 1,300,000. Anything below those minimums is structurally weak. Anything below 100,000 is GPU-crackable in a coffee break. Bonus theater: a config option named `pbkdfIterations` whose documented default is 10,000 with an inline comment 'tune for your environment' — downstream consumers will not tune it.",
|
|
227
|
+
"implicated_controls": [
|
|
228
|
+
"nist-800-63b",
|
|
229
|
+
"iso-27001-2022-A.8.24",
|
|
230
|
+
"pci-dss-4-8.3.2"
|
|
231
|
+
]
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
"pattern_id": "vendored-pqc-without-provenance",
|
|
235
|
+
"claim": "We ship our own ML-KEM / Kyber / Dilithium implementation for performance / bundle-size / no-deps reasons.",
|
|
236
|
+
"fast_detection_test": "Locate the vendored implementation. Audit for: (a) does it match a known-good reference (liboqs / pq-crystals / Cloudflare CIRCL / aws-lc-rs PQC fork)? (b) is the source-of-truth commit hash recorded? (c) is there a build-time integrity verification (the vendored copy is verified against an upstream hash at CI)? (d) is the implementation constant-time (no early-exit branches on secret values, no memcmp on secret outputs)? Vendored PQC without provenance + integrity + constant-time audit is implementation theater — the library ships a primitive whose security properties have not been verified.",
|
|
237
|
+
"implicated_controls": [
|
|
238
|
+
"nist-800-53-SA-12",
|
|
239
|
+
"iso-27001-2022-A.8.28",
|
|
240
|
+
"eu-cra-annex-I-1"
|
|
241
|
+
]
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
"pattern_id": "crypto-agility-claim-no-pluggability",
|
|
245
|
+
"claim": "Our crypto layer is 'crypto-agile' — we can swap algorithms when needed.",
|
|
246
|
+
"fast_detection_test": "Locate the crypto abstraction. Is the algorithm a runtime-pluggable strategy (interface + registered implementations, downstream consumers can supply their own)? Or is it a hardcoded library call wrapped in a function whose name happens to be `cryptoAgileSigner`? Acceptable crypto-agility evidence: (a) an interface / trait / abstract class with at least two implementations in the source tree, (b) configuration hook for downstream consumers to register an implementation, (c) explicit algorithm-identifier metadata travels with ciphertext / signature for forward decoding. Naming a function 'crypto-agile' without those structural properties is theater.",
|
|
247
|
+
"implicated_controls": [
|
|
248
|
+
"iso-27001-2022-A.8.25",
|
|
249
|
+
"iso-27001-2022-A.8.28",
|
|
250
|
+
"nist-800-53-SA-8"
|
|
251
|
+
]
|
|
252
|
+
}
|
|
253
|
+
],
|
|
254
|
+
"framework_context": {
|
|
255
|
+
"gap_summary": "Compliance frameworks treat shipped cryptography as a property of the deploying organization, not the library author. NIST 800-53 SC-13 specifies use of FIPS-validated crypto by the federal system that consumes the library; it does not bind the library author to ship FIPS-friendly defaults or to prevent non-FIPS providers being silently selected. ISO 27001:2022 A.8.24 applies to the using organization; A.8.28 (secure coding) is the closest control to library-author crypto choices but contains no PQC, KDF-iteration, or RNG-source specifics. PCI DSS 4.0 §3.6 / §8.3.2 bind merchants and service providers, not their upstream library vendors — yet a payment library shipping PBKDF2 with 10k iterations is what the merchant inherits. EU CRA Annex I §1 IS the inflection point: it places direct cybersecurity obligations on manufacturers of products with digital elements, including 'state-of-the-art' cryptography, secure-by-default configurations, vulnerability handling, and (via Art.13) SBOM publication with cryptographic attribute disclosure. EU CRA's binding date for vulnerability-handling and SBOM provisions is 2026-09-11; full compliance deadline 2027-12-11. NIS2 Art.21(2)(g) names supply-chain security and cryptography for essential entities, and Art.23 imposes 24-hour early-warning notifications when an exploited vulnerability is in a product they depend on — pushing the obligation upstream to the library author by indirect pressure. UK CAF C.5 + UK PSTI (binding since April 2024) cover connected-product security; ISO 27001:2022 A.8.28 (secure coding) is the longest-laggard on PQC. AU ISM has approved-cryptographic-algorithm lists that library authors must declare conformance to. Bottom line: the framework lag is shrinking due to EU CRA, but for library authors operating today, conformance is largely voluntary — and downstream consumers inherit whatever the author shipped.",
|
|
256
|
+
"lag_score": 365,
|
|
257
|
+
"per_framework_gaps": [
|
|
258
|
+
{
|
|
259
|
+
"framework": "nist-800-53",
|
|
260
|
+
"control_id": "SC-13",
|
|
261
|
+
"designed_for": "Use of FIPS-validated cryptographic modules by the operating organization.",
|
|
262
|
+
"insufficient_because": "Binds the deploying organization, not the library author. A library can ship MD5 by default and remain SC-13-irrelevant — the burden shifts to every downstream consumer to audit and reconfigure. Needs an upstream variant (SC-13 LIBRARY-VARIANT) requiring vendor-shipped defaults to be FIPS-friendly and to fail closed on non-FIPS provider selection when the consumer has asserted FIPS mode."
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
"framework": "iso-27001-2022",
|
|
266
|
+
"control_id": "A.8.24",
|
|
267
|
+
"designed_for": "Use of cryptography — policy on cryptographic controls by the using organization.",
|
|
268
|
+
"insufficient_because": "Same upstream gap as SC-13. Published 2022 before FIPS 203/204/205 finalization; no PQC language. A library author can claim 'A.8.24 not in scope, we are a vendor' and downstream consumers inherit the shipped defaults."
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
"framework": "iso-27001-2022",
|
|
272
|
+
"control_id": "A.8.28",
|
|
273
|
+
"designed_for": "Secure coding — secure coding practices throughout the software development lifecycle.",
|
|
274
|
+
"insufficient_because": "Closest control to library-author crypto choices. Contains no PQC requirement, no KDF iteration minimum, no RNG-source requirement, no constant-time-implementation requirement. Secure-coding-without-cryptographic-specifics permits MD5-by-default, PBKDF2-10k, Math.random in token generation."
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
"framework": "pci-dss-4",
|
|
278
|
+
"control_id": "3.6 / 8.3.2",
|
|
279
|
+
"designed_for": "Strong cryptography for cardholder data and PBKDF for password storage.",
|
|
280
|
+
"insufficient_because": "Binds merchants and service providers, not their upstream library vendors. A payment library shipping PBKDF2-10k is what the merchant inherits without an explicit override. No framework hook to push the obligation upstream."
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
"framework": "eu-cra",
|
|
284
|
+
"control_id": "Annex I §1",
|
|
285
|
+
"designed_for": "Essential cybersecurity requirements — manufacturers of products with digital elements must ship state-of-the-art cryptography with secure defaults.",
|
|
286
|
+
"insufficient_because": "Binding date for vulnerability-handling and SBOM provisions: 2026-09-11; full compliance: 2027-12-11. 'State-of-the-art' is interpretive without a NIST PQC reference. Library authors today are not yet legally bound; downstream consumers cannot yet point to a binding requirement when filing remediation requests upstream."
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
"framework": "nis2",
|
|
290
|
+
"control_id": "Art.21(2)(g)",
|
|
291
|
+
"designed_for": "Supply-chain security for essential entities — including cryptography in upstream products.",
|
|
292
|
+
"insufficient_because": "Binds the essential entity, not the library author. Indirect pressure: essential-entity consumers may stop adopting libraries with weak crypto defaults, but the framework provides no upstream enforcement hook."
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
"framework": "uk-caf",
|
|
296
|
+
"control_id": "C.5 (Connected Products)",
|
|
297
|
+
"designed_for": "Connected-product security; minimum security periods; vulnerability disclosure.",
|
|
298
|
+
"insufficient_because": "Targets connected-product manufacturers under UK PSTI Act. Library authors shipping non-product crypto code are outside scope unless their library is incorporated into a regulated connected product, at which point obligations flow through the product manufacturer."
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
"framework": "au-essential-8",
|
|
302
|
+
"control_id": "M8 (Application Control) / M-Patch Apps",
|
|
303
|
+
"designed_for": "Application control + patching for the operating organization.",
|
|
304
|
+
"insufficient_because": "No direct library-author obligation. AU ISM's approved-cryptographic-algorithm list IS the relevant upstream signal but is non-binding without procurement teeth."
|
|
305
|
+
}
|
|
306
|
+
]
|
|
307
|
+
},
|
|
308
|
+
"skill_preload": [
|
|
309
|
+
"pqc-first",
|
|
310
|
+
"supply-chain-integrity",
|
|
311
|
+
"exploit-scoring",
|
|
312
|
+
"framework-gap-analysis",
|
|
313
|
+
"compliance-theater",
|
|
314
|
+
"global-grc",
|
|
315
|
+
"policy-exception-gen"
|
|
316
|
+
]
|
|
317
|
+
},
|
|
318
|
+
"direct": {
|
|
319
|
+
"threat_context": "Library-author crypto posture mid-2026: FIPS 203/204/205 finalized 2024-08-13. Production ML-KEM / ML-DSA / SLH-DSA reference implementations available via liboqs, pq-crystals, Cloudflare CIRCL, aws-lc-rs, BoringSSL EVP_KEM_*, OpenSSL 3.5 native, noble-post-quantum (JavaScript), pqcrypto crate (Rust), pqcrypto-mlkem (Python). Downstream-consumer pressure: Chrome ships X25519MLKEM768 since v124 (April 2024); npm advisories started flagging classical-only TLS libraries Q4 2025; supply-chain attacks against vendored crypto are an established pattern (event-stream 2018, ua-parser-js 2021, ctx 2022, multiple 2024-2025 incidents where library authors shipped backdoored or trojanized cryptographic primitives). The current dominant failure mode for library authors is not 'ships no crypto' but 'ships crypto with stale defaults': MD5 still appearing as default hash in 14% of npm packages with crypto surface (audit Q1 2026 from npm-audit-trends); PBKDF2 default iterations under 100k in 28% of packages that expose a password-hashing API; Math.random() used in security context in 6% of token-generation libraries audited; vendored PQC without provenance in 41% of packages that advertise PQC support. AI-discovery acceleration: AI-assisted code audit tooling identifies these patterns in seconds across million-line repos. Downstream blast radius: a popular framework with 10M+ weekly installs shipping a weak cryptographic default propagates the vulnerability to every consumer regardless of the consumer's own security posture.",
|
|
320
|
+
"rwep_threshold": {
|
|
321
|
+
"escalate": 75,
|
|
322
|
+
"monitor": 45,
|
|
323
|
+
"close": 25
|
|
324
|
+
},
|
|
325
|
+
"framework_lag_declaration": "Frameworks structurally bind the OPERATING organization, not the library author. NIST 800-53 SC-13, ISO 27001:2022 A.8.24/A.8.28, PCI DSS 4.0 §3.6/§8.3.2 all push obligations downstream to consumers who inherit the shipped defaults. EU CRA Annex I §1 is the first framework with direct upstream obligations on manufacturers of products with digital elements, but its binding date for vulnerability-handling and SBOM provisions is 2026-09-11 (four months from now) with full compliance 2027-12-11. NIS2 Art.21(2)(g) exerts indirect pressure via essential-entity consumers. UK CAF C.5 + UK PSTI covers connected products only. ISO 27001:2022 A.8.28 'secure coding' is silent on PQC, KDF iteration minimums, RNG-source requirements, constant-time-implementation requirements — the longest structural laggard. NIST IR 8547 + OMB M-23-02 + CNSA 2.0 push federal-system PQC migration through 2030 but rely on procurement pressure to flow upstream. Gap = ~365 days from operational PQC readiness (2024-08-13 FIPS finalization) to binding library-author obligations (2026-09-11 EU CRA partial bind). Compensating controls (downstream-consumer adoption pressure, supply-chain auditing tools, voluntary SECURITY.md disclosure of cryptographic provenance) must close this gap pending EU CRA enforcement.",
|
|
326
|
+
"skill_chain": [
|
|
327
|
+
{
|
|
328
|
+
"skill": "pqc-first",
|
|
329
|
+
"purpose": "Identify hardcoded classical primitives in shipped source; assess feasibility of hybrid PQC migration without breaking downstream-consumer API.",
|
|
330
|
+
"required": true
|
|
331
|
+
},
|
|
332
|
+
{
|
|
333
|
+
"skill": "supply-chain-integrity",
|
|
334
|
+
"purpose": "For vendored cryptographic primitives, verify provenance (upstream hash, integrity check, constant-time audit).",
|
|
335
|
+
"required": true
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
"skill": "exploit-scoring",
|
|
339
|
+
"purpose": "Compute RWEP for each finding using the blast_radius-heavy weighting appropriate to library-author findings.",
|
|
340
|
+
"required": true
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
"skill": "framework-gap-analysis",
|
|
344
|
+
"purpose": "Map each shipped-default weakness to the framework controls that fail to bind it upstream and the downstream-consumer obligations it creates.",
|
|
345
|
+
"required": true
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
"skill": "compliance-theater",
|
|
349
|
+
"purpose": "Run the seven theater fingerprints in govern.theater_fingerprints; emit verdict per finding.",
|
|
350
|
+
"required": true
|
|
351
|
+
},
|
|
352
|
+
{
|
|
353
|
+
"skill": "global-grc",
|
|
354
|
+
"purpose": "Cross-walk findings to per-jurisdiction obligations including EU CRA Art.13/14 notification clocks.",
|
|
355
|
+
"skip_if": "jurisdiction_obligations.length == 0",
|
|
356
|
+
"required": false
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
"skill": "policy-exception-gen",
|
|
360
|
+
"purpose": "Generate auditor-ready exception language for deprecated primitives retained under API-stability promise.",
|
|
361
|
+
"skip_if": "close.exception_generation.trigger_condition == false",
|
|
362
|
+
"required": false
|
|
363
|
+
}
|
|
364
|
+
],
|
|
365
|
+
"token_budget": {
|
|
366
|
+
"estimated_total": 24000,
|
|
367
|
+
"breakdown": {
|
|
368
|
+
"govern": 3200,
|
|
369
|
+
"direct": 1800,
|
|
370
|
+
"look": 2800,
|
|
371
|
+
"detect": 3600,
|
|
372
|
+
"analyze": 5200,
|
|
373
|
+
"validate": 4200,
|
|
374
|
+
"close": 3200
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
},
|
|
378
|
+
"look": {
|
|
379
|
+
"artifacts": [
|
|
380
|
+
{
|
|
381
|
+
"id": "package-manifests",
|
|
382
|
+
"type": "config_file",
|
|
383
|
+
"source": "Read package.json, pyproject.toml, setup.py, go.mod, Cargo.toml, pom.xml, build.gradle, Gemfile, composer.json, mix.exs at repo root and at every nested package boundary. Use Glob `**/{package.json,pyproject.toml,go.mod,Cargo.toml,pom.xml,build.gradle,Gemfile,composer.json}` excluding `node_modules`, `vendor`, `.venv`, `target`, `dist`, `build`.",
|
|
384
|
+
"description": "Package manifests — establish the language ecosystems present, declared crypto-adjacent dependencies, and the public API surface.",
|
|
385
|
+
"required": true
|
|
386
|
+
},
|
|
387
|
+
{
|
|
388
|
+
"id": "lockfiles",
|
|
389
|
+
"type": "config_file",
|
|
390
|
+
"source": "Read package-lock.json, yarn.lock, pnpm-lock.yaml, poetry.lock, uv.lock, Pipfile.lock, go.sum, Cargo.lock, composer.lock at repo root and at every package boundary.",
|
|
391
|
+
"description": "Lockfiles — concrete versions of crypto-adjacent deps actually shipped to consumers (openssl, sodium, libsodium-wrappers, tweetnacl, noble-curves, noble-hashes, noble-post-quantum, jsrsasign, node-forge, pqcrypto, oqs-rs, kyber-crystals, dilithium, aws-lc-rs, ring, rustls, rust-openssl).",
|
|
392
|
+
"required": false
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
"id": "hash-primitive-call-sites",
|
|
396
|
+
"type": "file_path",
|
|
397
|
+
"source": "Grep across the repo (excluding test/spec/fixture/node_modules/vendor/.venv/target/dist/build) for hash-primitive call sites. Patterns: `crypto.createHash\\(`, `crypto.createHmac\\(`, `hashlib\\.(md5|sha1|sha224|sha256|sha384|sha512|blake2b|blake2s|sha3_)`, `MessageDigest\\.getInstance\\(`, `Digest::(MD5|SHA1|SHA256)`, `hash/md5`, `hash/sha1`, `\"md5\"`, `\"sha1\"`, `\"sha-1\"`, `\"sha256\"`, `\"sha3-256\"`. Use Grep with multiline=true where the algorithm-name string is on a different line from the constructor.",
|
|
398
|
+
"description": "Every hash-primitive call site. Distinguish security-context usage (signature input, MAC input, integrity check, password derivation, token derivation) from non-security usage (cache key, ETag, dedup). The non-security distinction must be evidenced inline; absent evidence, treat as security-context.",
|
|
399
|
+
"required": true
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
"id": "cipher-and-kex-call-sites",
|
|
403
|
+
"type": "file_path",
|
|
404
|
+
"source": "Grep for cipher and KEX call sites: `createCipheriv\\(`, `createDecipheriv\\(`, `crypto\\.publicEncrypt\\(`, `crypto\\.privateDecrypt\\(`, `createDiffieHellman\\(`, `createECDH\\(`, `crypto\\.generateKeyPair`, `Cipher\\.getInstance\\(`, `aesgcm`, `ChaCha20Poly1305`, `\\.(seal|open)\\(`, `OpenSSL::Cipher`, hardcoded curve names `\"P-256\"`, `\"secp256r1\"`, `\"prime256v1\"`, `\"P-384\"`, `\"secp384r1\"`, `\"P-521\"`, `\"secp521r1\"`, `\"secp256k1\"`, `\"X25519\"`, `\"X448\"`.",
|
|
405
|
+
"description": "Cipher and key-exchange call sites. Identify mode (GCM/CBC/CTR/ECB), curve, key size, IV-generation pattern. ECB mode anywhere is a hard fail. CBC without HMAC is a hard fail. AES-128 without GCM authenticator is a finding.",
|
|
406
|
+
"required": true
|
|
407
|
+
},
|
|
408
|
+
{
|
|
409
|
+
"id": "signature-call-sites",
|
|
410
|
+
"type": "file_path",
|
|
411
|
+
"source": "Grep for signature operations: `crypto\\.sign\\(`, `crypto\\.verify\\(`, `Signature\\.getInstance\\(`, `\\.sign_pss\\(`, `\\.verify_pss\\(`, `RSA-PSS`, `RSA-PKCS1`, `ECDSA`, `Ed25519`, `Ed448`, `ML-DSA`, `Dilithium`, `SLH-DSA`, `SPHINCS`. Capture key sizes for RSA (look for `modulusLength`, `key_size`, `--rsa-2048` literals), curve choice for ECDSA, hash choice paired with signature (RSA-SHA1 is a hard fail).",
|
|
412
|
+
"description": "Signature scheme inventory. RSA-1024 anywhere is a hard fail; RSA-2048 with > 5-year sensitivity requires PQC roadmap; ECDSA-P256 acceptable today but needs hybrid ML-DSA migration plan; bare RSA-PKCS1 (not PSS) for new signatures is a finding.",
|
|
413
|
+
"required": true
|
|
414
|
+
},
|
|
415
|
+
{
|
|
416
|
+
"id": "kdf-call-sites",
|
|
417
|
+
"type": "file_path",
|
|
418
|
+
"source": "Grep for key-derivation calls: `pbkdf2(Sync)?\\(`, `PBKDF2`, `hashlib\\.pbkdf2_hmac`, `bcrypt\\.(hash|hashSync|compare)`, `scrypt(Sync)?\\(`, `argon2\\.(hash|verify)`, `argon2id`, `hkdf\\(`, `HKDF`, `derive_key`. For each, extract the cost parameters: PBKDF2 iterations, bcrypt cost factor, scrypt N/r/p, argon2 t/m/p.",
|
|
419
|
+
"description": "Key-derivation parameter inventory. Apply OWASP 2023 minimums: PBKDF2-HMAC-SHA256 >= 600,000; PBKDF2-HMAC-SHA512 >= 210,000; bcrypt cost >= 12; scrypt N >= 2^17, r=8, p=1; argon2id m >= 19 MiB (19456 KiB), t >= 2, p >= 1. Any parameter below minimum is a finding.",
|
|
420
|
+
"required": true
|
|
421
|
+
},
|
|
422
|
+
{
|
|
423
|
+
"id": "rng-call-sites",
|
|
424
|
+
"type": "file_path",
|
|
425
|
+
"source": "Grep for RNG sources: `Math\\.random\\(`, `random\\.random\\(`, `random\\.randint\\(`, `random\\.choice\\(`, `rand\\(`, `srand\\(`, `mt_rand\\(`, `secrets\\.(token_|randbits|choice)`, `crypto\\.randomBytes\\(`, `crypto\\.getRandomValues\\(`, `crypto\\.randomUUID\\(`, `os\\.urandom\\(`, `getrandom\\(`, `SecureRandom`, `OsRng`, `ThreadRng`, `/dev/urandom`, `/dev/random`. Capture file_path:line for each.",
|
|
426
|
+
"description": "RNG-source inventory. Production-context Math.random / random.random / rand without cryptographic-RNG fallback is CWE-338. Distinguish test/spec/fixture usage explicitly via path allowlist; production usage requires a cryptographic RNG.",
|
|
427
|
+
"required": true
|
|
428
|
+
},
|
|
429
|
+
{
|
|
430
|
+
"id": "hardcoded-key-material",
|
|
431
|
+
"type": "file_path",
|
|
432
|
+
"source": "Grep for hardcoded crypto material: PEM markers `-----BEGIN (RSA |EC |DSA |PRIVATE |PUBLIC |CERTIFICATE )?(PRIVATE|PUBLIC) KEY-----`, SSH key prefixes `ssh-rsa AAAA`, `ssh-ed25519 AAAA`, `ecdsa-sha2-nistp256 AAAA`, hex-blob heuristics for keys (>= 64 hex chars on a single literal line), base64-encoded blobs >= 256 chars in source files. Cross-reference with the `secrets` playbook for the exfil-secret angle; here the focus is library-author shipping defaults that look like keys (e.g. example certs, demo keys, sample HMAC seeds that downstream consumers fail to rotate).",
|
|
433
|
+
"description": "Hardcoded key material shipped with the library. Library-author angle: any 'demo' or 'example' key that downstream consumers fail to rotate becomes a universal-default vulnerability (cf. embedded-router demo keys, Wi-Fi default WPA keys, IoT bootloader signing keys).",
|
|
434
|
+
"required": false
|
|
435
|
+
},
|
|
436
|
+
{
|
|
437
|
+
"id": "tls-config-construction",
|
|
438
|
+
"type": "file_path",
|
|
439
|
+
"source": "Grep for in-code TLS context construction: `tls\\.createSecureContext`, `tls\\.createServer`, `https\\.createServer`, `ssl\\.SSLContext\\(`, `ssl\\.create_default_context`, `rustls::ServerConfig`, `rustls::ClientConfig`, `tls\\.Config\\{`, `SSL_CTX_new`, options like `minVersion`, `maxVersion`, `secureProtocol`, `ciphers`, `ecdhCurve`, `sigalgs`, `groups`, `ALPNProtocols`.",
|
|
440
|
+
"description": "In-code TLS configuration. Library authors that construct TLS contexts internally must default to TLS 1.3 minimum, X25519MLKEM768 group preference (when openssl >= 3.5 detected), modern cipher list. Hardcoded `secureProtocol: 'TLSv1_method'` or `minVersion: 'TLSv1'` is a hard fail.",
|
|
441
|
+
"required": false
|
|
442
|
+
},
|
|
443
|
+
{
|
|
444
|
+
"id": "pqc-adoption-signals",
|
|
445
|
+
"type": "file_path",
|
|
446
|
+
"source": "Grep for PQC adoption: `ml[-_]?kem`, `ml[-_]?dsa`, `slh[-_]?dsa`, `kyber`, `dilithium`, `sphincs`, `falcon`, `kemEncapsulate`, `kemDecapsulate`, `EVP_KEM_`, `OQS_KEM_`, `oqsprovider`, `liboqs`, `noble-post-quantum`, `pqcrypto::`, `aws-lc-rs::pqc`, `circl/sign/dilithium`, `circl/kem/kyber`.",
|
|
447
|
+
"description": "PQC adoption signals. If `pqc-readiness-gap` directive runs, this artifact is the primary input. Distinguish concrete cryptographic operations from configuration strings, feature-flag names, and comments.",
|
|
448
|
+
"required": false
|
|
449
|
+
},
|
|
450
|
+
{
|
|
451
|
+
"id": "fips-provider-activation",
|
|
452
|
+
"type": "file_path",
|
|
453
|
+
"source": "Grep for FIPS-mode activation: `OSSL_PROVIDER_load.*fips`, `crypto\\.setFips\\(`, `openssl::provider::Provider::load_default`, `Provider::load.*\"fips\"`, openssl.cnf or fipsmodule.cnf files in the repo, environment-variable references to `OPENSSL_FIPS`, `OPENSSL_CONF`. Capture whether the activation is conditional (e.g. only if env var set) or unconditional.",
|
|
454
|
+
"description": "FIPS-provider activation evidence. The `fips-validation-status` directive uses this to distinguish runtime FIPS activation from link-time FIPS claims.",
|
|
455
|
+
"required": false
|
|
456
|
+
},
|
|
457
|
+
{
|
|
458
|
+
"id": "vendored-crypto-tree",
|
|
459
|
+
"type": "file_path",
|
|
460
|
+
"source": "Glob for vendored crypto: `vendor/**/{crypto,openssl,sodium,nacl,kyber,dilithium,sphincs,curve25519,blake2,sha3,argon2}*`, `third_party/**/*crypto*`, `crates/**/*crypto*` (excluding the package's own crypto module). Look for upstream-reference files: `UPSTREAM`, `ORIGIN`, `PROVENANCE.md`, `.upstream-commit`, integrity hashes in lockfiles.",
|
|
461
|
+
"description": "Vendored cryptographic primitives. Library authors sometimes vendor crypto to reduce dep tree or for licensing reasons. Without provenance + integrity audit, vendored crypto is a supply-chain backdoor opportunity.",
|
|
462
|
+
"required": false
|
|
463
|
+
},
|
|
464
|
+
{
|
|
465
|
+
"id": "ci-crypto-tests",
|
|
466
|
+
"type": "file_path",
|
|
467
|
+
"source": "Glob for CI configs: `.github/workflows/**/*.yml`, `.gitlab-ci.yml`, `.circleci/config.yml`, `azure-pipelines.yml`, `Jenkinsfile`. Grep for crypto-test invocations, FIPS-test runs, constant-time analysis tools (`dudect`, `valgrind --tool=memcheck` on secret-dependent code, `ctgrind`).",
|
|
468
|
+
"description": "Build-time crypto verification. Absence of constant-time tests on vendored PQC primitives is a finding for the `pqc-readiness-gap` directive.",
|
|
469
|
+
"required": false
|
|
470
|
+
}
|
|
471
|
+
],
|
|
472
|
+
"collection_scope": {
|
|
473
|
+
"time_window": "current",
|
|
474
|
+
"asset_scope": "entire_source_tree_excluding_vendored_dependencies_and_build_artifacts",
|
|
475
|
+
"depth": "deep",
|
|
476
|
+
"sampling": "exhaustive — every production-context source file is grepped. Test, spec, fixture, example, and documentation paths are walked separately and findings annotated with `path_context=test`. Use Glob + Grep with explicit exclusion of `node_modules`, `vendor` (unless the directive specifically targets vendored crypto), `.venv`, `venv`, `target`, `dist`, `build`, `coverage`, `.git`."
|
|
477
|
+
},
|
|
478
|
+
"environment_assumptions": [
|
|
479
|
+
{
|
|
480
|
+
"assumption": "working directory contains a source tree (not a dependency consumer)",
|
|
481
|
+
"if_false": "If the working directory is a node_modules subtree, a Cargo registry checkout, a Python site-packages directory, etc., halt with visibility_gap=consumer_not_author. This playbook audits what an author SHIPS, not what a consumer INSTALLED. Re-run from the source repository."
|
|
482
|
+
},
|
|
483
|
+
{
|
|
484
|
+
"assumption": "agent has Glob + Grep + Read on the entire source tree",
|
|
485
|
+
"if_false": "Investigation is unfounded. Downgrade all artifact collection to inconclusive and escalate."
|
|
486
|
+
},
|
|
487
|
+
{
|
|
488
|
+
"assumption": "the library is intended for downstream consumption (published to a registry, distributed as a SDK, embedded in a product)",
|
|
489
|
+
"if_false": "Blast radius drops by 1-2 tiers in the analyze phase; findings remain but compliance theater verdicts and EU CRA notification clocks may not apply."
|
|
490
|
+
},
|
|
491
|
+
{
|
|
492
|
+
"assumption": "the source tree uses identifiable language conventions (file extensions, package manifest)",
|
|
493
|
+
"if_false": "Generic Grep patterns still apply but path-context allowlists (test/spec/fixture exclusions) may misclassify findings. Mark findings with `path_classification=heuristic` and request human review."
|
|
494
|
+
}
|
|
495
|
+
],
|
|
496
|
+
"fallback_if_unavailable": [
|
|
497
|
+
{
|
|
498
|
+
"artifact_id": "package-manifests",
|
|
499
|
+
"fallback_action": "escalate_to_human",
|
|
500
|
+
"confidence_impact": "high"
|
|
501
|
+
},
|
|
502
|
+
{
|
|
503
|
+
"artifact_id": "lockfiles",
|
|
504
|
+
"fallback_action": "use_compensating_artifact",
|
|
505
|
+
"confidence_impact": "medium"
|
|
506
|
+
},
|
|
507
|
+
{
|
|
508
|
+
"artifact_id": "hash-primitive-call-sites",
|
|
509
|
+
"fallback_action": "mark_inconclusive",
|
|
510
|
+
"confidence_impact": "high"
|
|
511
|
+
},
|
|
512
|
+
{
|
|
513
|
+
"artifact_id": "cipher-and-kex-call-sites",
|
|
514
|
+
"fallback_action": "mark_inconclusive",
|
|
515
|
+
"confidence_impact": "high"
|
|
516
|
+
},
|
|
517
|
+
{
|
|
518
|
+
"artifact_id": "signature-call-sites",
|
|
519
|
+
"fallback_action": "mark_inconclusive",
|
|
520
|
+
"confidence_impact": "high"
|
|
521
|
+
},
|
|
522
|
+
{
|
|
523
|
+
"artifact_id": "kdf-call-sites",
|
|
524
|
+
"fallback_action": "mark_inconclusive",
|
|
525
|
+
"confidence_impact": "medium"
|
|
526
|
+
},
|
|
527
|
+
{
|
|
528
|
+
"artifact_id": "rng-call-sites",
|
|
529
|
+
"fallback_action": "mark_inconclusive",
|
|
530
|
+
"confidence_impact": "high"
|
|
531
|
+
},
|
|
532
|
+
{
|
|
533
|
+
"artifact_id": "hardcoded-key-material",
|
|
534
|
+
"fallback_action": "mark_inconclusive",
|
|
535
|
+
"confidence_impact": "medium"
|
|
536
|
+
},
|
|
537
|
+
{
|
|
538
|
+
"artifact_id": "pqc-adoption-signals",
|
|
539
|
+
"fallback_action": "use_compensating_artifact",
|
|
540
|
+
"confidence_impact": "medium"
|
|
541
|
+
},
|
|
542
|
+
{
|
|
543
|
+
"artifact_id": "fips-provider-activation",
|
|
544
|
+
"fallback_action": "mark_inconclusive",
|
|
545
|
+
"confidence_impact": "medium"
|
|
546
|
+
},
|
|
547
|
+
{
|
|
548
|
+
"artifact_id": "vendored-crypto-tree",
|
|
549
|
+
"fallback_action": "mark_inconclusive",
|
|
550
|
+
"confidence_impact": "medium"
|
|
551
|
+
}
|
|
552
|
+
]
|
|
553
|
+
},
|
|
554
|
+
"detect": {
|
|
555
|
+
"indicators": [
|
|
556
|
+
{
|
|
557
|
+
"id": "weak-hash-import",
|
|
558
|
+
"type": "file_path",
|
|
559
|
+
"value": "Any file imports or constructs an MD5 / SHA1 hash and the output flows into a security context. Patterns: `crypto\\.createHash\\(['\"](md5|sha1|sha-1)['\"]\\)`, `hashlib\\.(md5|sha1)\\(`, `MessageDigest\\.getInstance\\(['\"](MD5|SHA-1)['\"]\\)`, `crypto/md5`, `crypto/sha1`, `Digest::(MD5|SHA1)\\.`",
|
|
560
|
+
"description": "Weak hash primitive shipped in library source. Hard fail unless inline comment justifies non-security usage AND no flow into auth/integrity code path.",
|
|
561
|
+
"confidence": "deterministic",
|
|
562
|
+
"deterministic": true
|
|
563
|
+
},
|
|
564
|
+
{
|
|
565
|
+
"id": "weak-cipher-mode",
|
|
566
|
+
"type": "file_path",
|
|
567
|
+
"value": "AES with ECB mode anywhere: `aes-\\d+-ecb`, `AES/ECB/`, `Cipher\\.getInstance\\(['\"]AES['\"]\\)` (default mode ECB). Or DES/3DES anywhere: `des-cbc`, `des-ede3`, `\\\"des\\\"`, `\\\"3des\\\"`, `DES/`, `DESede/`. Or RC4: `\\\"rc4\\\"`, `arc4`, `ARCFOUR`.",
|
|
568
|
+
"description": "Catastrophic cipher choice. ECB leaks plaintext patterns; DES/3DES is below current security margins; RC4 is broken.",
|
|
569
|
+
"confidence": "deterministic",
|
|
570
|
+
"deterministic": true
|
|
571
|
+
},
|
|
572
|
+
{
|
|
573
|
+
"id": "rsa-1024-anywhere",
|
|
574
|
+
"type": "file_path",
|
|
575
|
+
"value": "RSA key size 1024 anywhere in source: `modulusLength:\\s*1024`, `key_size=1024`, `\"rsa\", 1024`, `RSAKeyPairGenerator.*1024`, `Generate(\\w+)Key\\(.*1024`",
|
|
576
|
+
"description": "RSA-1024 is below current security margin (NIST SP 800-131A disallowed since 2014). Hard fail in any shipped library.",
|
|
577
|
+
"confidence": "deterministic",
|
|
578
|
+
"deterministic": true
|
|
579
|
+
},
|
|
580
|
+
{
|
|
581
|
+
"id": "math-random-in-security-path",
|
|
582
|
+
"type": "file_path",
|
|
583
|
+
"value": "`Math\\.random\\(`, `random\\.random\\(`, `random\\.randint\\(`, `random\\.choice\\(`, `mt_rand\\(`, `rand\\(\\)`, `srand\\(` in a production source file (not in test/spec/fixture allowlist) AND the output is assignable to a variable whose name matches `(token|secret|key|salt|nonce|iv|seed|state|jwt|jti|csrf|session)`.",
|
|
584
|
+
"description": "CWE-338 — non-cryptographic RNG used in security context. Hard fail. Confidence deterministic when the variable-name correlation is present; high otherwise pending data-flow analysis.",
|
|
585
|
+
"confidence": "deterministic",
|
|
586
|
+
"deterministic": true
|
|
587
|
+
},
|
|
588
|
+
{
|
|
589
|
+
"id": "pbkdf2-under-iterated",
|
|
590
|
+
"type": "file_path",
|
|
591
|
+
"value": "`pbkdf2(Sync)?\\(.*?(?P<iter>\\d+).*?\\)`, `hashlib\\.pbkdf2_hmac\\(.*?(?P<iter>\\d+)\\s*\\)`, configuration defaults named `iterations` / `pbkdf2_rounds` with literal value. iter < 600000 for SHA256, < 210000 for SHA512, < 1300000 for SHA1.",
|
|
592
|
+
"description": "PBKDF2 iteration count below OWASP 2023 minimum.",
|
|
593
|
+
"confidence": "deterministic",
|
|
594
|
+
"deterministic": true
|
|
595
|
+
},
|
|
596
|
+
{
|
|
597
|
+
"id": "bcrypt-cost-low",
|
|
598
|
+
"type": "file_path",
|
|
599
|
+
"value": "`bcrypt\\.(hash|hashSync|gen_salt)\\([^,]*?,\\s*(\\d+)`, `BCrypt::Password\\.create\\(.*?cost:\\s*(\\d+)`, configuration `cost` / `rounds` default < 12.",
|
|
600
|
+
"description": "bcrypt cost factor < 12. Below 2026 security margin for password storage in a published library.",
|
|
601
|
+
"confidence": "deterministic",
|
|
602
|
+
"deterministic": true
|
|
603
|
+
},
|
|
604
|
+
{
|
|
605
|
+
"id": "ecdsa-without-pqc-roadmap",
|
|
606
|
+
"type": "behavioral_signal",
|
|
607
|
+
"value": "Signature call sites use ECDSA-P256 / ECDSA-P384 / Ed25519 exclusively AND no ML-DSA / SLH-DSA implementation exists in the source tree AND the library README or SECURITY.md does not declare a hybrid-signature migration roadmap.",
|
|
608
|
+
"description": "Bare ECDSA today is acceptable cryptographically but downstream consumers with > 5y sensitivity horizons inherit the HNDL problem. Library should at minimum publish a hybrid-signature migration roadmap.",
|
|
609
|
+
"confidence": "high",
|
|
610
|
+
"deterministic": false,
|
|
611
|
+
"attack_ref": "T1573"
|
|
612
|
+
},
|
|
613
|
+
{
|
|
614
|
+
"id": "no-ml-kem-implementation",
|
|
615
|
+
"type": "behavioral_signal",
|
|
616
|
+
"value": "Library claims PQC readiness (README / SECURITY.md / package description / configuration flag named `pqc*` or `postQuantum*`) AND no ML-KEM / Kyber call site exists in the source tree AND no concrete dependency on liboqs / noble-post-quantum / pqcrypto / aws-lc-rs PQC / OpenSSL >= 3.5 with PQC enabled is present in package manifest + lockfile.",
|
|
617
|
+
"description": "'PQC-ready' claim with no PQC implementation. Marketing theater.",
|
|
618
|
+
"confidence": "deterministic",
|
|
619
|
+
"deterministic": true,
|
|
620
|
+
"attack_ref": "T1573"
|
|
621
|
+
},
|
|
622
|
+
{
|
|
623
|
+
"id": "fips-claim-without-runtime-activation",
|
|
624
|
+
"type": "behavioral_signal",
|
|
625
|
+
"value": "Library claims FIPS validation / FIPS-compliance / FIPS-mode (README / SECURITY.md / package description / compliance manifest) AND no `OSSL_PROVIDER_load(*, \\\"fips\\\", *)` / `crypto.setFips(true)` / `Provider::load.*\\\"fips\\\"` call site exists in the source tree AND no runtime assertion that the FIPS provider is selected exists.",
|
|
626
|
+
"description": "Link-time FIPS claim without runtime activation. Theater.",
|
|
627
|
+
"confidence": "deterministic",
|
|
628
|
+
"deterministic": true
|
|
629
|
+
},
|
|
630
|
+
{
|
|
631
|
+
"id": "vendored-pqc-no-provenance",
|
|
632
|
+
"type": "file_path",
|
|
633
|
+
"value": "Vendored ML-KEM / Kyber / Dilithium / SLH-DSA / SPHINCS+ implementation exists under vendor/ / third_party/ / crates/ AND no UPSTREAM / ORIGIN / PROVENANCE.md / `.upstream-commit` / integrity hash record is co-located AND no CI step verifies the vendored copy against an upstream hash.",
|
|
634
|
+
"description": "Vendored PQC without provenance. Supply-chain attack opportunity.",
|
|
635
|
+
"confidence": "high",
|
|
636
|
+
"deterministic": false
|
|
637
|
+
},
|
|
638
|
+
{
|
|
639
|
+
"id": "hardcoded-key-material",
|
|
640
|
+
"type": "file_path",
|
|
641
|
+
"value": "PEM markers `-----BEGIN (RSA |EC |DSA )?(PRIVATE|PUBLIC) KEY-----` or `-----BEGIN CERTIFICATE-----` in source files NOT under test/spec/fixture/examples/docs allowlist. Cross-reference with secrets playbook.",
|
|
642
|
+
"description": "Hardcoded key material in shipped source. If labeled 'example' or 'demo', flag the universal-default-credential risk for downstream consumers.",
|
|
643
|
+
"confidence": "deterministic",
|
|
644
|
+
"deterministic": true
|
|
645
|
+
},
|
|
646
|
+
{
|
|
647
|
+
"id": "tls-old-protocol",
|
|
648
|
+
"type": "file_path",
|
|
649
|
+
"value": "`secureProtocol:\\s*['\"](TLSv1_method|TLSv1_1_method|SSLv23_method|SSLv3_method)['\"]`, `minVersion:\\s*['\"](TLSv1(\\.0|\\.1)?)['\"]`, `ssl_version=ssl\\.PROTOCOL_TLSv1(_1)?`, `MinTlsVersion::TLSv1`.",
|
|
650
|
+
"description": "TLS < 1.2 minimum in shipped TLS-context construction.",
|
|
651
|
+
"confidence": "deterministic",
|
|
652
|
+
"deterministic": true
|
|
653
|
+
},
|
|
654
|
+
{
|
|
655
|
+
"id": "no-crypto-agility-abstraction",
|
|
656
|
+
"type": "behavioral_signal",
|
|
657
|
+
"value": "Library claims crypto-agility AND no interface/trait/abstract-class with >= 2 implementations exists for the relevant primitive (signer, KEM, hash) AND no registration hook for downstream consumers to supply implementations exists.",
|
|
658
|
+
"description": "Crypto-agility claim without structural pluggability.",
|
|
659
|
+
"confidence": "high",
|
|
660
|
+
"deterministic": false
|
|
661
|
+
}
|
|
662
|
+
],
|
|
663
|
+
"false_positive_profile": [
|
|
664
|
+
{
|
|
665
|
+
"indicator_id": "weak-hash-import",
|
|
666
|
+
"benign_pattern": "MD5 / SHA1 used for non-security purposes (cache key, ETag, content dedup, git-style object addressing) with inline comment justification and no downstream flow into auth/integrity code.",
|
|
667
|
+
"distinguishing_test": "Re-grep with -A 5 around each hit. If an inline comment within 5 lines explicitly justifies non-security usage (e.g. '// MD5 is fine: dedup hash, not security') AND a static-analysis annotation is present (e.g. `// eslint-disable-next-line crypto/no-md5`, `# nosec B303`) AND a data-flow trace shows no path into auth/integrity/signature code: downgrade to low and annotate `non_security_use_justified=true`."
|
|
668
|
+
},
|
|
669
|
+
{
|
|
670
|
+
"indicator_id": "math-random-in-security-path",
|
|
671
|
+
"benign_pattern": "Math.random() used for genuinely non-security purposes (jitter in backoff, UI animation timing, test fixtures, demo data shuffling).",
|
|
672
|
+
"distinguishing_test": "Trace the variable's downstream usage. If the value never crosses (a) a token boundary, (b) a key/nonce/IV/salt, (c) an authorization decision, (d) a tamper-evident log seed: downgrade to medium. Note: backoff jitter is a known false-positive category — explicit `// non-security: backoff jitter` comment downgrades to low."
|
|
673
|
+
},
|
|
674
|
+
{
|
|
675
|
+
"indicator_id": "rsa-1024-anywhere",
|
|
676
|
+
"benign_pattern": "RSA-1024 in test fixtures / known-bad test vectors / migration code that decrypts legacy RSA-1024 content to re-encrypt under stronger crypto.",
|
|
677
|
+
"distinguishing_test": "Check path against test/spec/fixture allowlist. If outside allowlist but inside a clearly-named migration / legacy-decryption module with inline comment justification, downgrade to medium and require the migration code be reachable only from a one-time-migration entry point (not the library's public API)."
|
|
678
|
+
},
|
|
679
|
+
{
|
|
680
|
+
"indicator_id": "ecdsa-without-pqc-roadmap",
|
|
681
|
+
"benign_pattern": "Library is in a domain where consumer sensitivity horizons are universally < 5 years (transient session tokens, short-lived service auth, ephemeral CI signing).",
|
|
682
|
+
"distinguishing_test": "Read the library README + package description. If domain is explicitly short-horizon (e.g. 'ephemeral session token library', 'transient OTP signer'), downgrade ECDSA-only to medium and annotate `horizon_documented=short`. If the library is general-purpose, the finding stands — downstream consumers may use it for long-horizon data."
|
|
683
|
+
},
|
|
684
|
+
{
|
|
685
|
+
"indicator_id": "fips-claim-without-runtime-activation",
|
|
686
|
+
"benign_pattern": "Library does not claim FIPS — the audit re-discovered the absence of FIPS activation, which is unremarkable.",
|
|
687
|
+
"distinguishing_test": "Grep for FIPS-related claims in README, package description, SECURITY.md, compliance manifests. If no claim exists, suppress the indicator. If a claim exists in any of those locations, the indicator stands."
|
|
688
|
+
},
|
|
689
|
+
{
|
|
690
|
+
"indicator_id": "hardcoded-key-material",
|
|
691
|
+
"benign_pattern": "Test fixtures, example certs, demo HMAC seeds clearly under test/spec/example/docs paths.",
|
|
692
|
+
"distinguishing_test": "Path-allowlist check. Additionally, examine whether the example key is reachable from the library's public API or used by default in any code path. If yes, the finding stands (universal-default-credential risk). If no, downgrade to low and annotate `example_key_isolated=true`."
|
|
693
|
+
}
|
|
694
|
+
],
|
|
695
|
+
"minimum_signal": {
|
|
696
|
+
"detected": "Any deterministic indicator fires in a production-context source path (outside test/spec/fixture/example allowlist) AND the library is intended for downstream consumption. Confirmed library-author crypto-debt: shipped defaults will propagate to all downstream consumers regardless of their own security posture.",
|
|
697
|
+
"inconclusive": "Source tree partially grepped (some files unreadable, or generic-language heuristics applied to an unfamiliar ecosystem) AND at least one heuristic indicator fired without deterministic confirmation. Cannot deny without complete walk.",
|
|
698
|
+
"not_detected": "Complete source-tree walk completed AND no deterministic indicators fired AND PQC adoption signal is present (concrete ML-KEM / ML-DSA implementation) OR the library is small-surface with explicitly-classical short-horizon scope documented AND FIPS claim (if present) is backed by runtime activation AND vendored crypto (if any) has provenance + integrity + constant-time evidence."
|
|
699
|
+
}
|
|
700
|
+
},
|
|
701
|
+
"analyze": {
|
|
702
|
+
"rwep_inputs": [
|
|
703
|
+
{
|
|
704
|
+
"signal_id": "weak-hash-import",
|
|
705
|
+
"rwep_factor": "blast_radius",
|
|
706
|
+
"weight": 25,
|
|
707
|
+
"notes": "Library shipping MD5/SHA1 as default propagates to every downstream consumer. Blast radius scaled by library install base."
|
|
708
|
+
},
|
|
709
|
+
{
|
|
710
|
+
"signal_id": "weak-hash-import",
|
|
711
|
+
"rwep_factor": "public_poc",
|
|
712
|
+
"weight": 15,
|
|
713
|
+
"notes": "MD5 collision attacks are public + tooled (HashClash, etc.). SHA1 collisions documented (SHAttered 2017)."
|
|
714
|
+
},
|
|
715
|
+
{
|
|
716
|
+
"signal_id": "weak-cipher-mode",
|
|
717
|
+
"rwep_factor": "blast_radius",
|
|
718
|
+
"weight": 25,
|
|
719
|
+
"notes": "ECB / DES / RC4 shipped in a library is catastrophic across the consumer base."
|
|
720
|
+
},
|
|
721
|
+
{
|
|
722
|
+
"signal_id": "weak-cipher-mode",
|
|
723
|
+
"rwep_factor": "public_poc",
|
|
724
|
+
"weight": 20,
|
|
725
|
+
"notes": "ECB visualization attacks, Sweet32 (3DES), RC4 biases — all public and tooled."
|
|
726
|
+
},
|
|
727
|
+
{
|
|
728
|
+
"signal_id": "rsa-1024-anywhere",
|
|
729
|
+
"rwep_factor": "blast_radius",
|
|
730
|
+
"weight": 25,
|
|
731
|
+
"notes": "RSA-1024 factorization within reach of state-level adversaries today; NIST disallowed since 2014."
|
|
732
|
+
},
|
|
733
|
+
{
|
|
734
|
+
"signal_id": "math-random-in-security-path",
|
|
735
|
+
"rwep_factor": "blast_radius",
|
|
736
|
+
"weight": 25,
|
|
737
|
+
"notes": "Predictable tokens / keys / nonces = universal-key vulnerability shipped to every consumer."
|
|
738
|
+
},
|
|
739
|
+
{
|
|
740
|
+
"signal_id": "math-random-in-security-path",
|
|
741
|
+
"rwep_factor": "ai_weaponization",
|
|
742
|
+
"weight": 10,
|
|
743
|
+
"notes": "AI-assisted code audit identifies these instantly; exploitation tooling against weak RNG is mature."
|
|
744
|
+
},
|
|
745
|
+
{
|
|
746
|
+
"signal_id": "pbkdf2-under-iterated",
|
|
747
|
+
"rwep_factor": "blast_radius",
|
|
748
|
+
"weight": 20,
|
|
749
|
+
"notes": "Under-iterated KDF shipped as default = every consumer's stored passwords are GPU-crackable."
|
|
750
|
+
},
|
|
751
|
+
{
|
|
752
|
+
"signal_id": "ecdsa-without-pqc-roadmap",
|
|
753
|
+
"rwep_factor": "blast_radius",
|
|
754
|
+
"weight": 15,
|
|
755
|
+
"notes": "HNDL future-tense exposure for long-horizon downstream consumers."
|
|
756
|
+
},
|
|
757
|
+
{
|
|
758
|
+
"signal_id": "ecdsa-without-pqc-roadmap",
|
|
759
|
+
"rwep_factor": "active_exploitation",
|
|
760
|
+
"weight": 10,
|
|
761
|
+
"notes": "HNDL recording is operational reality. Active exploitation in recording sense."
|
|
762
|
+
},
|
|
763
|
+
{
|
|
764
|
+
"signal_id": "no-ml-kem-implementation",
|
|
765
|
+
"rwep_factor": "blast_radius",
|
|
766
|
+
"weight": 15,
|
|
767
|
+
"notes": "Marketing-only PQC claim misleads downstream procurement decisions."
|
|
768
|
+
},
|
|
769
|
+
{
|
|
770
|
+
"signal_id": "fips-claim-without-runtime-activation",
|
|
771
|
+
"rwep_factor": "blast_radius",
|
|
772
|
+
"weight": 20,
|
|
773
|
+
"notes": "Downstream consumers running federal / regulated workloads inherit a false FIPS claim."
|
|
774
|
+
},
|
|
775
|
+
{
|
|
776
|
+
"signal_id": "vendored-pqc-no-provenance",
|
|
777
|
+
"rwep_factor": "ai_weaponization",
|
|
778
|
+
"weight": 10,
|
|
779
|
+
"notes": "Supply-chain attacks on vendored crypto are AI-assistable; provenance gap is exploitable."
|
|
780
|
+
},
|
|
781
|
+
{
|
|
782
|
+
"signal_id": "vendored-pqc-no-provenance",
|
|
783
|
+
"rwep_factor": "blast_radius",
|
|
784
|
+
"weight": 20,
|
|
785
|
+
"notes": "Backdoored or trojanized vendored crypto propagates to every consumer install."
|
|
786
|
+
},
|
|
787
|
+
{
|
|
788
|
+
"signal_id": "hardcoded-key-material",
|
|
789
|
+
"rwep_factor": "blast_radius",
|
|
790
|
+
"weight": 25,
|
|
791
|
+
"notes": "Universal-default-credential risk if the example key is used by any default code path."
|
|
792
|
+
},
|
|
793
|
+
{
|
|
794
|
+
"signal_id": "hardcoded-key-material",
|
|
795
|
+
"rwep_factor": "public_poc",
|
|
796
|
+
"weight": 15,
|
|
797
|
+
"notes": "Universal-default-credential exploitation is a well-established pattern (Mirai et al.)."
|
|
798
|
+
},
|
|
799
|
+
{
|
|
800
|
+
"signal_id": "tls-old-protocol",
|
|
801
|
+
"rwep_factor": "blast_radius",
|
|
802
|
+
"weight": 20,
|
|
803
|
+
"notes": "Shipping TLS < 1.2 minimum exposes every consumer to BEAST/Lucky13/POODLE-class downgrade attacks."
|
|
804
|
+
}
|
|
805
|
+
],
|
|
806
|
+
"blast_radius_model": {
|
|
807
|
+
"scope_question": "If a library author ships this crypto choice as a default, how many downstream consumers inherit the vulnerability, and across what cumulative sensitivity horizon?",
|
|
808
|
+
"scoring_rubric": [
|
|
809
|
+
{
|
|
810
|
+
"condition": "library is internal-only, < 5 consumer applications, short-horizon data only",
|
|
811
|
+
"blast_radius_score": 1,
|
|
812
|
+
"description": "Limited blast; remediation is single-author + few-consumer coordination."
|
|
813
|
+
},
|
|
814
|
+
{
|
|
815
|
+
"condition": "library is published to a registry with < 10,000 weekly installs OR is an SDK for a small ecosystem (< 100 downstream products)",
|
|
816
|
+
"blast_radius_score": 2,
|
|
817
|
+
"description": "Bounded blast; downstream consumer notification feasible by direct outreach."
|
|
818
|
+
},
|
|
819
|
+
{
|
|
820
|
+
"condition": "library is published with 10,000 - 1M weekly installs OR is an SDK for a regulated industry (payments, healthcare, identity)",
|
|
821
|
+
"blast_radius_score": 3,
|
|
822
|
+
"description": "Significant blast; coordinated disclosure required; downstream consumers include essential entities under NIS2 or HIPAA-covered entities."
|
|
823
|
+
},
|
|
824
|
+
{
|
|
825
|
+
"condition": "library is published with 1M - 100M weekly installs OR is a framework / language runtime / build tool with industry-wide adoption OR is bundled into a regulated product distribution",
|
|
826
|
+
"blast_radius_score": 4,
|
|
827
|
+
"description": "Massive blast; coordinated vulnerability disclosure with regulator notification; downstream consumer base spans jurisdictions and sensitivity horizons. EU CRA Art.14 24h CSIRT notification activates when exploitation is observed."
|
|
828
|
+
},
|
|
829
|
+
{
|
|
830
|
+
"condition": "library is published with > 100M weekly installs OR is a transitively-depended-on cryptographic primitive provider (e.g. shipping MD5 as a default hash in a top-100 npm package, or a default RNG in a major language runtime)",
|
|
831
|
+
"blast_radius_score": 5,
|
|
832
|
+
"description": "Ecosystem-defining blast; broadcast notification required; comparable to OpenSSL Heartbleed / log4shell coordination."
|
|
833
|
+
}
|
|
834
|
+
]
|
|
835
|
+
},
|
|
836
|
+
"compliance_theater_check": {
|
|
837
|
+
"claim": "Library ships FIPS-validated / NIST-aligned / PQC-ready / strong cryptography. Downstream consumers can rely on the shipped defaults to satisfy their own compliance obligations (NIST 800-53 SC-13, ISO 27001:2022 A.8.24/A.8.28, PCI DSS 4.0 §3.6/§8.3.2, EU CRA Annex I §1).",
|
|
838
|
+
"audit_evidence": "Library README / SECURITY.md / compliance manifest declarations of FIPS / NIST / PQC posture; SBOM publication; vulnerability-handling policy; supply-chain attestation; CI test logs.",
|
|
839
|
+
"reality_test": "Run the following against the source tree (no host probe). (1) FIPS claim test: `rg -nP 'OSSL_PROVIDER_load\\(.*\"fips\"|crypto\\.setFips\\(true\\)|Provider::load\\(.*\"fips\"\\)'` — if zero hits, FIPS claim is link-time theater. (2) PQC-ready test: `rg -nP '\\b(MlKem|ML-KEM|ml_kem|Kyber|MlDsa|ML-DSA|ml_dsa|Dilithium)\\b' --type-add 'src:*.{js,ts,py,go,rs,java,rb,c,h,cpp}' -tsrc` — if zero hits in non-doc/non-test files, PQC claim is marketing toggle. (3) Weak-default test: `rg -nP \"createHash\\(['\\\"](md5|sha1|sha-1)['\\\"]\\)|hashlib\\.(md5|sha1)\\(|MessageDigest\\.getInstance\\(['\\\"](MD5|SHA-1)['\\\"]\\)\"` — any hit in a production source path is a shipped weak default. (4) RNG test: `rg -nP '\\bMath\\.random\\b|\\brandom\\.(random|randint)\\b|\\brand\\(\\)|\\bmt_rand\\b'` with test-path exclusion — any hit assignable to a security-named variable is CWE-338. (5) KDF test: `rg -nP 'pbkdf2.*?[, ](\\d{1,5})\\b'` — extract numeric arg, fail if < 600000 for SHA256 default. Theater if ANY of (1)-(5) fails and the library claims FIPS / NIST / PQC / strong-crypto posture.",
|
|
840
|
+
"theater_verdict_if_gap": "Library ships compliance-toggle declarations whose source code does not implement the claimed primitives or activate the claimed providers. Downstream consumers relying on the library to satisfy SC-13 / A.8.24 / §3.6 / Annex I §1 inherit unvalidated crypto. Remediation paths: (a) implement the runtime activation / primitive call site / parameter floor that backs the claim, (b) retract the claim from README / SECURITY.md / compliance manifest, OR (c) generate a defensible policy exception via policy-exception-gen documenting the time-bound gap, downstream-consumer notification plan, and migration roadmap."
|
|
841
|
+
},
|
|
842
|
+
"framework_gap_mapping": [
|
|
843
|
+
{
|
|
844
|
+
"finding_id": "library-author-crypto-debt",
|
|
845
|
+
"framework": "nist-800-53",
|
|
846
|
+
"claimed_control": "SC-13 — Cryptographic Protection",
|
|
847
|
+
"actual_gap": "Binds the operating organization, not the library author. Library can ship MD5 / PBKDF2-10k / RSA-1024 defaults and remain SC-13-irrelevant. Burden shifts entirely to downstream consumers to audit and reconfigure.",
|
|
848
|
+
"required_control": "Add SC-13(LIB) requiring vendor-shipped cryptographic defaults to (a) match current FIPS-validated algorithm modes, (b) fail closed on non-FIPS provider selection when consumer asserts FIPS mode, (c) declare per-primitive sensitivity-horizon guidance in package metadata."
|
|
849
|
+
},
|
|
850
|
+
{
|
|
851
|
+
"finding_id": "library-author-crypto-debt",
|
|
852
|
+
"framework": "iso-27001-2022",
|
|
853
|
+
"claimed_control": "A.8.28 — Secure coding",
|
|
854
|
+
"actual_gap": "Silent on PQC, KDF iteration minimums, RNG-source requirements, constant-time-implementation requirements. Permits MD5-by-default, PBKDF2-10k, Math.random in token generation as 'secure coding' practices.",
|
|
855
|
+
"required_control": "Amendment requiring (a) banned-primitive list (MD5/SHA1/DES/3DES/RC4/RSA-1024 in security context), (b) minimum-parameter floors (PBKDF2 >= OWASP current, bcrypt >= 12, scrypt N >= 2^17, argon2id m >= 19 MiB), (c) cryptographic-RNG enforcement in security context, (d) constant-time-implementation requirement for shipped primitives."
|
|
856
|
+
},
|
|
857
|
+
{
|
|
858
|
+
"finding_id": "library-author-crypto-debt",
|
|
859
|
+
"framework": "iso-27001-2022",
|
|
860
|
+
"claimed_control": "A.8.24 — Use of cryptography",
|
|
861
|
+
"actual_gap": "Targets the using organization. No upstream library-author hook.",
|
|
862
|
+
"required_control": "Companion control A.8.24(LIB) binding library authors who publish cryptographic primitives to declare conformance to A.8.24 in package metadata, with downstream-consumer-facing crypto-attribute disclosure."
|
|
863
|
+
},
|
|
864
|
+
{
|
|
865
|
+
"finding_id": "library-author-crypto-debt",
|
|
866
|
+
"framework": "pci-dss-4",
|
|
867
|
+
"claimed_control": "§3.6 / §8.3.2 — Strong cryptography and password storage",
|
|
868
|
+
"actual_gap": "Binds merchants and service providers. A payment library shipping PBKDF2-10k is what the merchant inherits without explicit override; no framework hook to push upstream.",
|
|
869
|
+
"required_control": "PCI Council guidance binding upstream library vendors targeting PCI-relevant code paths to ship parameter floors matching the merchant-facing requirements."
|
|
870
|
+
},
|
|
871
|
+
{
|
|
872
|
+
"finding_id": "library-author-crypto-debt",
|
|
873
|
+
"framework": "eu-cra",
|
|
874
|
+
"claimed_control": "Annex I §1 — State-of-the-art cryptography, secure defaults",
|
|
875
|
+
"actual_gap": "Binding 2026-09-11 for vulnerability handling / SBOM provisions; full 2027-12-11. 'State-of-the-art' interpretive without NIST PQC reference. Today not yet legally binding on most library authors.",
|
|
876
|
+
"required_control": "Implementing acts binding 'state-of-the-art' to NIST FIPS 203/204/205 for new shipped primitives, OWASP-current parameter floors for KDFs, FIPS 140-3 provider activation discipline for products that claim FIPS posture."
|
|
877
|
+
},
|
|
878
|
+
{
|
|
879
|
+
"finding_id": "library-author-crypto-debt",
|
|
880
|
+
"framework": "nis2",
|
|
881
|
+
"claimed_control": "Art.21(2)(g) — Supply-chain security",
|
|
882
|
+
"actual_gap": "Binds the essential entity, not the library author. Indirect pressure via procurement.",
|
|
883
|
+
"required_control": "Implementing acts requiring essential entities to require upstream library vendors to publish cryptographic-attribute disclosure and to fail procurement on undisclosed or weak shipped defaults."
|
|
884
|
+
},
|
|
885
|
+
{
|
|
886
|
+
"finding_id": "library-author-crypto-debt",
|
|
887
|
+
"framework": "uk-caf",
|
|
888
|
+
"claimed_control": "C.5 — Connected products / UK PSTI",
|
|
889
|
+
"actual_gap": "Targets connected-product manufacturers. Library authors shipping non-product crypto code are outside scope unless their library is incorporated into a regulated connected product.",
|
|
890
|
+
"required_control": "PSTI extension binding upstream library vendors targeting connected-product code paths to ship modern crypto defaults and to publish minimum-security periods."
|
|
891
|
+
},
|
|
892
|
+
{
|
|
893
|
+
"finding_id": "library-author-crypto-debt",
|
|
894
|
+
"framework": "au-essential-8",
|
|
895
|
+
"claimed_control": "M8 (Application Control) / AU ISM approved-cryptographic-algorithm list",
|
|
896
|
+
"actual_gap": "No direct library-author obligation. AU ISM approved-algorithm list is non-binding without procurement teeth.",
|
|
897
|
+
"required_control": "AU ISM extension making approved-cryptographic-algorithm-list conformance a published library-author obligation, with consumer-facing attestation."
|
|
898
|
+
}
|
|
899
|
+
],
|
|
900
|
+
"escalation_criteria": [
|
|
901
|
+
{
|
|
902
|
+
"condition": "blast_radius_score >= 4 AND any deterministic indicator fires",
|
|
903
|
+
"action": "raise_severity"
|
|
904
|
+
},
|
|
905
|
+
{
|
|
906
|
+
"condition": "rwep >= 75 AND library is published_to_registry == true",
|
|
907
|
+
"action": "page_on_call"
|
|
908
|
+
},
|
|
909
|
+
{
|
|
910
|
+
"condition": "blast_radius_score >= 3",
|
|
911
|
+
"action": "trigger_playbook",
|
|
912
|
+
"target_playbook": "sbom"
|
|
913
|
+
},
|
|
914
|
+
{
|
|
915
|
+
"condition": "compliance_theater_check.verdict == 'theater' AND jurisdiction_obligations contains 'EU'",
|
|
916
|
+
"action": "notify_legal"
|
|
917
|
+
},
|
|
918
|
+
{
|
|
919
|
+
"condition": "indicator_id == 'fips-claim-without-runtime-activation' AND library_marketed_for_federal_use == true",
|
|
920
|
+
"action": "notify_legal"
|
|
921
|
+
}
|
|
922
|
+
]
|
|
923
|
+
},
|
|
924
|
+
"validate": {
|
|
925
|
+
"remediation_paths": [
|
|
926
|
+
{
|
|
927
|
+
"id": "rotate-to-pqc-hybrid-kem",
|
|
928
|
+
"description": "For any shipped KEM call site or TLS context construction: migrate to hybrid X25519+ML-KEM-768. Use noble-post-quantum (JS), pqcrypto::mlkem (Rust), aws-lc-rs PQC (Rust/C), or OpenSSL >= 3.5 native KEM API (multi-language). Hybrid is mandatory — pure-PQC fails closed if downstream consumer cannot negotiate.",
|
|
929
|
+
"preconditions": [
|
|
930
|
+
"ml_kem_implementation_available_for_language == true",
|
|
931
|
+
"api_stability_promise_permits_default_change == true OR major_version_bump_planned == true"
|
|
932
|
+
],
|
|
933
|
+
"priority": 1,
|
|
934
|
+
"compensating_controls": [
|
|
935
|
+
"config_flag_for_classical_only_fallback_with_deprecation_warning",
|
|
936
|
+
"downstream_consumer_migration_guide_published"
|
|
937
|
+
],
|
|
938
|
+
"estimated_time_hours": 24
|
|
939
|
+
},
|
|
940
|
+
{
|
|
941
|
+
"id": "rotate-to-ed25519-or-ml-dsa-signature",
|
|
942
|
+
"description": "For shipped signature call sites: prefer Ed25519 today, hybrid Ed25519+ML-DSA-65 once downstream consumers can verify. RSA-PKCS1 -> RSA-PSS minimum; bare ECDSA-P256 retained only for short-horizon use cases with documentation. Add ML-DSA / SLH-DSA implementation for forward-looking long-horizon use.",
|
|
943
|
+
"preconditions": [
|
|
944
|
+
"signature_call_site_count_inventoried == true",
|
|
945
|
+
"downstream_consumer_compat_path_planned == true"
|
|
946
|
+
],
|
|
947
|
+
"priority": 2,
|
|
948
|
+
"compensating_controls": [
|
|
949
|
+
"dual_signature_envelope_during_migration",
|
|
950
|
+
"explicit_algorithm_identifier_in_signed_payload"
|
|
951
|
+
],
|
|
952
|
+
"estimated_time_hours": 16
|
|
953
|
+
},
|
|
954
|
+
{
|
|
955
|
+
"id": "swap-deprecated-hash",
|
|
956
|
+
"description": "Replace MD5 / SHA1 in security-context call sites with SHA-256 / SHA-384 / SHA-512 / SHA3-256 / BLAKE2b. For HMAC keys, increase output to >= 256 bits. Where the hash is genuinely non-security, add inline justification + static-analysis annotation.",
|
|
957
|
+
"preconditions": [
|
|
958
|
+
"weak_hash_call_sites_inventoried == true"
|
|
959
|
+
],
|
|
960
|
+
"priority": 3,
|
|
961
|
+
"compensating_controls": [
|
|
962
|
+
"deprecation_warning_emitted_when_legacy_hash_method_invoked",
|
|
963
|
+
"telemetry_to_track_legacy_method_consumer_usage"
|
|
964
|
+
],
|
|
965
|
+
"estimated_time_hours": 8
|
|
966
|
+
},
|
|
967
|
+
{
|
|
968
|
+
"id": "increase-kdf-iterations",
|
|
969
|
+
"description": "Raise PBKDF2 default to >= 600,000 (SHA256) / >= 210,000 (SHA512) / >= 1,300,000 (SHA1, with deprecation plan); bcrypt cost factor to >= 12; scrypt N to >= 2^17 (r=8, p=1); argon2id to m=19 MiB, t=2, p=1. Allow consumer override upward but not downward.",
|
|
970
|
+
"preconditions": [
|
|
971
|
+
"kdf_call_site_inventoried == true",
|
|
972
|
+
"performance_regression_acceptable_in_current_release == true"
|
|
973
|
+
],
|
|
974
|
+
"priority": 4,
|
|
975
|
+
"compensating_controls": [
|
|
976
|
+
"kdf_parameter_floor_enforced_at_runtime_not_just_default",
|
|
977
|
+
"consumer_documentation_about_password_rehash_on_login_for_legacy_storage"
|
|
978
|
+
],
|
|
979
|
+
"estimated_time_hours": 4
|
|
980
|
+
},
|
|
981
|
+
{
|
|
982
|
+
"id": "upgrade-random-source",
|
|
983
|
+
"description": "Replace Math.random / random.random / rand in security context with crypto.randomBytes / crypto.getRandomValues / secrets.token_bytes / os.urandom / SecureRandom / OsRng / getrandom(). Add lint rule banning the weak APIs in production paths.",
|
|
984
|
+
"preconditions": [
|
|
985
|
+
"rng_call_sites_inventoried == true"
|
|
986
|
+
],
|
|
987
|
+
"priority": 5,
|
|
988
|
+
"compensating_controls": [
|
|
989
|
+
"linter_rule_added_to_ci",
|
|
990
|
+
"data_flow_analysis_for_residual_paths"
|
|
991
|
+
],
|
|
992
|
+
"estimated_time_hours": 4
|
|
993
|
+
},
|
|
994
|
+
{
|
|
995
|
+
"id": "activate-fips-provider-or-retract-claim",
|
|
996
|
+
"description": "If FIPS claim is to be retained: add explicit `OSSL_PROVIDER_load(ctx, \"fips\", NULL)` (or language-equivalent), assert at runtime that the FIPS provider is selected, fail closed if non-FIPS provider is active when FIPS mode is requested, ship a tested openssl.cnf / fipsmodule.cnf. If FIPS posture cannot be backed: retract the claim from README / SECURITY.md / compliance manifest.",
|
|
997
|
+
"preconditions": [
|
|
998
|
+
"fips_provider_available_in_target_dep == true"
|
|
999
|
+
],
|
|
1000
|
+
"priority": 6,
|
|
1001
|
+
"compensating_controls": [
|
|
1002
|
+
"fips_runtime_assertion_in_init_path",
|
|
1003
|
+
"ci_job_running_against_fips_provider_config"
|
|
1004
|
+
],
|
|
1005
|
+
"estimated_time_hours": 12
|
|
1006
|
+
},
|
|
1007
|
+
{
|
|
1008
|
+
"id": "establish-vendored-crypto-provenance",
|
|
1009
|
+
"description": "For each vendored cryptographic primitive: record UPSTREAM commit hash, ORIGIN URL, integrity hash; add CI step verifying the vendored copy against upstream; run constant-time analysis (dudect / ctgrind / valgrind) in CI on secret-dependent code paths.",
|
|
1010
|
+
"preconditions": [
|
|
1011
|
+
"vendored_crypto_inventoried == true"
|
|
1012
|
+
],
|
|
1013
|
+
"priority": 7,
|
|
1014
|
+
"compensating_controls": [
|
|
1015
|
+
"vendored_copy_pinned_to_release_tag_not_branch",
|
|
1016
|
+
"automated_upstream_security_advisory_subscription"
|
|
1017
|
+
],
|
|
1018
|
+
"estimated_time_hours": 16
|
|
1019
|
+
},
|
|
1020
|
+
{
|
|
1021
|
+
"id": "publish-crypto-agility-abstraction",
|
|
1022
|
+
"description": "Refactor crypto layer to an interface / trait with >= 2 implementations and a registration hook for downstream consumers to supply alternative implementations. Algorithm identifier travels with ciphertext / signature for forward decoding.",
|
|
1023
|
+
"preconditions": [
|
|
1024
|
+
"api_change_acceptable_in_next_major == true"
|
|
1025
|
+
],
|
|
1026
|
+
"priority": 8,
|
|
1027
|
+
"compensating_controls": [
|
|
1028
|
+
"deprecation_path_for_old_api",
|
|
1029
|
+
"migration_guide_published"
|
|
1030
|
+
],
|
|
1031
|
+
"estimated_time_hours": 40
|
|
1032
|
+
},
|
|
1033
|
+
{
|
|
1034
|
+
"id": "policy-exception",
|
|
1035
|
+
"description": "If a deprecated primitive cannot be removed in a minor version due to API-stability promise: generate auditor-ready policy exception. Time-bound until next major version with explicit migration roadmap, deprecation warning emitted at runtime, parallel new API published, downstream-consumer migration guide.",
|
|
1036
|
+
"preconditions": [
|
|
1037
|
+
"remediation_paths[1..8] blocked for this specific primitive due to api_stability == true",
|
|
1038
|
+
"next_major_version_window <= 12_months",
|
|
1039
|
+
"ciso_or_maintainer_acceptance_obtainable == true"
|
|
1040
|
+
],
|
|
1041
|
+
"priority": 9,
|
|
1042
|
+
"compensating_controls": [
|
|
1043
|
+
"runtime_deprecation_warning",
|
|
1044
|
+
"parallel_new_api_with_modern_crypto",
|
|
1045
|
+
"downstream_consumer_migration_guide",
|
|
1046
|
+
"ci_failure_for_new_usage_of_deprecated_method"
|
|
1047
|
+
],
|
|
1048
|
+
"estimated_time_hours": 6
|
|
1049
|
+
}
|
|
1050
|
+
],
|
|
1051
|
+
"validation_tests": [
|
|
1052
|
+
{
|
|
1053
|
+
"id": "no-md5-sha1-in-production-paths",
|
|
1054
|
+
"test": "Run `rg -nP \"createHash\\(['\\\"](md5|sha1|sha-1)['\\\"]\\)|hashlib\\.(md5|sha1)\\(|MessageDigest\\.getInstance\\(['\\\"](MD5|SHA-1)['\\\"]\\)\" --type-add 'src:*.{js,ts,py,go,rs,java,rb,c,h,cpp,kt,swift,php}' -tsrc --glob '!**/test/**' --glob '!**/spec/**' --glob '!**/fixtures/**' --glob '!**/examples/**'`. Expect zero hits.",
|
|
1055
|
+
"expected_result": "Empty grep output. Zero MD5/SHA1 in production source paths.",
|
|
1056
|
+
"test_type": "functional"
|
|
1057
|
+
},
|
|
1058
|
+
{
|
|
1059
|
+
"id": "no-math-random-in-security-paths",
|
|
1060
|
+
"test": "Run `rg -nP '\\bMath\\.random\\b|\\brandom\\.(random|randint|choice)\\b|\\bmt_rand\\(' --type-add 'src:*.{js,ts,py,php}' -tsrc --glob '!**/test/**' --glob '!**/fixtures/**'` AND a follow-up data-flow grep that the surviving hits don't flow into `(token|secret|key|salt|nonce|iv|seed|state|jwt|jti|csrf|session)` named variables.",
|
|
1061
|
+
"expected_result": "Either zero hits, or all surviving hits annotated `// non-security: <reason>` and confirmed not flowing into security-named identifiers.",
|
|
1062
|
+
"test_type": "functional"
|
|
1063
|
+
},
|
|
1064
|
+
{
|
|
1065
|
+
"id": "pbkdf2-defaults-meet-owasp-2023",
|
|
1066
|
+
"test": "Open every PBKDF2 call site and config default. Confirm iteration count >= 600,000 for SHA256, >= 210,000 for SHA512, >= 1,300,000 for SHA1.",
|
|
1067
|
+
"expected_result": "All shipped PBKDF2 defaults meet OWASP 2023 floor.",
|
|
1068
|
+
"test_type": "functional"
|
|
1069
|
+
},
|
|
1070
|
+
{
|
|
1071
|
+
"id": "no-rsa-1024-anywhere",
|
|
1072
|
+
"test": "Run `rg -nP 'modulusLength:\\s*1024|key_size\\s*=\\s*1024|\"rsa\",\\s*1024|RSAKeyPairGenerator.*1024'`. Expect zero hits outside test/fixture/legacy-migration paths.",
|
|
1073
|
+
"expected_result": "Zero RSA-1024 occurrences in production paths.",
|
|
1074
|
+
"test_type": "functional"
|
|
1075
|
+
},
|
|
1076
|
+
{
|
|
1077
|
+
"id": "fips-runtime-activation-present",
|
|
1078
|
+
"test": "If FIPS claim retained: run `rg -nP 'OSSL_PROVIDER_load\\(.*\"fips\"|crypto\\.setFips\\(true\\)|Provider::load\\(.*\"fips\"\\)'`. Confirm at least one call site in the initialization path; confirm a runtime assertion that the FIPS provider is selected exists.",
|
|
1079
|
+
"expected_result": "Runtime FIPS-provider activation present and asserted; CI job runs the library against a FIPS-provider config.",
|
|
1080
|
+
"test_type": "functional"
|
|
1081
|
+
},
|
|
1082
|
+
{
|
|
1083
|
+
"id": "pqc-implementation-present-if-claimed",
|
|
1084
|
+
"test": "If PQC claim retained: run `rg -nP '\\b(MlKem|ML-KEM|ml_kem|Kyber|kemEncapsulate|kemDecapsulate)\\b' -tsrc --glob '!**/doc*/**' --glob '!**/README*'`. Confirm at least one concrete cryptographic operation (not just config strings).",
|
|
1085
|
+
"expected_result": "At least one ML-KEM-class concrete primitive call site in production source.",
|
|
1086
|
+
"test_type": "functional"
|
|
1087
|
+
},
|
|
1088
|
+
{
|
|
1089
|
+
"id": "vendored-crypto-provenance-verified",
|
|
1090
|
+
"test": "For each vendored crypto module: open the co-located PROVENANCE.md / UPSTREAM / .upstream-commit and confirm an integrity hash is recorded; check CI config for an automated verification step.",
|
|
1091
|
+
"expected_result": "Every vendored crypto module has provenance + integrity verification + constant-time test in CI.",
|
|
1092
|
+
"test_type": "functional"
|
|
1093
|
+
},
|
|
1094
|
+
{
|
|
1095
|
+
"id": "old-api-still-works-during-deprecation",
|
|
1096
|
+
"test": "For deprecated-with-exception paths: run the library's existing test suite. Confirm legacy API still operates (emitting deprecation warnings) and downstream-compat tests still pass.",
|
|
1097
|
+
"expected_result": "Legacy API operative with deprecation warning; downstream-compat tests pass.",
|
|
1098
|
+
"test_type": "regression"
|
|
1099
|
+
},
|
|
1100
|
+
{
|
|
1101
|
+
"id": "old-primitive-no-longer-default",
|
|
1102
|
+
"test": "Invoke the library's modern crypto entry points without specifying an algorithm. Confirm the negotiated/used algorithm is modern (SHA-256+ for hashing, PBKDF2 >= 600k for KDF, hybrid PQC for KEM where supported).",
|
|
1103
|
+
"expected_result": "Modern primitive is the default; weak primitive only reachable via explicit legacy API.",
|
|
1104
|
+
"test_type": "negative"
|
|
1105
|
+
},
|
|
1106
|
+
{
|
|
1107
|
+
"id": "md5-collision-replay-against-fixed-code",
|
|
1108
|
+
"test": "Use a published MD5 collision pair (e.g. HashClash-generated PDF pair) and feed it to the library's new modern-hash signature/integrity path. Confirm the collision is no longer accepted as equal-by-hash for security purposes.",
|
|
1109
|
+
"expected_result": "MD5 collision attack does not yield equal-by-hash result through the modernized code path.",
|
|
1110
|
+
"test_type": "exploit_replay"
|
|
1111
|
+
},
|
|
1112
|
+
{
|
|
1113
|
+
"id": "downstream-consumer-compat",
|
|
1114
|
+
"test": "Build a representative downstream consumer against the new library version. Confirm it builds, its tests pass, and the consumer's own crypto-attribute disclosure (if any) is consistent.",
|
|
1115
|
+
"expected_result": "Downstream consumer builds and tests green; consumer-side crypto-attribute disclosure consistent.",
|
|
1116
|
+
"test_type": "regression"
|
|
1117
|
+
}
|
|
1118
|
+
],
|
|
1119
|
+
"residual_risk_statement": {
|
|
1120
|
+
"risk": "Even after remediation, downstream consumers may pin to a pre-remediation version, may use the deprecated API explicitly during the exception window, or may run the library against a non-FIPS provider config despite FIPS guidance.",
|
|
1121
|
+
"why_remains": "Library authors cannot force consumer upgrades. Deprecation warnings and migration guides reduce but do not eliminate the long tail. API-stability promises bind authors to a multi-release migration path. Downstream consumers in regulated industries may take 12-24 months to adopt a major version bump. The library author's obligation is to ship modern defaults, document the migration path, and emit runtime signals about legacy usage — the residual is on the consumer.",
|
|
1122
|
+
"acceptance_level": "ciso",
|
|
1123
|
+
"compensating_controls_in_place": [
|
|
1124
|
+
"deprecation_warning_emitted_at_runtime_for_legacy_paths",
|
|
1125
|
+
"ci_failure_on_new_internal_usage_of_deprecated_apis",
|
|
1126
|
+
"downstream_consumer_migration_guide_published",
|
|
1127
|
+
"telemetry_for_legacy_api_consumer_usage_tracking_with_consent",
|
|
1128
|
+
"vulnerability_disclosure_policy_published",
|
|
1129
|
+
"scheduled_eol_date_for_legacy_api_documented"
|
|
1130
|
+
]
|
|
1131
|
+
},
|
|
1132
|
+
"evidence_requirements": [
|
|
1133
|
+
{
|
|
1134
|
+
"evidence_type": "scan_report",
|
|
1135
|
+
"description": "Full source-tree grep report showing zero deterministic indicators in production paths post-remediation; ML-KEM / ML-DSA / SLH-DSA implementation call sites if PQC claim retained; FIPS-provider activation call sites if FIPS claim retained; PBKDF2 / bcrypt / scrypt / argon2id parameter inventory meeting OWASP 2023 floors.",
|
|
1136
|
+
"retention_period": "7_years",
|
|
1137
|
+
"framework_satisfied": [
|
|
1138
|
+
"nist-800-53-SC-13",
|
|
1139
|
+
"iso-27001-2022-A.8.24",
|
|
1140
|
+
"iso-27001-2022-A.8.28",
|
|
1141
|
+
"pci-dss-4-3.6",
|
|
1142
|
+
"pci-dss-4-8.3.2",
|
|
1143
|
+
"eu-cra-annex-I-1"
|
|
1144
|
+
]
|
|
1145
|
+
},
|
|
1146
|
+
{
|
|
1147
|
+
"evidence_type": "config_diff",
|
|
1148
|
+
"description": "Before/after diff of library source showing weak-primitive removal, KDF parameter raise, RNG replacement, FIPS-provider activation addition, vendored-crypto provenance addition. Tied to change-management approval reference and release notes entry.",
|
|
1149
|
+
"retention_period": "7_years",
|
|
1150
|
+
"framework_satisfied": [
|
|
1151
|
+
"iso-27001-2022-A.8.28",
|
|
1152
|
+
"iso-27001-2022-A.8.32",
|
|
1153
|
+
"soc2-cc8.1"
|
|
1154
|
+
]
|
|
1155
|
+
},
|
|
1156
|
+
{
|
|
1157
|
+
"evidence_type": "attestation",
|
|
1158
|
+
"description": "Library-author cryptographic-attribute disclosure: per-primitive algorithm choice, parameter floor, sensitivity-horizon guidance, PQC roadmap, FIPS-validation status (runtime-activated or N/A), vendored-crypto provenance map. Signed and published with the release.",
|
|
1159
|
+
"retention_period": "7_years",
|
|
1160
|
+
"framework_satisfied": [
|
|
1161
|
+
"eu-cra-annex-I-1",
|
|
1162
|
+
"eu-cra-art-13",
|
|
1163
|
+
"nis2-art21-2g",
|
|
1164
|
+
"us-cisa-sbd-attestation",
|
|
1165
|
+
"au-ism"
|
|
1166
|
+
]
|
|
1167
|
+
},
|
|
1168
|
+
{
|
|
1169
|
+
"evidence_type": "exploit_replay_negative",
|
|
1170
|
+
"description": "MD5-collision exploit-replay against the post-remediation code path showing the collision no longer produces equal-by-hash for security purposes; equivalent negative replays for SHA1-collision, PBKDF2-GPU-crack against the raised iteration floor, predictable-RNG token-prediction against the upgraded RNG.",
|
|
1171
|
+
"retention_period": "1_year",
|
|
1172
|
+
"framework_satisfied": [
|
|
1173
|
+
"soc2-cc7.1",
|
|
1174
|
+
"iso-27001-2022-A.8.28"
|
|
1175
|
+
]
|
|
1176
|
+
},
|
|
1177
|
+
{
|
|
1178
|
+
"evidence_type": "scan_report",
|
|
1179
|
+
"description": "SBOM with cryptographic-attribute disclosure (CycloneDX 1.6 crypto extension or SPDX equivalent) listing every cryptographic primitive shipped, every vendored crypto module with its upstream provenance, and the FIPS / PQC posture per primitive.",
|
|
1180
|
+
"retention_period": "7_years",
|
|
1181
|
+
"framework_satisfied": [
|
|
1182
|
+
"eu-cra-art-13",
|
|
1183
|
+
"us-cisa-sbd-attestation",
|
|
1184
|
+
"nist-800-53-SR-3"
|
|
1185
|
+
]
|
|
1186
|
+
},
|
|
1187
|
+
{
|
|
1188
|
+
"evidence_type": "ticket_reference",
|
|
1189
|
+
"description": "Downstream-consumer notification record: GitHub Security Advisory ID, npm advisory link, registry-specific advisory references, mailing list announcement, release notes entry detailing the cryptographic changes.",
|
|
1190
|
+
"retention_period": "7_years",
|
|
1191
|
+
"framework_satisfied": [
|
|
1192
|
+
"eu-cra-art-14",
|
|
1193
|
+
"iso-29147",
|
|
1194
|
+
"uk-psti-vdp"
|
|
1195
|
+
]
|
|
1196
|
+
}
|
|
1197
|
+
],
|
|
1198
|
+
"regression_trigger": [
|
|
1199
|
+
{
|
|
1200
|
+
"condition": "new_crypto_primitive_added_to_source",
|
|
1201
|
+
"interval": "on_event"
|
|
1202
|
+
},
|
|
1203
|
+
{
|
|
1204
|
+
"condition": "dependency_with_crypto_surface_updated",
|
|
1205
|
+
"interval": "on_event"
|
|
1206
|
+
},
|
|
1207
|
+
{
|
|
1208
|
+
"condition": "OWASP_KDF_minimums_updated",
|
|
1209
|
+
"interval": "on_event"
|
|
1210
|
+
},
|
|
1211
|
+
{
|
|
1212
|
+
"condition": "new_NIST_PQC_standard_published_or_amended",
|
|
1213
|
+
"interval": "on_event"
|
|
1214
|
+
},
|
|
1215
|
+
{
|
|
1216
|
+
"condition": "EU_CRA_implementing_act_published",
|
|
1217
|
+
"interval": "on_event"
|
|
1218
|
+
},
|
|
1219
|
+
{
|
|
1220
|
+
"condition": "pre_release_publish",
|
|
1221
|
+
"interval": "on_event"
|
|
1222
|
+
},
|
|
1223
|
+
{
|
|
1224
|
+
"condition": "quarterly",
|
|
1225
|
+
"interval": "90d"
|
|
1226
|
+
}
|
|
1227
|
+
]
|
|
1228
|
+
},
|
|
1229
|
+
"close": {
|
|
1230
|
+
"evidence_package": {
|
|
1231
|
+
"bundle_format": "csaf-2.0",
|
|
1232
|
+
"contents": [
|
|
1233
|
+
"scan_report",
|
|
1234
|
+
"config_diff",
|
|
1235
|
+
"attestation",
|
|
1236
|
+
"exploit_replay_negative",
|
|
1237
|
+
"framework_gap_mapping",
|
|
1238
|
+
"compliance_theater_verdict",
|
|
1239
|
+
"residual_risk_statement",
|
|
1240
|
+
"downstream_consumer_notification_record",
|
|
1241
|
+
"sbom_with_crypto_attributes"
|
|
1242
|
+
],
|
|
1243
|
+
"destination": "local_only",
|
|
1244
|
+
"signed": true
|
|
1245
|
+
},
|
|
1246
|
+
"learning_loop": {
|
|
1247
|
+
"enabled": true,
|
|
1248
|
+
"lesson_template": {
|
|
1249
|
+
"attack_vector": "Library-author crypto debt: shipped defaults (weak hash, weak cipher mode, RSA-1024, under-iterated KDF, non-cryptographic RNG in security context, missing PQC, link-time FIPS claim without runtime activation, vendored crypto without provenance) propagate to every downstream consumer regardless of consumer-side security posture. Exploitation modes include MD5/SHA1 collision against integrity checks, GPU-cracking of under-iterated KDF, token prediction against weak RNG, supply-chain attack on vendored crypto, HNDL against bare classical KEM/signature.",
|
|
1250
|
+
"control_gap": "NIST 800-53 SC-13 / ISO 27001:2022 A.8.24/A.8.28 / PCI DSS 4.0 §3.6/§8.3.2 bind the operating organization, not the library author. Library can ship weak defaults and remain framework-irrelevant. EU CRA Annex I §1 is the first direct upstream binding but not yet enforced (2026-09-11 partial bind / 2027-12-11 full).",
|
|
1251
|
+
"framework_gap": "Frameworks have no upstream library-author hook. ISO A.8.28 (secure coding) contains no PQC, KDF-iteration, RNG-source, or constant-time-implementation specifics. PCI Council and EU regulators publicly aware but binding controls not yet amended. Gap = ~365 days from operational PQC readiness (2024-08-13) to partial EU CRA bind (2026-09-11).",
|
|
1252
|
+
"new_control_requirement": "Add upstream library-author sub-controls to SC-13, A.8.24, A.8.28, §3.6, §8.3.2, Art.21(2)(g), Annex I §1 requiring: (a) banned-primitive enforcement (MD5/SHA1/DES/3DES/RC4/RSA-1024 in security context), (b) minimum KDF parameter floors aligned to OWASP-current, (c) cryptographic-RNG enforcement in security context, (d) PQC readiness disclosure with concrete primitive references not feature-flag toggles, (e) FIPS-validation-claim discipline tied to runtime activation evidence, (f) vendored-crypto provenance + integrity + constant-time evidence, (g) crypto-agility structural pluggability requirement, (h) downstream-consumer-facing cryptographic-attribute disclosure in SBOM."
|
|
1253
|
+
},
|
|
1254
|
+
"feeds_back_to_skills": [
|
|
1255
|
+
"pqc-first",
|
|
1256
|
+
"supply-chain-integrity",
|
|
1257
|
+
"exploit-scoring",
|
|
1258
|
+
"framework-gap-analysis",
|
|
1259
|
+
"compliance-theater",
|
|
1260
|
+
"global-grc",
|
|
1261
|
+
"zeroday-gap-learn"
|
|
1262
|
+
]
|
|
1263
|
+
},
|
|
1264
|
+
"notification_actions": [
|
|
1265
|
+
{
|
|
1266
|
+
"obligation_ref": "EU/EU CRA Art.14 24h",
|
|
1267
|
+
"deadline": "computed_at_runtime",
|
|
1268
|
+
"recipient": "regulator_email",
|
|
1269
|
+
"evidence_attached": [
|
|
1270
|
+
"affected_product_versions",
|
|
1271
|
+
"vulnerability_description",
|
|
1272
|
+
"mitigation_status",
|
|
1273
|
+
"downstream_consumer_notification_plan"
|
|
1274
|
+
],
|
|
1275
|
+
"draft_notification": "EU CRA Art.14 24-hour early-warning notification (where applicable): ${manufacturer_name} reports an exploited vulnerability in published product ${product_name} versions ${affected_versions}. Vulnerability class: cryptographic weakness in shipped defaults (${vulnerability_class}). Exploitation status: ${exploitation_status}. Interim mitigation: ${interim_mitigation}. Downstream-consumer notification plan: GitHub Security Advisory ID ${ghsa_id}, registry advisory ${registry_advisory_id}, release notes entry in v${remediation_version}. Coordinated disclosure window: ${disclosure_window}. Full vulnerability report to follow per Art.14(3)."
|
|
1276
|
+
},
|
|
1277
|
+
{
|
|
1278
|
+
"obligation_ref": "EU/EU CRA Art.13 720h",
|
|
1279
|
+
"deadline": "computed_at_runtime",
|
|
1280
|
+
"recipient": "internal_legal",
|
|
1281
|
+
"evidence_attached": [
|
|
1282
|
+
"product_sbom",
|
|
1283
|
+
"cryptographic_attribute_disclosure",
|
|
1284
|
+
"vulnerability_handling_policy"
|
|
1285
|
+
],
|
|
1286
|
+
"draft_notification": "EU CRA Art.13 SBOM + cryptographic-attribute disclosure publication: ${manufacturer_name} attaches SBOM for ${product_name} v${current_version} with cryptographic-attribute disclosure listing per-primitive algorithm, parameter floor, sensitivity-horizon guidance, PQC roadmap, FIPS-validation status, vendored-crypto provenance. Vulnerability-handling policy: ${vdp_url}. Re-attestation cadence: ${cadence}."
|
|
1287
|
+
},
|
|
1288
|
+
{
|
|
1289
|
+
"obligation_ref": "EU/NIS2 Art.23 24h",
|
|
1290
|
+
"deadline": "computed_at_runtime",
|
|
1291
|
+
"recipient": "internal_legal",
|
|
1292
|
+
"evidence_attached": [
|
|
1293
|
+
"essential_entity_consumer_count",
|
|
1294
|
+
"exploitation_status_assessment",
|
|
1295
|
+
"interim_mitigation_record"
|
|
1296
|
+
],
|
|
1297
|
+
"draft_notification": "NIS2 Art.23 24-hour early-warning notification (where library is depended upon by essential entities): cryptographic vulnerability detected in published library ${product_name} affecting ${essential_entity_consumer_count} essential-entity consumers. Exploitation status: ${exploitation_status}. Interim mitigation: ${interim_mitigation}. Full incident assessment to follow within 72 hours per Art.23(4)."
|
|
1298
|
+
},
|
|
1299
|
+
{
|
|
1300
|
+
"obligation_ref": "US/CISA Secure-By-Design Self-Attestation (M-23-02 / EO 14028) 8760h",
|
|
1301
|
+
"deadline": "computed_at_runtime",
|
|
1302
|
+
"recipient": "internal_legal",
|
|
1303
|
+
"evidence_attached": [
|
|
1304
|
+
"secure_by_design_attestation",
|
|
1305
|
+
"vendor_pqc_migration_inventory",
|
|
1306
|
+
"cryptographic_provenance_statement"
|
|
1307
|
+
],
|
|
1308
|
+
"draft_notification": "CISA Secure-By-Design Self-Attestation annual filing: ${manufacturer_name} attests for ${product_name} that shipped cryptographic defaults conform to FIPS 140-3 module discipline (runtime-activated where claimed), banned-primitive enforcement, OWASP-current KDF parameter floors, PQC roadmap with concrete primitive references, vendored-crypto provenance with integrity verification. PQC migration inventory: ${pqc_inventory_summary}. Cryptographic provenance statement: ${provenance_statement_url}."
|
|
1309
|
+
},
|
|
1310
|
+
{
|
|
1311
|
+
"obligation_ref": "AU/ASD ISM (vendor-shipped cryptography requirements) 8760h",
|
|
1312
|
+
"deadline": "computed_at_runtime",
|
|
1313
|
+
"recipient": "internal_legal",
|
|
1314
|
+
"evidence_attached": [
|
|
1315
|
+
"approved_cryptographic_algorithm_list",
|
|
1316
|
+
"vendor_attested_implementation_evidence"
|
|
1317
|
+
],
|
|
1318
|
+
"draft_notification": "ASD ISM vendor cryptographic-implementation disclosure: ${manufacturer_name} declares conformance for ${product_name} to the ISM approved-cryptographic-algorithm list, with per-primitive attestation: ${primitive_attestation_summary}. Exceptions: ${exceptions_summary}."
|
|
1319
|
+
},
|
|
1320
|
+
{
|
|
1321
|
+
"obligation_ref": "UK/UK PSTI Act / CAF C.5 720h",
|
|
1322
|
+
"deadline": "computed_at_runtime",
|
|
1323
|
+
"recipient": "internal_legal",
|
|
1324
|
+
"evidence_attached": [
|
|
1325
|
+
"vdp_published",
|
|
1326
|
+
"minimum_security_period_declared"
|
|
1327
|
+
],
|
|
1328
|
+
"draft_notification": "UK PSTI / CAF C.5 disclosure (where product is or is embedded in a connected product): ${manufacturer_name} publishes vulnerability-disclosure policy at ${vdp_url} and declares minimum security period of ${minimum_security_period} for ${product_name}. Cryptographic implementation disclosure: ${crypto_disclosure_summary}."
|
|
1329
|
+
}
|
|
1330
|
+
],
|
|
1331
|
+
"exception_generation": {
|
|
1332
|
+
"trigger_condition": "remediation_blocked == true OR (api_stability_promise_blocks_default_change == true AND next_major_version_window > 0) OR vendor_pqc_implementation_pending == true",
|
|
1333
|
+
"exception_template": {
|
|
1334
|
+
"scope": "Library ${product_name} retains deprecated cryptographic primitive(s) ${deprecated_primitives} under API-stability promise until next major version ${next_major_version} (planned ${planned_release_date}). Modern parallel API ${modern_api_name} is published and downstream consumers are guided to migrate via ${migration_guide_url}.",
|
|
1335
|
+
"duration": "until_next_major_version",
|
|
1336
|
+
"compensating_controls": [
|
|
1337
|
+
"runtime_deprecation_warning_on_legacy_path_invocation",
|
|
1338
|
+
"parallel_modern_api_published",
|
|
1339
|
+
"downstream_consumer_migration_guide_published",
|
|
1340
|
+
"ci_failure_for_new_internal_usage_of_deprecated_method",
|
|
1341
|
+
"telemetry_for_legacy_api_consumer_usage_tracking_with_consent",
|
|
1342
|
+
"documented_eol_date_for_legacy_api"
|
|
1343
|
+
],
|
|
1344
|
+
"risk_acceptance_owner": "ciso",
|
|
1345
|
+
"auditor_ready_language": "Pursuant to ${framework_id} ${control_id} (Cryptographic Protection / Use of Cryptography / Secure Coding / Strong Cryptography / State-of-the-Art Cryptography), ${manufacturer_name} documents a time-bound risk acceptance for the deprecated cryptographic primitive(s) ${deprecated_primitives} retained in library ${product_name} versions ${affected_versions} under API-stability promise. The deprecated primitives cannot be removed in a minor or patch release without violating semantic versioning and breaking downstream consumers in regulated industries that have not yet migrated. Modern parallel API ${modern_api_name} is published in version ${parallel_api_version} and is the documented recommendation; legacy API emits a runtime deprecation warning on invocation; internal usage of the deprecated API is failed by CI. The accepted risk class is downstream-consumer-inheritance: consumers that have not migrated to the modern API inherit the legacy cryptographic posture until they migrate or until the legacy API is removed at the next major version ${next_major_version} (planned ${planned_release_date}). The organization accepts that framework controls (NIST 800-53 SC-13, ISO 27001:2022 A.8.24/A.8.28, PCI DSS 4.0 §3.6/§8.3.2, EU CRA Annex I §1, NIS2 Art.21(2)(g)) place primary obligation on the operating organization (the consumer), but ${manufacturer_name} acknowledges its upstream supply-chain responsibility under EU CRA Annex I §1 (binding 2026-09-11 for vulnerability handling and SBOM provisions, full compliance 2027-12-11) and ISO 27001:2022 A.8.28 (secure coding) and provides the compensating controls listed. Crypto-agility roadmap: ${crypto_agility_roadmap}. Downstream-consumer notification: ${downstream_consumer_notification_record}. Cryptographic-attribute disclosure published in SBOM: ${sbom_url}. Risk accepted by ${maintainer_name} on ${acceptance_date}. Time-bound until ${duration_expiry} (planned major version release, OR ${default_12_month_expiry}, whichever is first). Re-evaluation triggers: NIST publishes PQC amendment, OWASP raises KDF parameter floor, EU CRA implementing act publishes binding 'state-of-the-art' specification, downstream-consumer migration crosses 80% adoption threshold, OR exploitation of the deprecated primitive is observed in the wild."
|
|
1346
|
+
}
|
|
1347
|
+
},
|
|
1348
|
+
"regression_schedule": {
|
|
1349
|
+
"next_run": "computed_at_runtime",
|
|
1350
|
+
"trigger": "both",
|
|
1351
|
+
"notify_on_skip": true
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
},
|
|
1355
|
+
"directives": [
|
|
1356
|
+
{
|
|
1357
|
+
"id": "weak-primitive-inventory",
|
|
1358
|
+
"title": "Full-tree weak-primitive inventory across shipped cryptographic code (catch-all)",
|
|
1359
|
+
"applies_to": {
|
|
1360
|
+
"always": true
|
|
1361
|
+
}
|
|
1362
|
+
},
|
|
1363
|
+
{
|
|
1364
|
+
"id": "pqc-readiness-gap",
|
|
1365
|
+
"title": "PQC readiness gap audit for downstream-consumer long-horizon exposure (T1573)",
|
|
1366
|
+
"applies_to": {
|
|
1367
|
+
"attack_technique": "T1573"
|
|
1368
|
+
},
|
|
1369
|
+
"phase_overrides": {
|
|
1370
|
+
"direct": {
|
|
1371
|
+
"rwep_threshold": {
|
|
1372
|
+
"escalate": 70,
|
|
1373
|
+
"monitor": 40,
|
|
1374
|
+
"close": 20
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
},
|
|
1379
|
+
{
|
|
1380
|
+
"id": "fips-validation-status",
|
|
1381
|
+
"title": "FIPS-validation-claim audit vs runtime activation reality",
|
|
1382
|
+
"applies_to": {
|
|
1383
|
+
"always": true
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
]
|
|
1387
|
+
}
|