@blamejs/exceptd-skills 0.16.22 → 0.16.24
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/ARCHITECTURE.md +2 -2
- package/CHANGELOG.md +42 -0
- package/CONTEXT.md +9 -9
- package/README.md +3 -3
- package/agents/report-generator.md +2 -2
- package/agents/skill-updater.md +1 -1
- package/agents/source-validator.md +3 -4
- package/agents/threat-researcher.md +1 -1
- package/bin/exceptd.js +91 -32
- package/data/_indexes/_meta.json +10 -10
- package/data/_indexes/activity-feed.json +12 -12
- package/data/_indexes/chains.json +70435 -4026
- package/data/_indexes/frequency.json +492 -163
- package/data/_indexes/section-offsets.json +51 -51
- package/data/_indexes/summary-cards.json +272 -106
- package/data/_indexes/token-budget.json +10 -10
- package/data/_indexes/trigger-table.json +15 -6
- package/data/_indexes/xref.json +218 -26
- package/data/cve-catalog.json +10 -10
- package/data/cwe-catalog.json +1 -0
- package/lib/auto-discovery.js +39 -1
- package/lib/collectors/ai-api.js +112 -7
- package/lib/collectors/citation-hygiene.js +27 -0
- package/lib/collectors/crypto-codebase.js +25 -0
- package/lib/collectors/kernel.js +32 -2
- package/lib/collectors/library-author.js +30 -0
- package/lib/collectors/runtime.js +38 -3
- package/lib/collectors/sbom.js +21 -2
- package/lib/collectors/scan-excludes.js +4 -1
- package/lib/collectors/secrets.js +125 -0
- package/lib/cve-cli.js +9 -1
- package/lib/cve-curation.js +8 -1
- package/lib/cve-regression-watcher.js +5 -2
- package/lib/exit-codes.js +2 -0
- package/lib/flag-suggest.js +1 -1
- package/lib/lint-skills.js +70 -0
- package/lib/playbook-runner.js +75 -14
- package/lib/prefetch.js +24 -1
- package/lib/refresh-external.js +32 -3
- package/lib/rfc-cli.js +8 -1
- package/lib/scoring.js +36 -8
- package/lib/validate-cve-catalog.js +36 -14
- package/lib/validate-package.js +8 -0
- package/lib/validate-playbooks.js +42 -0
- package/lib/verify.js +4 -3
- package/manifest-snapshot.json +4 -2
- package/manifest-snapshot.sha256 +1 -1
- package/manifest.json +57 -54
- package/orchestrator/README.md +1 -1
- package/orchestrator/index.js +65 -7
- package/orchestrator/scanner.js +53 -5
- package/package.json +1 -1
- package/sbom.cdx.json +110 -110
- package/scripts/build-indexes.js +42 -8
- package/scripts/builders/cwe-chains.js +1 -0
- package/scripts/builders/section-offsets.js +10 -2
- package/scripts/builders/token-budget.js +3 -3
- package/scripts/check-changelog-extract.js +38 -1
- package/scripts/check-sbom-currency.js +72 -0
- package/scripts/check-version-tags.js +5 -0
- package/scripts/release.js +22 -15
- package/skills/exploit-scoring/skill.md +8 -8
package/lib/verify.js
CHANGED
|
@@ -602,13 +602,14 @@ function validateAgainstSchema(value, schema, here, root) {
|
|
|
602
602
|
* and returns the first non-comment / non-empty line. Returns null if
|
|
603
603
|
* the file is unreadable / empty.
|
|
604
604
|
*
|
|
605
|
-
* Shared across
|
|
605
|
+
* Shared across five sites so every loader normalises identically:
|
|
606
606
|
* - lib/verify.js (manifest signature gate)
|
|
607
607
|
* - lib/refresh-network.js (refresh-network pre-swap gate)
|
|
608
608
|
* - scripts/verify-shipped-tarball.js (predeploy gate)
|
|
609
609
|
* - bin/exceptd.js (attestation pin)
|
|
610
|
-
*
|
|
611
|
-
*
|
|
610
|
+
* - lib/prefetch.js (cache-consume index signature pin)
|
|
611
|
+
* tests/normalize-contract.test.js asserts byte-identical output across the
|
|
612
|
+
* sites under a BOM + CRLF fuzz corpus.
|
|
612
613
|
*/
|
|
613
614
|
function loadExpectedFingerprintFirstLine(pinPath) {
|
|
614
615
|
let buf;
|
package/manifest-snapshot.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_comment": "Auto-generated by scripts/refresh-manifest-snapshot.js — do not hand-edit. Public skill surface used by check-manifest-snapshot.js to detect breaking removals.",
|
|
3
|
-
"_generated_at": "2026-06-
|
|
3
|
+
"_generated_at": "2026-06-05T18:14:35.343Z",
|
|
4
4
|
"atlas_version": "5.6.0",
|
|
5
5
|
"skill_count": 51,
|
|
6
6
|
"skills": [
|
|
@@ -155,7 +155,9 @@
|
|
|
155
155
|
"RFC-9421",
|
|
156
156
|
"RFC-9458"
|
|
157
157
|
],
|
|
158
|
-
"cwe_refs": [
|
|
158
|
+
"cwe_refs": [
|
|
159
|
+
"CWE-918"
|
|
160
|
+
],
|
|
159
161
|
"d3fend_refs": [
|
|
160
162
|
"D3-CA",
|
|
161
163
|
"D3-CSPP",
|
package/manifest-snapshot.sha256
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
507b7d47541c9a338602aee3fcedac2233ca1c0046bd41735adbf5b87cd0f50b manifest-snapshot.json
|
package/manifest.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "exceptd-security",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.24",
|
|
4
4
|
"description": "AI security skills grounded in mid-2026 threat reality, not stale framework documentation",
|
|
5
5
|
"homepage": "https://exceptd.com",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
],
|
|
54
54
|
"last_threat_review": "2026-05-15",
|
|
55
55
|
"signature": "0H+JfyUVmo/pVFEi5rLENATHjlukPVUqnOWmNPEH77wm8svKGK0aNJ46k6QU5GdHb8c9X9pVJKiuhON6AxDjDw==",
|
|
56
|
-
"signed_at": "2026-06-
|
|
56
|
+
"signed_at": "2026-06-05T21:54:10.774Z",
|
|
57
57
|
"cwe_refs": [
|
|
58
58
|
"CWE-125",
|
|
59
59
|
"CWE-362",
|
|
@@ -123,7 +123,7 @@
|
|
|
123
123
|
],
|
|
124
124
|
"last_threat_review": "2026-05-17",
|
|
125
125
|
"signature": "PHwHEsoy7ctBYOtlAfAdCDVfsq2Bpk9+qESSF+5dVkDcez2zp2v9Ihsv2vqMEs3QxMndyQ+t7NVezyt5VamSCg==",
|
|
126
|
-
"signed_at": "2026-06-
|
|
126
|
+
"signed_at": "2026-06-05T21:54:10.776Z",
|
|
127
127
|
"cwe_refs": [
|
|
128
128
|
"CWE-1039",
|
|
129
129
|
"CWE-1426",
|
|
@@ -196,7 +196,7 @@
|
|
|
196
196
|
],
|
|
197
197
|
"last_threat_review": "2026-05-17",
|
|
198
198
|
"signature": "dD4p7lcRtMyfITOncqLkpOeMy6x6gM0V7UlWHgLEdcxqODb1s75ar1cBtTqDWPbMv6ZAzVo2HJLDK1hVjjU2AQ==",
|
|
199
|
-
"signed_at": "2026-06-
|
|
199
|
+
"signed_at": "2026-06-05T21:54:10.776Z",
|
|
200
200
|
"cwe_refs": [
|
|
201
201
|
"CWE-22",
|
|
202
202
|
"CWE-345",
|
|
@@ -248,7 +248,7 @@
|
|
|
248
248
|
"framework_gaps": [],
|
|
249
249
|
"last_threat_review": "2026-05-22",
|
|
250
250
|
"signature": "wsw8Mlr/gyw6S7Iaao9BVHdU5LFPWl8WVymW17Lkq9J1Mui0+fCrTg6UbrsaeE3s7EW3TVgzBuK+8EFd1+H5AA==",
|
|
251
|
-
"signed_at": "2026-06-
|
|
251
|
+
"signed_at": "2026-06-05T21:54:10.776Z"
|
|
252
252
|
},
|
|
253
253
|
{
|
|
254
254
|
"name": "compliance-theater",
|
|
@@ -279,7 +279,7 @@
|
|
|
279
279
|
],
|
|
280
280
|
"last_threat_review": "2026-05-22",
|
|
281
281
|
"signature": "uVTc1QRKOKcIVDajBz+q2egjiEAyOQaDNsvVI2ghj5FD0VvquoUBBE5Naca2FkaZa790EHWCsVZ4hhdaSQs2DQ==",
|
|
282
|
-
"signed_at": "2026-06-
|
|
282
|
+
"signed_at": "2026-06-05T21:54:10.777Z"
|
|
283
283
|
},
|
|
284
284
|
{
|
|
285
285
|
"name": "exploit-scoring",
|
|
@@ -307,8 +307,8 @@
|
|
|
307
307
|
"CIS-Controls-v8-Control7"
|
|
308
308
|
],
|
|
309
309
|
"last_threat_review": "2026-05-18",
|
|
310
|
-
"signature": "
|
|
311
|
-
"signed_at": "2026-06-
|
|
310
|
+
"signature": "Vne6mNYAubRMzF8Fz6CrU/hbvV+UzkGbpmWQrRSGlqNTGPHgzKOhDcZ2cqgRAI9AGz4IBE79dMaQrXqsnni9AQ==",
|
|
311
|
+
"signed_at": "2026-06-05T21:54:10.778Z"
|
|
312
312
|
},
|
|
313
313
|
{
|
|
314
314
|
"name": "rag-pipeline-security",
|
|
@@ -345,7 +345,7 @@
|
|
|
345
345
|
],
|
|
346
346
|
"last_threat_review": "2026-05-22",
|
|
347
347
|
"signature": "5rw2i39SxY2WphBbDLEP28wufnbPPE9+PWt54hmaGdwHXr9RLiVt5liL/5xp14sehlVgFsfpR/bg9vy//xV0DA==",
|
|
348
|
-
"signed_at": "2026-06-
|
|
348
|
+
"signed_at": "2026-06-05T21:54:10.778Z",
|
|
349
349
|
"cwe_refs": [
|
|
350
350
|
"CWE-1395",
|
|
351
351
|
"CWE-1426"
|
|
@@ -405,7 +405,10 @@
|
|
|
405
405
|
],
|
|
406
406
|
"last_threat_review": "2026-05-17",
|
|
407
407
|
"signature": "Vqu49nzntFWjn9A/QeJzm7q/2xk/cZJ6HFQKtiNi1zgcxzXKm+MlFdkaLgYHWj5/9HJohxyIDyBJQTvcJ20eDQ==",
|
|
408
|
-
"signed_at": "2026-06-
|
|
408
|
+
"signed_at": "2026-06-05T21:54:10.778Z",
|
|
409
|
+
"cwe_refs": [
|
|
410
|
+
"CWE-918"
|
|
411
|
+
],
|
|
409
412
|
"d3fend_refs": [
|
|
410
413
|
"D3-CA",
|
|
411
414
|
"D3-CSPP",
|
|
@@ -440,7 +443,7 @@
|
|
|
440
443
|
"framework_gaps": [],
|
|
441
444
|
"last_threat_review": "2026-05-22",
|
|
442
445
|
"signature": "W87VdyVdAxAdcRI6P/8StaV+MS8ZSPKM9HOCK9n/bBO6BM3ZSE3uImVoyJVpAXQlUpUGN+A3lCJZXv64LuxwDg==",
|
|
443
|
-
"signed_at": "2026-06-
|
|
446
|
+
"signed_at": "2026-06-05T21:54:10.779Z",
|
|
444
447
|
"cwe_refs": [
|
|
445
448
|
"CWE-1188"
|
|
446
449
|
],
|
|
@@ -474,7 +477,7 @@
|
|
|
474
477
|
"framework_gaps": [],
|
|
475
478
|
"last_threat_review": "2026-05-18",
|
|
476
479
|
"signature": "wdVX+edeNekpaIldqkhvtraV6DquLvIsKAjuZVwPQYn3l1vS99HXuFxmNsD7UeMlO3qgC6Dysfsto9EnuH0RBg==",
|
|
477
|
-
"signed_at": "2026-06-
|
|
480
|
+
"signed_at": "2026-06-05T21:54:10.779Z",
|
|
478
481
|
"forward_watch": [
|
|
479
482
|
"New AI attack classes as ATLAS v6 publishes",
|
|
480
483
|
"Post-quantum adversary capability timeline",
|
|
@@ -513,7 +516,7 @@
|
|
|
513
516
|
"framework_gaps": [],
|
|
514
517
|
"last_threat_review": "2026-05-01",
|
|
515
518
|
"signature": "b5miTiY0cnxETd2btxorfZBdJKt/fLnQx20sGYUb9zEqGqtm0LMLpghkW68j4/9k48KNyuGMtNWiKTSnodUGBw==",
|
|
516
|
-
"signed_at": "2026-06-
|
|
519
|
+
"signed_at": "2026-06-05T21:54:10.779Z"
|
|
517
520
|
},
|
|
518
521
|
{
|
|
519
522
|
"name": "zeroday-gap-learn",
|
|
@@ -540,7 +543,7 @@
|
|
|
540
543
|
"framework_gaps": [],
|
|
541
544
|
"last_threat_review": "2026-05-18",
|
|
542
545
|
"signature": "xbkip0AQtWQKAu+O6r/gYECNjezS6O9k9xkkJsYbMlr+j8CdqH3p5/0l+GZmDidImRC/DL07GCnKrk9HRR/yDQ==",
|
|
543
|
-
"signed_at": "2026-06-
|
|
546
|
+
"signed_at": "2026-06-05T21:54:10.780Z",
|
|
544
547
|
"forward_watch": [
|
|
545
548
|
"New CISA KEV entries",
|
|
546
549
|
"New ATLAS TTP additions in each ATLAS release",
|
|
@@ -604,7 +607,7 @@
|
|
|
604
607
|
],
|
|
605
608
|
"last_threat_review": "2026-05-22",
|
|
606
609
|
"signature": "li2NnC1oeVIr22ComP5QbcQoh5xpWITuaKpza1s2SsUkH6kGnnt4wFfFAzaC1ORmH9x2cr8hN8kaNANG/eIMBQ==",
|
|
607
|
-
"signed_at": "2026-06-
|
|
610
|
+
"signed_at": "2026-06-05T21:54:10.780Z",
|
|
608
611
|
"cwe_refs": [
|
|
609
612
|
"CWE-327"
|
|
610
613
|
],
|
|
@@ -652,7 +655,7 @@
|
|
|
652
655
|
],
|
|
653
656
|
"last_threat_review": "2026-05-22",
|
|
654
657
|
"signature": "sZHlJ7ueHPdtzVbR+yXQ5+wKgNyjWsa1LKVg9aWTmg/Onl71DvEILMyJiLpPQjseT56Mnr1DMYJE8xOGlffBAw==",
|
|
655
|
-
"signed_at": "2026-06-
|
|
658
|
+
"signed_at": "2026-06-05T21:54:10.781Z"
|
|
656
659
|
},
|
|
657
660
|
{
|
|
658
661
|
"name": "security-maturity-tiers",
|
|
@@ -689,7 +692,7 @@
|
|
|
689
692
|
],
|
|
690
693
|
"last_threat_review": "2026-05-01",
|
|
691
694
|
"signature": "3AwFnEJu6DukPPNep/3SnuPWEuV060fJEQIwThFm7ujmdbFk0/Ii0XwGv1dkvbbK7ymMdOQpp35l4aLONAucDA==",
|
|
692
|
-
"signed_at": "2026-06-
|
|
695
|
+
"signed_at": "2026-06-05T21:54:10.781Z",
|
|
693
696
|
"cwe_refs": [
|
|
694
697
|
"CWE-1188"
|
|
695
698
|
]
|
|
@@ -724,7 +727,7 @@
|
|
|
724
727
|
"framework_gaps": [],
|
|
725
728
|
"last_threat_review": "2026-05-11",
|
|
726
729
|
"signature": "iJWevUBurLvt2v8X+Ch2eHmZkPWpKeAtIpxTIP4MwbUHyco3igDeBywJCyaR2vURYRx8LkzzIMM8DxQM4LAXBQ==",
|
|
727
|
-
"signed_at": "2026-06-
|
|
730
|
+
"signed_at": "2026-06-05T21:54:10.781Z"
|
|
728
731
|
},
|
|
729
732
|
{
|
|
730
733
|
"name": "attack-surface-pentest",
|
|
@@ -796,7 +799,7 @@
|
|
|
796
799
|
"Pwn2Own Berlin 2026 (disclosed 2026-05-14, embargo ends 2026-08-12) — Microsoft Edge 4-bug sandbox escape by Orange Tsai (DEVCORE); forward-watch only (browser sandbox, out of current playbook scope); track Microsoft Edge security advisory and KEV add"
|
|
797
800
|
],
|
|
798
801
|
"signature": "DDMzI+4En4aIkwBUCGW6nj1eEkCyLqHGn2LJ2rnwWfYatjPI1U5HrTZNAN/n9JqWtAzk8F3rmsKehaaz5iNWDA==",
|
|
799
|
-
"signed_at": "2026-06-
|
|
802
|
+
"signed_at": "2026-06-05T21:54:10.782Z"
|
|
800
803
|
},
|
|
801
804
|
{
|
|
802
805
|
"name": "fuzz-testing-strategy",
|
|
@@ -856,7 +859,7 @@
|
|
|
856
859
|
"OSS-Fuzz-Gen / AI-assisted harness generation becoming the default expectation for OSS maintainers"
|
|
857
860
|
],
|
|
858
861
|
"signature": "dJB0iAstIUbyny+udl3OIkaLScEmqS97LNP73yQ8mxt+0bcqxZjpfXaWLzLuIQblGYvUvz75/H6rO2EJuGd4AQ==",
|
|
859
|
-
"signed_at": "2026-06-
|
|
862
|
+
"signed_at": "2026-06-05T21:54:10.782Z"
|
|
860
863
|
},
|
|
861
864
|
{
|
|
862
865
|
"name": "dlp-gap-analysis",
|
|
@@ -931,7 +934,7 @@
|
|
|
931
934
|
"Quebec Law 25, India DPDPA, KSA PDPL enforcement actions naming AI-tool prompt data as in-scope personal information"
|
|
932
935
|
],
|
|
933
936
|
"signature": "KEAoMji3VcPX/ZXXqVe6OStxSkTssfY9fIRPyPcDYqh50GzOFQ6koNOTBVAiWOvjDjQ38g12xun5srbqgmvRAw==",
|
|
934
|
-
"signed_at": "2026-06-
|
|
937
|
+
"signed_at": "2026-06-05T21:54:10.782Z"
|
|
935
938
|
},
|
|
936
939
|
{
|
|
937
940
|
"name": "supply-chain-integrity",
|
|
@@ -1010,7 +1013,7 @@
|
|
|
1010
1013
|
"Pwn2Own Berlin 2026 (disclosed 2026-05-14, embargo ends 2026-08-12) — NVIDIA Megatron Bridge path traversal by haehae; AI training-stack file-system trust boundary; track patch and SBOM-attestation impact"
|
|
1011
1014
|
],
|
|
1012
1015
|
"signature": "zuW8T0EMbVV83GsUP/W20Use2gBTicBW021T0sY7qsRY/U5qsPWkXYIWp3SdiKLTIKqTEd/0T7LQebjIs2QKCA==",
|
|
1013
|
-
"signed_at": "2026-06-
|
|
1016
|
+
"signed_at": "2026-06-05T21:54:10.783Z"
|
|
1014
1017
|
},
|
|
1015
1018
|
{
|
|
1016
1019
|
"name": "defensive-countermeasure-mapping",
|
|
@@ -1067,7 +1070,7 @@
|
|
|
1067
1070
|
],
|
|
1068
1071
|
"last_threat_review": "2026-05-11",
|
|
1069
1072
|
"signature": "Qe0Hg9BrX3Zm5pj0n2z/oiHbAXWdA2Dq461zc4izkkUjEX2CZ02rODjCI2ELbrVOU3GC7edxqAxA+5U/ObnHDQ==",
|
|
1070
|
-
"signed_at": "2026-06-
|
|
1073
|
+
"signed_at": "2026-06-05T21:54:10.783Z"
|
|
1071
1074
|
},
|
|
1072
1075
|
{
|
|
1073
1076
|
"name": "identity-assurance",
|
|
@@ -1134,7 +1137,7 @@
|
|
|
1134
1137
|
"d3fend_refs": [],
|
|
1135
1138
|
"last_threat_review": "2026-05-11",
|
|
1136
1139
|
"signature": "UV3458QXSkEpenzrOmdlTTfPHUD4hNyKMDHoeZDq/kiFb4mAG0ghQGTTgI9Ru8cJbSmYM1++m9N5TFIJ6JJPBg==",
|
|
1137
|
-
"signed_at": "2026-06-
|
|
1140
|
+
"signed_at": "2026-06-05T21:54:10.783Z"
|
|
1138
1141
|
},
|
|
1139
1142
|
{
|
|
1140
1143
|
"name": "ot-ics-security",
|
|
@@ -1190,7 +1193,7 @@
|
|
|
1190
1193
|
"d3fend_refs": [],
|
|
1191
1194
|
"last_threat_review": "2026-05-11",
|
|
1192
1195
|
"signature": "kIVzsPsJ72PzzWQwTuvjoHHoVEDCday5I52M9ohjB3/Ak+zlA8oyWLO/BKb/XuYY4fOApjfxTErSWv5uHQ2zDw==",
|
|
1193
|
-
"signed_at": "2026-06-
|
|
1196
|
+
"signed_at": "2026-06-05T21:54:10.784Z"
|
|
1194
1197
|
},
|
|
1195
1198
|
{
|
|
1196
1199
|
"name": "coordinated-vuln-disclosure",
|
|
@@ -1242,7 +1245,7 @@
|
|
|
1242
1245
|
"NYDFS 23 NYCRR 500 amendments potentially adding explicit CVD program requirements"
|
|
1243
1246
|
],
|
|
1244
1247
|
"signature": "bWr27Q1uN9xCe1ib4QulszBa7YIDNkGqo72k5nm2cK98LyPblicD+sO9MnGckAyB22BTN/cIB+FwFMcI5IxvBw==",
|
|
1245
|
-
"signed_at": "2026-06-
|
|
1248
|
+
"signed_at": "2026-06-05T21:54:10.784Z"
|
|
1246
1249
|
},
|
|
1247
1250
|
{
|
|
1248
1251
|
"name": "threat-modeling-methodology",
|
|
@@ -1292,7 +1295,7 @@
|
|
|
1292
1295
|
"PASTA v2 updates incorporating AI/ML application threats"
|
|
1293
1296
|
],
|
|
1294
1297
|
"signature": "Q854yzLqXdOazc6EyQbZzgAlivuq2vGFDVUCrxSldSvx/HX/ZM/uzmJyP7aBG7ZsMHxj6Lmj/H82YQoo1e+NCQ==",
|
|
1295
|
-
"signed_at": "2026-06-
|
|
1298
|
+
"signed_at": "2026-06-05T21:54:10.784Z"
|
|
1296
1299
|
},
|
|
1297
1300
|
{
|
|
1298
1301
|
"name": "webapp-security",
|
|
@@ -1366,7 +1369,7 @@
|
|
|
1366
1369
|
"d3fend_refs": [],
|
|
1367
1370
|
"last_threat_review": "2026-05-11",
|
|
1368
1371
|
"signature": "4ccahkJpGJZtwD7EBpnGcN0sEGPMEw8eqV+tvePVS04YAkLgYVWtlkasI/8n0be9xB+77x+Sjj3kIi2j2Lf9CA==",
|
|
1369
|
-
"signed_at": "2026-06-
|
|
1372
|
+
"signed_at": "2026-06-05T21:54:10.785Z",
|
|
1370
1373
|
"forward_watch": [
|
|
1371
1374
|
"NGINX Rift CVE-2026-42945 (disclosed 2026-05-13, source depthfirst) — KEV-watch predicted CISA KEV listing by 2026-05-29; AI-assisted discovery angle; track for active-exploitation confirmation and patch advisory affecting front-door web app deployments"
|
|
1372
1375
|
]
|
|
@@ -1419,7 +1422,7 @@
|
|
|
1419
1422
|
"d3fend_refs": [],
|
|
1420
1423
|
"last_threat_review": "2026-05-15",
|
|
1421
1424
|
"signature": "SBB7c3wNYfIdkyOp4g4nW0WP7xS+YokMzg32aaeJdbf14LTGQRzQUvSqb2TCj2HFUSHESOyKT1JpkAfyHLSQBQ==",
|
|
1422
|
-
"signed_at": "2026-06-
|
|
1425
|
+
"signed_at": "2026-06-05T21:54:10.785Z"
|
|
1423
1426
|
},
|
|
1424
1427
|
{
|
|
1425
1428
|
"name": "sector-healthcare",
|
|
@@ -1479,7 +1482,7 @@
|
|
|
1479
1482
|
"d3fend_refs": [],
|
|
1480
1483
|
"last_threat_review": "2026-05-11",
|
|
1481
1484
|
"signature": "U04GNLyRas1VmfEsB8khH4iqFZPwx96sPY0Kw9iVsSPU+KTeEFqwgtWK1X1pzgb+T16Pc7HSrCaXDOpTFvQEDw==",
|
|
1482
|
-
"signed_at": "2026-06-
|
|
1485
|
+
"signed_at": "2026-06-05T21:54:10.786Z"
|
|
1483
1486
|
},
|
|
1484
1487
|
{
|
|
1485
1488
|
"name": "sector-financial",
|
|
@@ -1560,7 +1563,7 @@
|
|
|
1560
1563
|
"TIBER-EU framework v2.0 alignment with DORA TLPT RTS (JC 2024/40); cross-recognition with CBEST and iCAST"
|
|
1561
1564
|
],
|
|
1562
1565
|
"signature": "xbylLqNPBuEsFE/MNVeGy/01K6yiJXMxQbzC1F4RWU5aseDGbNy5HrAv2JWI2+Aft05ozreNPjccvu66yJ5EBw==",
|
|
1563
|
-
"signed_at": "2026-06-
|
|
1566
|
+
"signed_at": "2026-06-05T21:54:10.786Z"
|
|
1564
1567
|
},
|
|
1565
1568
|
{
|
|
1566
1569
|
"name": "sector-federal-government",
|
|
@@ -1629,7 +1632,7 @@
|
|
|
1629
1632
|
"Australia PSPF 2024 revision and ISM quarterly updates — track for Essential Eight Maturity Level requirements for federal entities"
|
|
1630
1633
|
],
|
|
1631
1634
|
"signature": "C9c3JuBhUbwcb7uZpDdy+PNT8sYmYIxzD4uRHu421ePW1aSFJ8fkMvuTzSO8vD/F/jOOg5opM4kov/xSAn+qCg==",
|
|
1632
|
-
"signed_at": "2026-06-
|
|
1635
|
+
"signed_at": "2026-06-05T21:54:10.787Z"
|
|
1633
1636
|
},
|
|
1634
1637
|
{
|
|
1635
1638
|
"name": "sector-energy",
|
|
@@ -1694,7 +1697,7 @@
|
|
|
1694
1697
|
"ICS-CERT advisory feed (https://www.cisa.gov/news-events/cybersecurity-advisories/ics-advisories) for vendor CVEs in Siemens, Rockwell, Schneider Electric, ABB, GE Vernova, Hitachi Energy, AVEVA / OSIsoft PI"
|
|
1695
1698
|
],
|
|
1696
1699
|
"signature": "oz8Q5WVaY8au4IjbaZahx/DSaC00Q44ylSL3mDkTerCEpW/EyPUeiLeGxSrWxBCwVFEKSSJvnhJjhvX5lDPcCg==",
|
|
1697
|
-
"signed_at": "2026-06-
|
|
1700
|
+
"signed_at": "2026-06-05T21:54:10.787Z"
|
|
1698
1701
|
},
|
|
1699
1702
|
{
|
|
1700
1703
|
"name": "sector-telecom",
|
|
@@ -1780,7 +1783,7 @@
|
|
|
1780
1783
|
"O-RAN SFG / WG11 security specifications"
|
|
1781
1784
|
],
|
|
1782
1785
|
"signature": "NAtyzfLPXlUuB78Snb9nWmbZalC1CNlIYN9rYhdEmtB/xQGC6vVnThgrEAHlm7v/jMCFuknvEpUHKdscUnUADw==",
|
|
1783
|
-
"signed_at": "2026-06-
|
|
1786
|
+
"signed_at": "2026-06-05T21:54:10.787Z"
|
|
1784
1787
|
},
|
|
1785
1788
|
{
|
|
1786
1789
|
"name": "api-security",
|
|
@@ -1849,7 +1852,7 @@
|
|
|
1849
1852
|
"d3fend_refs": [],
|
|
1850
1853
|
"last_threat_review": "2026-05-18",
|
|
1851
1854
|
"signature": "1UTjZNC5Lyrgw93LAizdXVeSmv3jS8YQNT1db5OKsldub50+o1FXmAH4+3MxZozaOGDCX3yXbdDJSJaaSmfuAA==",
|
|
1852
|
-
"signed_at": "2026-06-
|
|
1855
|
+
"signed_at": "2026-06-05T21:54:10.788Z",
|
|
1853
1856
|
"forward_watch": [
|
|
1854
1857
|
"NGINX Rift CVE-2026-42945 (disclosed 2026-05-13, source depthfirst) — KEV-watch predicted CISA KEV listing by 2026-05-29; track for active-exploitation confirmation and patch advisory affecting API gateway / reverse-proxy deployments",
|
|
1855
1858
|
"Pwn2Own Berlin 2026 (disclosed 2026-05-14, embargo ends 2026-08-12) — LiteLLM 3-bug SSRF + Code Injection chain by k3vg3n; LLM-proxy API surface; track upstream patch and CVE assignments",
|
|
@@ -1935,7 +1938,7 @@
|
|
|
1935
1938
|
"CISA KEV additions for cloud-control-plane CVEs (IMDSv1 abuses, federation token mishandling, cross-tenant boundary failures); CISA Cybersecurity Advisories for cross-cloud advisories"
|
|
1936
1939
|
],
|
|
1937
1940
|
"signature": "EdsY4xe7YA8X8m+KZUbq49JwoCXgRKEz2eg3m86O37rvBmpm8ppvl9hrsekygvpBh2VmCHL2dEYiOD8OM2n7CA==",
|
|
1938
|
-
"signed_at": "2026-06-
|
|
1941
|
+
"signed_at": "2026-06-05T21:54:10.788Z"
|
|
1939
1942
|
},
|
|
1940
1943
|
{
|
|
1941
1944
|
"name": "container-runtime-security",
|
|
@@ -1997,7 +2000,7 @@
|
|
|
1997
2000
|
"d3fend_refs": [],
|
|
1998
2001
|
"last_threat_review": "2026-05-15",
|
|
1999
2002
|
"signature": "fnLKPLkjjRCJ/F9wdmZ1w1lXmqEJvTYkv6Uu+9OTd5vZTWKz3QMuxKOsas+ctCdOvTaeloqPUUprXx+ZZdDpCg==",
|
|
2000
|
-
"signed_at": "2026-06-
|
|
2003
|
+
"signed_at": "2026-06-05T21:54:10.789Z",
|
|
2001
2004
|
"forward_watch": [
|
|
2002
2005
|
"Pwn2Own Berlin 2026 (disclosed 2026-05-14, embargo ends 2026-08-12) — NVIDIA Container Toolkit container escape ($50K award) by chompie / IBM X-Force XOR; high-severity container/hypervisor boundary break; track patch and KEV add post-embargo"
|
|
2003
2006
|
]
|
|
@@ -2071,7 +2074,7 @@
|
|
|
2071
2074
|
"MITRE ATLAS v5.6.0 (released May 2026) shipped the AML.T0010 sub-technique expansion this forecast tracked plus new techniques (\"Publish Poisoned AI Agent Tool\", \"Escape to Host\"); inventory now 16 tactics, 84 techniques, 56 sub-techniques. Forward watch: subsequent ATLAS minor and major releases — track next-cadence updates to agentic-AI TTPs and MLOps-pipeline-specific techniques"
|
|
2072
2075
|
],
|
|
2073
2076
|
"signature": "t3dkdpTX04zvjitEeOJThpgjurLd1UO9GOut4LXSZgY3ULhfknI4zT7G5+m2RSZZTo7yyeZrwpg+7vEg9K6mAw==",
|
|
2074
|
-
"signed_at": "2026-06-
|
|
2077
|
+
"signed_at": "2026-06-05T21:54:10.789Z"
|
|
2075
2078
|
},
|
|
2076
2079
|
{
|
|
2077
2080
|
"name": "incident-response-playbook",
|
|
@@ -2133,7 +2136,7 @@
|
|
|
2133
2136
|
"NYDFS 23 NYCRR 500.17 amendments tightening ransom-payment 24h disclosure operationalization"
|
|
2134
2137
|
],
|
|
2135
2138
|
"signature": "+1kmtA6rAvIyDjjy+cJHK6BcfylyVsa5cUjRFijlFR9GsQfB93JnmkEJOqML50pdlcxtJI3yUodHpL3/YJGtCA==",
|
|
2136
|
-
"signed_at": "2026-06-
|
|
2139
|
+
"signed_at": "2026-06-05T21:54:10.789Z"
|
|
2137
2140
|
},
|
|
2138
2141
|
{
|
|
2139
2142
|
"name": "ransomware-response",
|
|
@@ -2213,7 +2216,7 @@
|
|
|
2213
2216
|
],
|
|
2214
2217
|
"last_threat_review": "2026-05-22",
|
|
2215
2218
|
"signature": "h48ASCz63aBfHzLKxMVDADMuT4atriK0iE6bJeVzZTsx/e8+hyv4fLP7+zYxT9Oe0Gss3v/Xy+t+Wd9uwzV+Aw==",
|
|
2216
|
-
"signed_at": "2026-06-
|
|
2219
|
+
"signed_at": "2026-06-05T21:54:10.790Z"
|
|
2217
2220
|
},
|
|
2218
2221
|
{
|
|
2219
2222
|
"name": "email-security-anti-phishing",
|
|
@@ -2266,7 +2269,7 @@
|
|
|
2266
2269
|
"d3fend_refs": [],
|
|
2267
2270
|
"last_threat_review": "2026-05-18",
|
|
2268
2271
|
"signature": "FVBn4ex2qPIo9SHMVJ6tntoz4tVwjbIq3m6wDjjZyv2JODlS+90GBYCOkNamxxkmw/6de6SMs0YHQiF/xjo/DQ==",
|
|
2269
|
-
"signed_at": "2026-06-
|
|
2272
|
+
"signed_at": "2026-06-05T21:54:10.790Z"
|
|
2270
2273
|
},
|
|
2271
2274
|
{
|
|
2272
2275
|
"name": "age-gates-child-safety",
|
|
@@ -2334,7 +2337,7 @@
|
|
|
2334
2337
|
"US state adult-site age-verification laws — 19+ states by mid-2026 (TX HB 18 upheld by SCOTUS June 2025 in Free Speech Coalition v. Paxton); track ongoing challenges in remaining states"
|
|
2335
2338
|
],
|
|
2336
2339
|
"signature": "ZHVdGWCcfG98tSVB0b9mwrsYwv71V3uUEl+6ss7omSQhmNvqV5s6MAZM5YladBt9MK/8T/zBrTYN4gAonOP+BQ==",
|
|
2337
|
-
"signed_at": "2026-06-
|
|
2340
|
+
"signed_at": "2026-06-05T21:54:10.791Z"
|
|
2338
2341
|
},
|
|
2339
2342
|
{
|
|
2340
2343
|
"name": "cloud-iam-incident",
|
|
@@ -2414,7 +2417,7 @@
|
|
|
2414
2417
|
],
|
|
2415
2418
|
"last_threat_review": "2026-05-15",
|
|
2416
2419
|
"signature": "r9ii4nb3HJELdtKCGF5qy9PHOiot3GC24yfxfGAKlLENHkdRvRkvvL99eV/6RXyfUaMyrnc2Te8tPQcNu5bsDg==",
|
|
2417
|
-
"signed_at": "2026-06-
|
|
2420
|
+
"signed_at": "2026-06-05T21:54:10.791Z",
|
|
2418
2421
|
"forward_watch": [
|
|
2419
2422
|
"AWS IAM Identity Center session-policy refresh and step-up-on-admin enforcement (anticipated 2026-H2 release)",
|
|
2420
2423
|
"GCP Workload Identity Federation principal-set attribute mapping tightening (post-2026 Q3 Federation hardening guide)",
|
|
@@ -2508,7 +2511,7 @@
|
|
|
2508
2511
|
],
|
|
2509
2512
|
"last_threat_review": "2026-05-15",
|
|
2510
2513
|
"signature": "9mfDtMApMAg9V/lmwpniNxo/6gNZoOEoYDfyFvyWvKrPMtc7H9F8uz06FVoARe/J49saAKTVXOurNE1D/KtpCQ==",
|
|
2511
|
-
"signed_at": "2026-06-
|
|
2514
|
+
"signed_at": "2026-06-05T21:54:10.791Z",
|
|
2512
2515
|
"forward_watch": [
|
|
2513
2516
|
"Entra ID conditional access evolution post-Midnight Blizzard — Microsoft's 2025-2026 commitments on legacy-tenant MFA enforcement and OAuth-app consent gating",
|
|
2514
2517
|
"Okta IPSIE (Interoperability Profile for Secure Identity in the Enterprise) OpenID Foundation working-group output and adoption timeline",
|
|
@@ -2580,7 +2583,7 @@
|
|
|
2580
2583
|
"d3fend_refs": [],
|
|
2581
2584
|
"last_threat_review": "2026-06-02",
|
|
2582
2585
|
"signature": "dOFgANMtHm64uSFRjMfeA0fWZS9ISwMTt59I2CbjaF1PgTtbtb8yg/f+3pC4eXcXIET0KPGxRRmENycfIz3rAw==",
|
|
2583
|
-
"signed_at": "2026-06-
|
|
2586
|
+
"signed_at": "2026-06-05T21:54:10.792Z"
|
|
2584
2587
|
},
|
|
2585
2588
|
{
|
|
2586
2589
|
"name": "mail-server-hardening",
|
|
@@ -2639,7 +2642,7 @@
|
|
|
2639
2642
|
"d3fend_refs": [],
|
|
2640
2643
|
"last_threat_review": "2026-06-02",
|
|
2641
2644
|
"signature": "5x8RGzKo/T2IbYnFkYMZs16ThD9a5FEdrKHsnwvtMuGxdyyfZsKNIJVWw2I8O0um0UOXwwkl17Z3zhch26ymCQ==",
|
|
2642
|
-
"signed_at": "2026-06-
|
|
2645
|
+
"signed_at": "2026-06-05T21:54:10.792Z"
|
|
2643
2646
|
},
|
|
2644
2647
|
{
|
|
2645
2648
|
"name": "network-trust",
|
|
@@ -2695,7 +2698,7 @@
|
|
|
2695
2698
|
"d3fend_refs": [],
|
|
2696
2699
|
"last_threat_review": "2026-06-02",
|
|
2697
2700
|
"signature": "C/RdmnGjXKreKiGkwJfUESIxUwQzisGJ9A7KBdE9cBRBHBYHkAcScV89L+Z3kOG032Qax6LeIQai7Lr3nrQBCA==",
|
|
2698
|
-
"signed_at": "2026-06-
|
|
2701
|
+
"signed_at": "2026-06-05T21:54:10.792Z"
|
|
2699
2702
|
},
|
|
2700
2703
|
{
|
|
2701
2704
|
"name": "audit-log-integrity",
|
|
@@ -2750,7 +2753,7 @@
|
|
|
2750
2753
|
"d3fend_refs": [],
|
|
2751
2754
|
"last_threat_review": "2026-06-02",
|
|
2752
2755
|
"signature": "LvUAq+rXCA8PgNy9lTKOmFqa8T9EJg4JEH0axXvEAf9MIHqbR51ergUkFMLaTuvFuApwsPu0r1C30QgScZbiAw==",
|
|
2753
|
-
"signed_at": "2026-06-
|
|
2756
|
+
"signed_at": "2026-06-05T21:54:10.793Z"
|
|
2754
2757
|
},
|
|
2755
2758
|
{
|
|
2756
2759
|
"name": "self-update-integrity",
|
|
@@ -2804,7 +2807,7 @@
|
|
|
2804
2807
|
"d3fend_refs": [],
|
|
2805
2808
|
"last_threat_review": "2026-06-02",
|
|
2806
2809
|
"signature": "BOQZ8G9LdyG/tfpz6rCU4THz5Dq2HGJkUV7uCqSTCMrqnXH6seNXKM41FWawYo0s2VUlXtRgaO7ETp5qgxw+CQ==",
|
|
2807
|
-
"signed_at": "2026-06-
|
|
2810
|
+
"signed_at": "2026-06-05T21:54:10.793Z"
|
|
2808
2811
|
},
|
|
2809
2812
|
{
|
|
2810
2813
|
"name": "multitenancy-isolation",
|
|
@@ -2862,7 +2865,7 @@
|
|
|
2862
2865
|
"d3fend_refs": [],
|
|
2863
2866
|
"last_threat_review": "2026-06-02",
|
|
2864
2867
|
"signature": "bncN0VE4ns0lxtPe48xDR33lerw54BPVkSwX7XlrLQcMHTrV94lmjO8z4ZP4Ko61n+KpuP2SNU8v9JT0bGMmAA==",
|
|
2865
|
-
"signed_at": "2026-06-
|
|
2868
|
+
"signed_at": "2026-06-05T21:54:10.793Z"
|
|
2866
2869
|
},
|
|
2867
2870
|
{
|
|
2868
2871
|
"name": "decompression-dos",
|
|
@@ -2920,7 +2923,7 @@
|
|
|
2920
2923
|
"d3fend_refs": [],
|
|
2921
2924
|
"last_threat_review": "2026-06-02",
|
|
2922
2925
|
"signature": "03i0ZO5ScHIOjGvDKUEsws6m+20fnlJrEhSBtMU7PJzQutrPpmW9gULE0wbayTD5H9URh5nSKZuuVjvjVhZNCg==",
|
|
2923
|
-
"signed_at": "2026-06-
|
|
2926
|
+
"signed_at": "2026-06-05T21:54:10.793Z"
|
|
2924
2927
|
},
|
|
2925
2928
|
{
|
|
2926
2929
|
"name": "log-injection-telemetry",
|
|
@@ -2975,7 +2978,7 @@
|
|
|
2975
2978
|
"d3fend_refs": [],
|
|
2976
2979
|
"last_threat_review": "2026-06-02",
|
|
2977
2980
|
"signature": "twTmA2l+Am2k2PCzB2DNxDQwoYlGopJp/3QgQwBsP7h2LF+uNudisqfuOVV/bYnWfrUhuYZUWbsR3mhzbJCUBw==",
|
|
2978
|
-
"signed_at": "2026-06-
|
|
2981
|
+
"signed_at": "2026-06-05T21:54:10.794Z"
|
|
2979
2982
|
},
|
|
2980
2983
|
{
|
|
2981
2984
|
"name": "privacy-consent-ops",
|
|
@@ -3030,11 +3033,11 @@
|
|
|
3030
3033
|
"d3fend_refs": [],
|
|
3031
3034
|
"last_threat_review": "2026-06-02",
|
|
3032
3035
|
"signature": "0sfKSVrIf555c9bDGkXB96fUClN52fMAMYoQsNQ9eUUSzDiWUwdou+q0gYt43nObtj3m9Yb9X6q3oCXDVMgUDg==",
|
|
3033
|
-
"signed_at": "2026-06-
|
|
3036
|
+
"signed_at": "2026-06-05T21:54:10.794Z"
|
|
3034
3037
|
}
|
|
3035
3038
|
],
|
|
3036
3039
|
"manifest_signature": {
|
|
3037
3040
|
"algorithm": "Ed25519",
|
|
3038
|
-
"signature_base64": "
|
|
3041
|
+
"signature_base64": "mV0pAkSn14nwUzoUbvbXQqctfe42CQBEKApecPrRWWOxhyI7mjM2XhYoHDdogS6sDtQhJZgcUSZm0+rs1ITkDw=="
|
|
3039
3042
|
}
|
|
3040
3043
|
}
|
package/orchestrator/README.md
CHANGED
|
@@ -88,7 +88,7 @@ The orchestrator produces output in three formats:
|
|
|
88
88
|
| Format | Audience | File |
|
|
89
89
|
|--------|----------|------|
|
|
90
90
|
| `executive` | CISO / Board | `reports/templates/executive-summary.md` |
|
|
91
|
-
| `technical` | Security Engineers |
|
|
91
|
+
| `technical` | Security Engineers | (no canonical template — assembled by report-generator) |
|
|
92
92
|
| `compliance` | Auditors / GRC | `reports/templates/compliance-gap-report.md` |
|
|
93
93
|
| `zero-day` | Incident Response | `reports/templates/zero-day-response.md` |
|
|
94
94
|
|
package/orchestrator/index.js
CHANGED
|
@@ -195,7 +195,14 @@ Examples:
|
|
|
195
195
|
controlGaps = JSON.parse(fs.readFileSync(path.join(root, 'data', 'framework-control-gaps.json'), 'utf8'));
|
|
196
196
|
cveCatalog = JSON.parse(fs.readFileSync(path.join(root, 'data', 'cve-catalog.json'), 'utf8'));
|
|
197
197
|
} catch (err) {
|
|
198
|
-
|
|
198
|
+
// Honor --json on the catalog-read failure path too: a JSON consumer must
|
|
199
|
+
// get the same structured ok:false envelope the other error exits emit.
|
|
200
|
+
const msg = `framework-gap: cannot read catalog: ${err.message}`;
|
|
201
|
+
if (jsonOut) {
|
|
202
|
+
process.stdout.write(JSON.stringify({ ok: false, verb: 'framework-gap', error: msg }) + '\n');
|
|
203
|
+
} else {
|
|
204
|
+
console.error(`[framework-gap] cannot read catalog: ${err.message}`);
|
|
205
|
+
}
|
|
199
206
|
safeExit(EXIT_CODES.GENERIC_FAILURE);
|
|
200
207
|
return;
|
|
201
208
|
}
|
|
@@ -697,10 +704,24 @@ function _acquireWatchLock() {
|
|
|
697
704
|
e.code = 'EWATCHLOCKED';
|
|
698
705
|
throw e;
|
|
699
706
|
}
|
|
700
|
-
// Stale — reclaim atomically. unlink + re-create with O_EXCL
|
|
701
|
-
//
|
|
707
|
+
// Stale — reclaim atomically. unlink + re-create with O_EXCL. If another
|
|
708
|
+
// reclaimer won the race between our unlink and our re-create, the O_EXCL
|
|
709
|
+
// create throws EEXIST; that is contention, not a generic failure, so
|
|
710
|
+
// re-tag it as EWATCHLOCKED to map onto the EX_TEMPFAIL "retry later"
|
|
711
|
+
// exit rather than the GENERIC_FAILURE the bare EEXIST would fall to.
|
|
702
712
|
try { fsMod.unlinkSync(lockPath); } catch { /* concurrent reclaim, fine */ }
|
|
703
|
-
|
|
713
|
+
try {
|
|
714
|
+
tryCreate();
|
|
715
|
+
} catch (recreateErr) {
|
|
716
|
+
if (recreateErr.code === 'EEXIST') {
|
|
717
|
+
const e = new Error(
|
|
718
|
+
`another exceptd watch process reclaimed ${lockPath} concurrently; retry`
|
|
719
|
+
);
|
|
720
|
+
e.code = 'EWATCHLOCKED';
|
|
721
|
+
throw e;
|
|
722
|
+
}
|
|
723
|
+
throw recreateErr;
|
|
724
|
+
}
|
|
704
725
|
}
|
|
705
726
|
|
|
706
727
|
return {
|
|
@@ -755,7 +776,11 @@ async function runWatch() {
|
|
|
755
776
|
lock = _acquireWatchLock();
|
|
756
777
|
} catch (err) {
|
|
757
778
|
console.error(`[orchestrator] cannot start watch: ${err.message}`);
|
|
758
|
-
|
|
779
|
+
// sysexits EX_TEMPFAIL: the watch daemon lock is held; retry later. Read
|
|
780
|
+
// the value from the canonical exit-code table when it carries it so the
|
|
781
|
+
// `doctor --exit-codes` dump and this path share one source of truth.
|
|
782
|
+
const watchLocked = EXIT_CODES.WATCH_LOCK_CONTENTION || 75;
|
|
783
|
+
process.exitCode = err.code === 'EWATCHLOCKED' ? watchLocked : 1;
|
|
759
784
|
return;
|
|
760
785
|
}
|
|
761
786
|
|
|
@@ -1609,6 +1634,7 @@ function runWatchlistAlerts(rawArgs = []) {
|
|
|
1609
1634
|
async function validateAllCvesPreferCache(catalog, cacheDir) {
|
|
1610
1635
|
const fs = require('fs');
|
|
1611
1636
|
const path = require('path');
|
|
1637
|
+
const crypto = require('crypto');
|
|
1612
1638
|
const { validateCve } = require('../sources/validators');
|
|
1613
1639
|
|
|
1614
1640
|
// 50 MB cap on any single cache file. Refuses to read past the cap to
|
|
@@ -1618,6 +1644,34 @@ async function validateAllCvesPreferCache(catalog, cacheDir) {
|
|
|
1618
1644
|
// ~3 MB as of 2026); anything beyond 50 MB is almost certainly damage.
|
|
1619
1645
|
const CACHE_FILE_MAX_BYTES = 50 * 1024 * 1024;
|
|
1620
1646
|
|
|
1647
|
+
// Load the prefetch cache index once. Every payload written by the prefetch
|
|
1648
|
+
// pipeline records a per-entry sha256 here, so a consume-side recompute
|
|
1649
|
+
// catches a payload rewritten on disk after prefetch. The fingerprint is
|
|
1650
|
+
// computed over JSON.stringify(payload) (unindented) at write time, so the
|
|
1651
|
+
// round-trip parse + re-stringify below produces the comparable hash.
|
|
1652
|
+
let cacheIndex = null;
|
|
1653
|
+
try {
|
|
1654
|
+
cacheIndex = JSON.parse(fs.readFileSync(path.join(cacheDir, '_index.json'), 'utf8'));
|
|
1655
|
+
} catch { cacheIndex = null; }
|
|
1656
|
+
|
|
1657
|
+
// Verify a cache payload against its recorded sha256 before it is trusted.
|
|
1658
|
+
// Returns false on any tamper signal: no index, no sha256 entry, or a
|
|
1659
|
+
// mismatch. The caller then refuses the cached value and re-validates the
|
|
1660
|
+
// CVE live, so forged cache contents can no longer mask drift.
|
|
1661
|
+
function cacheEntryVerified(source, id, parsed) {
|
|
1662
|
+
const meta = cacheIndex && cacheIndex.entries && cacheIndex.entries[`${source}/${id}`];
|
|
1663
|
+
if (!meta || typeof meta.sha256 !== 'string') {
|
|
1664
|
+
console.error(`[validate-cves] cache integrity: no recorded sha256 for ${source}/${id}; ignoring cache entry and validating live.`);
|
|
1665
|
+
return false;
|
|
1666
|
+
}
|
|
1667
|
+
const actual = crypto.createHash('sha256').update(JSON.stringify(parsed)).digest('hex');
|
|
1668
|
+
if (actual !== meta.sha256) {
|
|
1669
|
+
console.error(`[validate-cves] cache integrity: sha256 mismatch for ${source}/${id} (expected ${meta.sha256.slice(0, 16)}..., got ${actual.slice(0, 16)}...); ignoring tampered cache entry and validating live.`);
|
|
1670
|
+
return false;
|
|
1671
|
+
}
|
|
1672
|
+
return true;
|
|
1673
|
+
}
|
|
1674
|
+
|
|
1621
1675
|
function readCached(source, id) {
|
|
1622
1676
|
const safe = id.replace(/[^A-Za-z0-9._-]/g, '_');
|
|
1623
1677
|
const p = path.join(cacheDir, source, `${safe}.json`);
|
|
@@ -1628,7 +1682,9 @@ async function validateAllCvesPreferCache(catalog, cacheDir) {
|
|
|
1628
1682
|
console.error(`[validate-cves] cache file ${p} exceeds ${CACHE_FILE_MAX_BYTES} byte cap (${st.size}); refusing to read.`);
|
|
1629
1683
|
return null;
|
|
1630
1684
|
}
|
|
1631
|
-
|
|
1685
|
+
const parsed = JSON.parse(fs.readFileSync(p, 'utf8'));
|
|
1686
|
+
if (!cacheEntryVerified(source, id, parsed)) return null;
|
|
1687
|
+
return parsed;
|
|
1632
1688
|
}
|
|
1633
1689
|
catch { return null; }
|
|
1634
1690
|
}
|
|
@@ -2016,7 +2072,9 @@ async function runWatchlistOrgScan(rawArgs = []) {
|
|
|
2016
2072
|
// tests and from `bin/exceptd.js`'s programmatic entrypoints.
|
|
2017
2073
|
if (require.main === module) {
|
|
2018
2074
|
main().catch(err => {
|
|
2019
|
-
|
|
2075
|
+
// Match the structured ok:false stderr contract the rest of the surface
|
|
2076
|
+
// uses so a JSON consumer gets a parseable envelope on the fatal path too.
|
|
2077
|
+
console.error(JSON.stringify({ ok: false, verb: cmd, error: String((err && err.message) || err) }));
|
|
2020
2078
|
process.exitCode = 1;
|
|
2021
2079
|
});
|
|
2022
2080
|
}
|