@blamejs/exceptd-skills 0.12.39 → 0.12.41
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 +17 -0
- package/ARCHITECTURE.md +7 -4
- package/CHANGELOG.md +136 -237
- package/CONTEXT.md +2 -2
- package/README.md +2 -8
- package/agents/threat-researcher.md +2 -2
- package/bin/exceptd.js +134 -39
- package/data/_indexes/_meta.json +9 -9
- package/data/_indexes/activity-feed.json +1 -1
- package/data/_indexes/catalog-summaries.json +1 -1
- package/data/_indexes/chains.json +2794 -800
- package/data/_indexes/frequency.json +4 -0
- package/data/_indexes/section-offsets.json +20 -20
- package/data/_indexes/token-budget.json +5 -5
- package/data/cve-catalog.json +21 -28
- package/data/exploit-availability.json +1 -0
- package/data/framework-control-gaps.json +229 -193
- package/data/global-frameworks.json +1 -0
- package/data/playbooks/crypto-codebase.json +13 -0
- package/data/zeroday-lessons.json +1 -0
- package/lib/framework-gap.js +13 -3
- package/lib/lint-skills.js +1 -1
- package/lib/playbook-runner.js +8 -4
- package/lib/scoring.js +9 -1
- package/lib/sign.js +40 -7
- package/lib/verify.js +5 -5
- package/manifest-snapshot.json +1 -1
- package/manifest-snapshot.sha256 +1 -1
- package/manifest.json +45 -45
- package/orchestrator/README.md +7 -7
- package/orchestrator/index.js +32 -14
- package/orchestrator/scheduler.js +2 -2
- package/package.json +1 -1
- package/sbom.cdx.json +36 -36
- package/scripts/check-test-coverage.js +6 -6
- package/scripts/refresh-reverse-refs.js +42 -15
- package/skills/mlops-security/skill.md +1 -1
package/sbom.cdx.json
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"bomFormat": "CycloneDX",
|
|
3
3
|
"specVersion": "1.6",
|
|
4
|
-
"serialNumber": "urn:uuid:
|
|
4
|
+
"serialNumber": "urn:uuid:3e4749be-65f9-4891-832a-68678b93ceaf",
|
|
5
5
|
"version": 1,
|
|
6
6
|
"metadata": {
|
|
7
|
-
"timestamp": "2026-05-
|
|
7
|
+
"timestamp": "2026-05-17T19:49:31.500Z",
|
|
8
8
|
"tools": [
|
|
9
9
|
{
|
|
10
10
|
"vendor": "blamejs",
|
|
11
11
|
"name": "scripts/refresh-sbom.js",
|
|
12
|
-
"version": "0.12.
|
|
12
|
+
"version": "0.12.41"
|
|
13
13
|
}
|
|
14
14
|
],
|
|
15
15
|
"component": {
|
|
16
|
-
"bom-ref": "pkg:npm/@blamejs/exceptd-skills@0.12.
|
|
16
|
+
"bom-ref": "pkg:npm/@blamejs/exceptd-skills@0.12.41",
|
|
17
17
|
"type": "application",
|
|
18
18
|
"name": "@blamejs/exceptd-skills",
|
|
19
|
-
"version": "0.12.
|
|
19
|
+
"version": "0.12.41",
|
|
20
20
|
"description": "AI security skills grounded in mid-2026 threat reality, not stale framework documentation. 42 skills, 10 catalogs, 34 jurisdictions, pre-computed indexes, Ed25519-signed.",
|
|
21
21
|
"licenses": [
|
|
22
22
|
{
|
|
@@ -25,17 +25,17 @@
|
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
],
|
|
28
|
-
"purl": "pkg:npm/%40blamejs/exceptd-skills@0.12.
|
|
28
|
+
"purl": "pkg:npm/%40blamejs/exceptd-skills@0.12.41",
|
|
29
29
|
"hashes": [
|
|
30
30
|
{
|
|
31
31
|
"alg": "SHA-256",
|
|
32
|
-
"content": "
|
|
32
|
+
"content": "b573867d9a7b8eeb707c7232a25d7732c3ec0436c1928153c2b9a227f1f310ba"
|
|
33
33
|
}
|
|
34
34
|
],
|
|
35
35
|
"externalReferences": [
|
|
36
36
|
{
|
|
37
37
|
"type": "distribution",
|
|
38
|
-
"url": "https://www.npmjs.com/package/@blamejs/exceptd-skills/v/0.12.
|
|
38
|
+
"url": "https://www.npmjs.com/package/@blamejs/exceptd-skills/v/0.12.41"
|
|
39
39
|
},
|
|
40
40
|
{
|
|
41
41
|
"type": "vcs",
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"hashes": [
|
|
87
87
|
{
|
|
88
88
|
"alg": "SHA-256",
|
|
89
|
-
"content": "
|
|
89
|
+
"content": "65493e20f232b92d5a22c354f5043631f4ae4565d11a291e3868d25cab617623"
|
|
90
90
|
}
|
|
91
91
|
]
|
|
92
92
|
},
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
"hashes": [
|
|
98
98
|
{
|
|
99
99
|
"alg": "SHA-256",
|
|
100
|
-
"content": "
|
|
100
|
+
"content": "b2428492132e3405cb564ddedaba6dbf7c4bf10e7f42623fc07788eafa0bc48c"
|
|
101
101
|
}
|
|
102
102
|
]
|
|
103
103
|
},
|
|
@@ -108,7 +108,7 @@
|
|
|
108
108
|
"hashes": [
|
|
109
109
|
{
|
|
110
110
|
"alg": "SHA-256",
|
|
111
|
-
"content": "
|
|
111
|
+
"content": "62f756ac3289b26629078dfe10f13c35f09b8f564727379bc879388b0b46b40c"
|
|
112
112
|
}
|
|
113
113
|
]
|
|
114
114
|
},
|
|
@@ -119,7 +119,7 @@
|
|
|
119
119
|
"hashes": [
|
|
120
120
|
{
|
|
121
121
|
"alg": "SHA-256",
|
|
122
|
-
"content": "
|
|
122
|
+
"content": "2d1ea8c3f03420c07a8d76f5979f9b43c4a23c1fd7cb8e86688a8600d6882e67"
|
|
123
123
|
}
|
|
124
124
|
]
|
|
125
125
|
},
|
|
@@ -152,7 +152,7 @@
|
|
|
152
152
|
"hashes": [
|
|
153
153
|
{
|
|
154
154
|
"alg": "SHA-256",
|
|
155
|
-
"content": "
|
|
155
|
+
"content": "a3feda318adf801afc9243d73f5fc77c6dd88125c5b3511486703c2d23739df8"
|
|
156
156
|
}
|
|
157
157
|
]
|
|
158
158
|
},
|
|
@@ -218,7 +218,7 @@
|
|
|
218
218
|
"hashes": [
|
|
219
219
|
{
|
|
220
220
|
"alg": "SHA-256",
|
|
221
|
-
"content": "
|
|
221
|
+
"content": "3fffe9400690054eb1899e34b84e5ebbafe2cf2795fee697954aea03c12028ab"
|
|
222
222
|
}
|
|
223
223
|
]
|
|
224
224
|
},
|
|
@@ -229,7 +229,7 @@
|
|
|
229
229
|
"hashes": [
|
|
230
230
|
{
|
|
231
231
|
"alg": "SHA-256",
|
|
232
|
-
"content": "
|
|
232
|
+
"content": "5b774902c6b20817408b98fab9ef76dc178a9747f4e67dc295796d45f7df727f"
|
|
233
233
|
}
|
|
234
234
|
]
|
|
235
235
|
},
|
|
@@ -262,7 +262,7 @@
|
|
|
262
262
|
"hashes": [
|
|
263
263
|
{
|
|
264
264
|
"alg": "SHA-256",
|
|
265
|
-
"content": "
|
|
265
|
+
"content": "415384660f879d26491a612e579943092135acb676cbb95327f309c921ff69ed"
|
|
266
266
|
}
|
|
267
267
|
]
|
|
268
268
|
},
|
|
@@ -306,7 +306,7 @@
|
|
|
306
306
|
"hashes": [
|
|
307
307
|
{
|
|
308
308
|
"alg": "SHA-256",
|
|
309
|
-
"content": "
|
|
309
|
+
"content": "003a400f5ae5b15527589571679ccdb9b3a62e60073627b5fbdeb2a9fe330a7a"
|
|
310
310
|
}
|
|
311
311
|
]
|
|
312
312
|
},
|
|
@@ -317,7 +317,7 @@
|
|
|
317
317
|
"hashes": [
|
|
318
318
|
{
|
|
319
319
|
"alg": "SHA-256",
|
|
320
|
-
"content": "
|
|
320
|
+
"content": "8ad45086bce2a6991fea664f36b72794123a4aeaa02eab4322d3ac9fd03d427a"
|
|
321
321
|
}
|
|
322
322
|
]
|
|
323
323
|
},
|
|
@@ -328,7 +328,7 @@
|
|
|
328
328
|
"hashes": [
|
|
329
329
|
{
|
|
330
330
|
"alg": "SHA-256",
|
|
331
|
-
"content": "
|
|
331
|
+
"content": "9ba563a85f7f8d6c3c957de64945e20925a89d0ed6ea6fc561cf093811acf558"
|
|
332
332
|
}
|
|
333
333
|
]
|
|
334
334
|
},
|
|
@@ -383,7 +383,7 @@
|
|
|
383
383
|
"hashes": [
|
|
384
384
|
{
|
|
385
385
|
"alg": "SHA-256",
|
|
386
|
-
"content": "
|
|
386
|
+
"content": "042bf1ad0af026606ebff4b048a94ff0adcc56958600c24e121443f7004b03fe"
|
|
387
387
|
}
|
|
388
388
|
]
|
|
389
389
|
},
|
|
@@ -526,7 +526,7 @@
|
|
|
526
526
|
"hashes": [
|
|
527
527
|
{
|
|
528
528
|
"alg": "SHA-256",
|
|
529
|
-
"content": "
|
|
529
|
+
"content": "27d46a0e09a3edbe97dfbb070c3991348567cf93c86a3e94c767c5ad2dfb653e"
|
|
530
530
|
}
|
|
531
531
|
]
|
|
532
532
|
},
|
|
@@ -614,7 +614,7 @@
|
|
|
614
614
|
"hashes": [
|
|
615
615
|
{
|
|
616
616
|
"alg": "SHA-256",
|
|
617
|
-
"content": "
|
|
617
|
+
"content": "15e1c8b3cd698622418ae6a502f9d93fa60dbc3eb1c3ec36163283502a303058"
|
|
618
618
|
}
|
|
619
619
|
]
|
|
620
620
|
},
|
|
@@ -647,7 +647,7 @@
|
|
|
647
647
|
"hashes": [
|
|
648
648
|
{
|
|
649
649
|
"alg": "SHA-256",
|
|
650
|
-
"content": "
|
|
650
|
+
"content": "7baf7c4e2a42e85c8a92d6b5b4c48aba4448065765b775e1cb8d38bd43742e7f"
|
|
651
651
|
}
|
|
652
652
|
]
|
|
653
653
|
},
|
|
@@ -658,7 +658,7 @@
|
|
|
658
658
|
"hashes": [
|
|
659
659
|
{
|
|
660
660
|
"alg": "SHA-256",
|
|
661
|
-
"content": "
|
|
661
|
+
"content": "f5395b0e858ba67d5c78fe61dcb50ebbe8cff01ce38d7fdbf3cab6b30aa84afd"
|
|
662
662
|
}
|
|
663
663
|
]
|
|
664
664
|
},
|
|
@@ -746,7 +746,7 @@
|
|
|
746
746
|
"hashes": [
|
|
747
747
|
{
|
|
748
748
|
"alg": "SHA-256",
|
|
749
|
-
"content": "
|
|
749
|
+
"content": "f229e9d388e4ef6827b738cec820db3b2ddf6077317ff1bbd016f29103bbcda8"
|
|
750
750
|
}
|
|
751
751
|
]
|
|
752
752
|
},
|
|
@@ -757,7 +757,7 @@
|
|
|
757
757
|
"hashes": [
|
|
758
758
|
{
|
|
759
759
|
"alg": "SHA-256",
|
|
760
|
-
"content": "
|
|
760
|
+
"content": "ac71e496084eefcf80f4e1ed44f91d6d41b871f0cbdfbfcc119142e70acbf994"
|
|
761
761
|
}
|
|
762
762
|
]
|
|
763
763
|
},
|
|
@@ -889,7 +889,7 @@
|
|
|
889
889
|
"hashes": [
|
|
890
890
|
{
|
|
891
891
|
"alg": "SHA-256",
|
|
892
|
-
"content": "
|
|
892
|
+
"content": "020c5a64bec15476da61711d4219164ddc1957f5f6b6779eb3c5d70b90c6b98e"
|
|
893
893
|
}
|
|
894
894
|
]
|
|
895
895
|
},
|
|
@@ -911,7 +911,7 @@
|
|
|
911
911
|
"hashes": [
|
|
912
912
|
{
|
|
913
913
|
"alg": "SHA-256",
|
|
914
|
-
"content": "
|
|
914
|
+
"content": "1185d2dadcd6f08e15fb2b142c1b9c8bc106730893bbb439614510ca4bdec2af"
|
|
915
915
|
}
|
|
916
916
|
]
|
|
917
917
|
},
|
|
@@ -922,7 +922,7 @@
|
|
|
922
922
|
"hashes": [
|
|
923
923
|
{
|
|
924
924
|
"alg": "SHA-256",
|
|
925
|
-
"content": "
|
|
925
|
+
"content": "4516f97e656ca80ffb7a407a7c9218040785062e3613c2fb6211d0357cd28712"
|
|
926
926
|
}
|
|
927
927
|
]
|
|
928
928
|
},
|
|
@@ -933,7 +933,7 @@
|
|
|
933
933
|
"hashes": [
|
|
934
934
|
{
|
|
935
935
|
"alg": "SHA-256",
|
|
936
|
-
"content": "
|
|
936
|
+
"content": "5e40214440835b3fadd18b181196a56ecb6f868ec2719db2bc753ced6e3f674c"
|
|
937
937
|
}
|
|
938
938
|
]
|
|
939
939
|
},
|
|
@@ -944,7 +944,7 @@
|
|
|
944
944
|
"hashes": [
|
|
945
945
|
{
|
|
946
946
|
"alg": "SHA-256",
|
|
947
|
-
"content": "
|
|
947
|
+
"content": "772059acd0bc4355ed8db0cd65e6258d753ef38b93eb6fb03e02c8e3142a61c7"
|
|
948
948
|
}
|
|
949
949
|
]
|
|
950
950
|
},
|
|
@@ -977,7 +977,7 @@
|
|
|
977
977
|
"hashes": [
|
|
978
978
|
{
|
|
979
979
|
"alg": "SHA-256",
|
|
980
|
-
"content": "
|
|
980
|
+
"content": "8bc56bbb518d7be3fd983e939239317c49e71309f9a7aa8997cbc3331af6e356"
|
|
981
981
|
}
|
|
982
982
|
]
|
|
983
983
|
},
|
|
@@ -1010,7 +1010,7 @@
|
|
|
1010
1010
|
"hashes": [
|
|
1011
1011
|
{
|
|
1012
1012
|
"alg": "SHA-256",
|
|
1013
|
-
"content": "
|
|
1013
|
+
"content": "cef87c48a92c3709140f9171631804df04450b8383ca55147b458580d19314dc"
|
|
1014
1014
|
}
|
|
1015
1015
|
]
|
|
1016
1016
|
},
|
|
@@ -1252,7 +1252,7 @@
|
|
|
1252
1252
|
"hashes": [
|
|
1253
1253
|
{
|
|
1254
1254
|
"alg": "SHA-256",
|
|
1255
|
-
"content": "
|
|
1255
|
+
"content": "716f44a51df7c61f79e2da21015a0e93997fa493a366b39f9f83b605c2c5f8b6"
|
|
1256
1256
|
}
|
|
1257
1257
|
]
|
|
1258
1258
|
},
|
|
@@ -1296,7 +1296,7 @@
|
|
|
1296
1296
|
"hashes": [
|
|
1297
1297
|
{
|
|
1298
1298
|
"alg": "SHA-256",
|
|
1299
|
-
"content": "
|
|
1299
|
+
"content": "2552423461774bb472c69a8344a919b76b0db56b4f47c353c3d144788389521f"
|
|
1300
1300
|
}
|
|
1301
1301
|
]
|
|
1302
1302
|
},
|
|
@@ -1604,7 +1604,7 @@
|
|
|
1604
1604
|
"hashes": [
|
|
1605
1605
|
{
|
|
1606
1606
|
"alg": "SHA-256",
|
|
1607
|
-
"content": "
|
|
1607
|
+
"content": "a7bf448527e15bb0c6936217c69f3e18cc823f534e0c7f749966cde32039c63e"
|
|
1608
1608
|
}
|
|
1609
1609
|
]
|
|
1610
1610
|
},
|
|
@@ -193,9 +193,9 @@ const DOCS_ALWAYS_GREEN = new Set([
|
|
|
193
193
|
"CLAUDE.md", "SUPPORT.md", ".gitignore", ".npmrc", ".editorconfig",
|
|
194
194
|
]);
|
|
195
195
|
|
|
196
|
-
//
|
|
197
|
-
//
|
|
198
|
-
//
|
|
196
|
+
// Operator-facing docs (release notes, install instructions, security
|
|
197
|
+
// disclosure policy, migration guides, AI-assistant ground truth) must not
|
|
198
|
+
// auto-green — a PR could otherwise land deceptive copy here without any
|
|
199
199
|
// reviewer signal. Downgrade to manual-review so the diff surfaces in the
|
|
200
200
|
// gate output — a human (or the maintainer reviewing the bot summary) at
|
|
201
201
|
// least sees the change exists.
|
|
@@ -478,9 +478,9 @@ function coversCveIoc(corpus, cveId) {
|
|
|
478
478
|
// assert.notEqual(foo.status, 2, 'must not be unknown-cmd') ← also refused
|
|
479
479
|
// unless the same line ends with `// allow-notEqual: <reason>`.
|
|
480
480
|
//
|
|
481
|
-
//
|
|
482
|
-
//
|
|
483
|
-
//
|
|
481
|
+
// Structural lint replaces a per-instance hunt across 25+ test sites — keeps
|
|
482
|
+
// new tests / new ports from regressing into coincidence-passing assertions.
|
|
483
|
+
// Fix the class, not the instance.
|
|
484
484
|
function scanForCoincidenceAsserts(cwd) {
|
|
485
485
|
const out = [];
|
|
486
486
|
const testsDir = path.join(cwd, "tests");
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
* atlas-ttps, `skills_referencing` for the other three) listing every
|
|
11
11
|
* skill that points at that entry. The reverse field drifts whenever a
|
|
12
12
|
* skill adds or removes a forward ref without the catalog being updated
|
|
13
|
-
* in lockstep —
|
|
13
|
+
* in lockstep — this script rebuilds the reverse direction from the
|
|
14
|
+
* forward source of truth so the two never disagree.
|
|
14
15
|
*
|
|
15
16
|
* Behaviour. For each catalog file:
|
|
16
17
|
* 1. Walk every skill's relevant forward-ref array in manifest.json.
|
|
@@ -22,7 +23,7 @@
|
|
|
22
23
|
*
|
|
23
24
|
* The script does NOT touch playbooks_referencing — that field carries
|
|
24
25
|
* playbook ids (data/playbooks/*.json), not skill names; it has its own
|
|
25
|
-
* source of truth and is out of scope for this
|
|
26
|
+
* source of truth and is out of scope for this refresh.
|
|
26
27
|
*
|
|
27
28
|
* Run: node scripts/refresh-reverse-refs.js
|
|
28
29
|
* npm run refresh-reverse-refs
|
|
@@ -46,8 +47,8 @@ const DATA_DIR = path.join(REPO_ROOT, 'data');
|
|
|
46
47
|
* forwardField source-collection[].* array name
|
|
47
48
|
* reverseField per-entry reverse field name in the catalog
|
|
48
49
|
* source 'manifest.skills' (default) — walk every skill's forward ref
|
|
49
|
-
* 'cve.entries' — walk every CVE's forward ref (
|
|
50
|
-
*
|
|
50
|
+
* 'cve.entries' — walk every CVE's forward ref (added in
|
|
51
|
+
* v0.12.32); contributes CVE-IDs (skipping `_draft: true`
|
|
51
52
|
* entries so the reverse direction tracks operator-queryable
|
|
52
53
|
* truth, not in-progress curation state)
|
|
53
54
|
* entryKey field on the source object used as the reverse-list value
|
|
@@ -83,12 +84,12 @@ const CATALOGS = [
|
|
|
83
84
|
source: 'manifest.skills',
|
|
84
85
|
entryKey: 'name',
|
|
85
86
|
},
|
|
86
|
-
//
|
|
87
|
-
//
|
|
88
|
-
//
|
|
89
|
-
//
|
|
90
|
-
//
|
|
91
|
-
//
|
|
87
|
+
// v0.12.32: CVE → CWE reverse direction. CWE entries declare
|
|
88
|
+
// `evidence_cves` as the operator-facing "which CVEs land here" index;
|
|
89
|
+
// previously hand-maintained and drifted whenever a new CVE landed
|
|
90
|
+
// without the matching CWE's evidence_cves being updated. Now mirrors
|
|
91
|
+
// `cve.cwe_refs` → `cwe.evidence_cves` automatically. Drafts excluded
|
|
92
|
+
// (they're invisible to default consumers anyway).
|
|
92
93
|
{
|
|
93
94
|
file: 'cwe-catalog.json',
|
|
94
95
|
forwardField: 'cwe_refs',
|
|
@@ -96,6 +97,22 @@ const CATALOGS = [
|
|
|
96
97
|
source: 'cve.entries',
|
|
97
98
|
entryKey: null, // value is the iterating CVE id
|
|
98
99
|
},
|
|
100
|
+
// v0.12.40: CVE → framework-gap reverse direction. Resolved 137
|
|
101
|
+
// directional mismatches between cve.framework_control_gaps (dict-keyed
|
|
102
|
+
// by gap-id) and gap.evidence_cves (array of CVE ids). The forward
|
|
103
|
+
// shape on the CVE side is an OBJECT not an array — keys are the gap
|
|
104
|
+
// ids, values are per-CVE narrative. The reverse direction (which CVEs
|
|
105
|
+
// cite this gap) is a simple set of CVE ids on the gap entry. The
|
|
106
|
+
// helper handles the dict-keyed forward field via the
|
|
107
|
+
// `forwardFieldShape: 'object-keys'` flag.
|
|
108
|
+
{
|
|
109
|
+
file: 'framework-control-gaps.json',
|
|
110
|
+
forwardField: 'framework_control_gaps',
|
|
111
|
+
forwardFieldShape: 'object-keys', // dict; iterate keys
|
|
112
|
+
reverseField: 'evidence_cves',
|
|
113
|
+
source: 'cve.entries',
|
|
114
|
+
entryKey: null, // value is the iterating CVE id
|
|
115
|
+
},
|
|
99
116
|
];
|
|
100
117
|
|
|
101
118
|
function readJson(p) {
|
|
@@ -115,19 +132,29 @@ function buildReverseIndex(skills, forwardField) {
|
|
|
115
132
|
return index;
|
|
116
133
|
}
|
|
117
134
|
|
|
118
|
-
//
|
|
119
|
-
//
|
|
135
|
+
// v0.12.32: build a reverse index keyed by catalog ID from the CVE
|
|
136
|
+
// catalog's forward refs. Each CVE entry has cwe_refs / attack_refs
|
|
120
137
|
// arrays; the reverse side is the CVE ID, indexed by the catalog entry.
|
|
121
138
|
// Draft entries are skipped — drafts are invisible to default consumers
|
|
122
139
|
// via cross-ref-api, so the reverse direction should track operator-
|
|
123
140
|
// queryable truth, not in-progress curation state.
|
|
124
|
-
|
|
141
|
+
//
|
|
142
|
+
// v0.12.40: forwardFieldShape parameter handles the
|
|
143
|
+
// CVE.framework_control_gaps case where the forward field is a dict
|
|
144
|
+
// (gap-id → narrative) rather than an array.
|
|
145
|
+
function buildCveReverseIndex(cveCatalog, forwardField, forwardFieldShape) {
|
|
125
146
|
const index = new Map();
|
|
126
147
|
for (const [cveId, entry] of Object.entries(cveCatalog)) {
|
|
127
148
|
if (cveId === '_meta') continue;
|
|
128
149
|
if (!entry || typeof entry !== 'object') continue;
|
|
129
150
|
if (entry._draft === true) continue;
|
|
130
|
-
|
|
151
|
+
let refs;
|
|
152
|
+
if (forwardFieldShape === 'object-keys') {
|
|
153
|
+
const fv = entry[forwardField];
|
|
154
|
+
refs = (fv && typeof fv === 'object' && !Array.isArray(fv)) ? Object.keys(fv) : [];
|
|
155
|
+
} else {
|
|
156
|
+
refs = Array.isArray(entry[forwardField]) ? entry[forwardField] : [];
|
|
157
|
+
}
|
|
131
158
|
for (const targetId of refs) {
|
|
132
159
|
if (!index.has(targetId)) index.set(targetId, new Set());
|
|
133
160
|
index.get(targetId).add(cveId);
|
|
@@ -140,7 +167,7 @@ function rebuildCatalog(cfg, manifest, cveCatalog) {
|
|
|
140
167
|
const filePath = path.join(DATA_DIR, cfg.file);
|
|
141
168
|
const catalog = readJson(filePath);
|
|
142
169
|
const index = cfg.source === 'cve.entries'
|
|
143
|
-
? buildCveReverseIndex(cveCatalog, cfg.forwardField)
|
|
170
|
+
? buildCveReverseIndex(cveCatalog, cfg.forwardField, cfg.forwardFieldShape)
|
|
144
171
|
: buildReverseIndex(manifest.skills, cfg.forwardField);
|
|
145
172
|
let changed = 0;
|
|
146
173
|
let added = 0;
|
|
@@ -61,7 +61,7 @@ forward_watch:
|
|
|
61
61
|
- OpenSSF model-signing emergence to v1.0 — Sigstore-based model-weight signing; track for production adoption and admission-control integration
|
|
62
62
|
- SLSA v1.1 ML profile (draft) — model-provenance extension for training-run attestation chains; track ID and section changes
|
|
63
63
|
- EU AI Act high-risk technical-file implementing acts (2026-2027) — operational requirements for Article 10 / 13 / 15 documentation may pin ML-BOM or model-signing
|
|
64
|
-
- MITRE ATLAS v5.4.0 (released February 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: ATLAS
|
|
64
|
+
- MITRE ATLAS v5.4.0 (released February 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
|
|
65
65
|
last_threat_review: "2026-05-15"
|
|
66
66
|
---
|
|
67
67
|
|