@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/sbom.cdx.json CHANGED
@@ -1,22 +1,22 @@
1
1
  {
2
2
  "bomFormat": "CycloneDX",
3
3
  "specVersion": "1.6",
4
- "serialNumber": "urn:uuid:f88cc5a9-f82c-4dad-bad8-3f535098c1dd",
4
+ "serialNumber": "urn:uuid:3e4749be-65f9-4891-832a-68678b93ceaf",
5
5
  "version": 1,
6
6
  "metadata": {
7
- "timestamp": "2026-05-16T15:28:55.018Z",
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.39"
12
+ "version": "0.12.41"
13
13
  }
14
14
  ],
15
15
  "component": {
16
- "bom-ref": "pkg:npm/@blamejs/exceptd-skills@0.12.39",
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.39",
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.39",
28
+ "purl": "pkg:npm/%40blamejs/exceptd-skills@0.12.41",
29
29
  "hashes": [
30
30
  {
31
31
  "alg": "SHA-256",
32
- "content": "1e79d453bfbcdc5692191a505f429d55e0369d088fe9f0607e1c4c865420ee8f"
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.39"
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": "90f9f12c572b5c55a86aa67940f247751ab346e20d7b14be86b9104aa7f3b6e3"
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": "d32c31dec321b6daba763b3aa2a210dd12673410f81418de2cb3b67e6135e017"
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": "98c75aa9c1690eda7d8cb80d3e1a01c064d9c98e99998a8e332a2401972e2695"
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": "8bec99f10923681050ee07e510cc1c966137f03c880ef8f9b373cba4a4214053"
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": "cef346c414332e249a5235bb9e7cef99f81702ac27575aabb87750ba15259355"
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": "af27f2a05842b96dbb77a4887131ef3c61015193c0affdbcdd5f0548e31854c4"
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": "f4236d406c41a051b9e2b72c8a389c78fcc7148f91236c06604a00549162406b"
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": "5bfd08a3fc62850e0cdaf454a2dce3e6719acb8917b7c7249c4c02bf945b62f5"
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": "a9eeda95d24b56c28a0d0178fc601b531653e2ba7dc857160b35ad23ad6c7471"
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": "f88c5757553e3626981546ad1772189c6d40f9ddc24f730def949414cbab9cd0"
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": "0168825497e03f079274c9da2e5529310a2ba5bd7c7da7c93acd0b66ed845b8a"
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": "9c1367218daa3d54dcae0a510639521093e5a2c588c7742816e5dd075bec1ee9"
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": "c927653e6d9d86d1a36c23a3d782b099a49675ccd928cdc204887c79b0cfbbf1"
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": "ac1e0bc44b92a11799164b1388c1040a2d3f40a21294ac2c37f8ce6e11949258"
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": "8e56ee29977db9287e213b515e05c9bb76babc403a66c77a7bd353b170b473c7"
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": "fd05bb2df95d6faf755edc8fa67d61760bb26232c9ada9f5641f3849447f216b"
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": "4ecf41dee39945536de0246d16a27a5889cc1b76087b22886ad8188506c95fad"
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": "c93aaaa4253b0f836543fcec8baeff30e8624f7aef99518de8f55f6c6576e4eb"
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": "1fef6f6954bcb9f141938c3b4dc8962e92358d30a4bb71c123140d7dfcb2936c"
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": "fa542106c79317aef0571fec9a38b457ffdfe6161567c20284f43ac48dcd6d71"
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": "01830562ee30b5a7de5bceded33429b9011ef5f574c1dea71615f82420aa5f1c"
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": "de63d1a423b7dd62c64dcdc58d6e6b5a9c0c5e47bfc2bdfe4ade02cd7dbc6628"
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": "dd90c25c9729357d6c943344eaf40eb4868f15fd4483f8305c45fbc91d4eb5cf"
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": "633004eba0f8f11698927308a25672158981b5cda2c822d62f7b88cd5c94d523"
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": "a3ae7cd6a7908d4404140cb69e74ebf598aa371d9b7eb919e80704f11b33b81d"
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": "7268e2b1096db71e4104830a16859a47a993e0abbb6d3c7c4032715c046a2e11"
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": "3c5e8972b2609d1e816e78d26d0fcdb2a8d4913ef08dc76c269ed7aab1d8779e"
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": "cb6871691028f55d59e3efe47be2f1d6bf65fa8c6f3cf301e78d5d119fe3616d"
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
- // Cycle 9 finding: operator-facing docs (release notes, install instructions,
197
- // security disclosure policy, migration guides, AI-assistant ground truth)
198
- // previously auto-greened. A PR could land deceptive copy here without any
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
- // Cycle 8 JJJ: pre-fix, this class was a per-instance hunt across 25+ test
482
- // sites. Moving it to a structural lint keeps new tests / new ports from
483
- // regressing. Fix the class, not the instance (CLAUDE.md pitfall).
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 — Cycle 9 audit found this drift in production.
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 audit fix.
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 (cycle 12 F3
50
- * extension); contributes CVE-IDs (skipping `_draft: true`
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
- // Cycle 12 F3 (v0.12.32): CVE → CWE reverse direction. CWE entries
87
- // declare `evidence_cves` as the operator-facing "which CVEs land here"
88
- // index; pre-fix this was hand-maintained and drifted whenever a new
89
- // CVE landed without the matching CWE's evidence_cves being updated.
90
- // Now mirrors `cve.cwe_refs` → `cwe.evidence_cves` automatically.
91
- // Drafts excluded (they're invisible to default consumers anyway).
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
- // Cycle 12 F3 (v0.12.32): build a reverse index keyed by catalog ID from the
119
- // CVE catalog's forward refs. Each CVE entry has cwe_refs / attack_refs
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
- function buildCveReverseIndex(cveCatalog, forwardField) {
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
- const refs = Array.isArray(entry[forwardField]) ? entry[forwardField] : [];
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 v5.5 / v6.0 — track next-cadence updates to agentic-AI TTPs and MLOps-pipeline-specific techniques
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