@blamejs/exceptd-skills 0.21.2 → 0.21.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/cve-batch.js CHANGED
@@ -7,6 +7,7 @@
7
7
  const fs = require('fs');
8
8
  const path = require('path');
9
9
  const enrich = require('./cve-enrich.js');
10
+ const gaps = require('./gap-detectors.js');
10
11
 
11
12
  // The insertion point just after the top-level "_meta" member, brace-matched
12
13
  // from its key. The catalog is 2-space-indented and new members match it.
@@ -60,6 +61,24 @@ function insertEntries(catalogText, entriesById) {
60
61
  return catalogText.slice(0, at) + insert + catalogText.slice(at);
61
62
  }
62
63
 
64
+ // Sets the top-level _meta.last_updated to `today`, adding the member when it is
65
+ // absent. Only a direct child of _meta is touched; entries carry their own
66
+ // last_updated and keep it. The activity feed dates the catalog by this field.
67
+ function stampMetaDate(catalogText, today) {
68
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(String(today))) throw new Error(`cve-batch: invalid date ${today}`);
69
+ const m = /\n {2}"_meta"\s*:\s*\{/.exec(catalogText);
70
+ if (!m) throw new Error('cve-batch: could not locate top-level "_meta" member');
71
+ const { at } = _metaEnd(catalogText);
72
+ const head = catalogText.slice(m.index, at);
73
+ const member = /(\n {4}"last_updated"\s*:\s*")[^"]*(")/;
74
+ // head begins with the _meta key, so its first brace opens _meta.
75
+ const open = head.indexOf('{') + 1;
76
+ const stamped = member.test(head)
77
+ ? head.replace(member, `$1${today}$2`)
78
+ : head.slice(0, open) + `\n "last_updated": ${JSON.stringify(today)},` + head.slice(open);
79
+ return catalogText.slice(0, m.index) + stamped + catalogText.slice(at);
80
+ }
81
+
63
82
  function recomputeAiMeta(catalogText, aiCount, total) {
64
83
  // current_rate is ROUNDED; the floor is enforced against the RAW rate, so the
65
84
  // floor is the raw rate FLOORED (rounding both leaves 0.02262 facing a 0.023
@@ -105,7 +124,9 @@ test('${cveId}: curated KEV entry is complete and self-consistent', () => {
105
124
  assert.notStrictEqual(e._auto_imported, true, 'not a draft');
106
125
  assert.strictEqual(e.cisa_kev, true);
107
126
  assert.strictEqual(typeof e.cvss_score, 'number');
108
- assert.ok(Array.isArray(e.cwe_refs) && e.cwe_refs.length > 0, 'has cwe_refs');
127
+ // NVD assigns no CWE to some records, so an empty list is valid.
128
+ assert.ok(Array.isArray(e.cwe_refs), 'has a cwe_refs array');
129
+ for (const ref of e.cwe_refs) assert.match(ref, /^CWE-\\d+$/);
109
130
  assert.ok(Array.isArray(e.attack_refs) && e.attack_refs.length > 0, 'has attack_refs');
110
131
  const sum = Object.values(e.rwep_factors).reduce((a, b) => a + b, 0);
111
132
  assert.strictEqual(sum, e.rwep_score, 'Σ rwep_factors === rwep_score');
@@ -154,6 +175,13 @@ async function curateBatch({ factsPath, judgmentsPath, apply, catalogRoot, today
154
175
  }
155
176
  }
156
177
 
178
+ // New entries and lessons may not cite the curation input; the gap-detector
179
+ // budget covers only texts already in the catalog.
180
+ for (const f of gaps.pipelineWordingFindings({ 'cve-catalog': entries, 'zeroday-lessons': lessons }, { includeDrafts: true })) {
181
+ errors.push(`${f.id}: ${f.catalog === 'cve-catalog' ? 'entry' : 'lesson'} ${f.field} cites the curation ` +
182
+ `input or a field name ("Packet: ...", "the packet names ..."); state the fact and its source instead.`);
183
+ }
184
+
157
185
  // Reported as a validation error so the DRY RUN surfaces it; insertEntries
158
186
  // throws on the same condition, but only under --apply.
159
187
  const catText = fs.readFileSync(path.join(catalogRoot, 'data', 'cve-catalog.json'), 'utf8');
@@ -171,10 +199,12 @@ async function curateBatch({ factsPath, judgmentsPath, apply, catalogRoot, today
171
199
  const ids = Object.keys(parsed).filter((k) => k !== '_meta');
172
200
  const aiCount = ids.filter((k) => parsed[k].ai_discovered === true).length;
173
201
  text = recomputeAiMeta(text, aiCount, ids.length);
202
+ text = stampMetaDate(text, today);
174
203
  fs.writeFileSync(catPath, text);
175
204
 
176
205
  const lesPath = path.join(catalogRoot, 'data', 'zeroday-lessons.json');
177
206
  const lesObj = addLessons(JSON.parse(fs.readFileSync(lesPath, 'utf8')), lessons);
207
+ lesObj._meta.last_updated = today;
178
208
  fs.writeFileSync(lesPath, JSON.stringify(lesObj, null, 2) + '\n');
179
209
 
180
210
  // The id carries its "CVE-" prefix, so lowercasing gives tests/cve-<y>-<n>.test.js.
@@ -221,4 +251,4 @@ async function cli(argv) {
221
251
  if (!r.ok) process.exitCode = 1;
222
252
  }
223
253
 
224
- module.exports = { insertEntries, recomputeAiMeta, addLessons, renderTest, curateBatch, cli };
254
+ module.exports = { insertEntries, recomputeAiMeta, stampMetaDate, addLessons, renderTest, curateBatch, cli };
package/lib/cve-enrich.js CHANGED
@@ -34,6 +34,23 @@ function extractVendorAdvisories(references, kevVendor, cveId) {
34
34
  return out;
35
35
  }
36
36
 
37
+ // A curator-supplied advisory in the { vendor, id, url, published } form takes
38
+ // the derived shape, so every record carries vendor, advisory_id, url, severity
39
+ // and published_date. Any other member is kept after those five.
40
+ function normalizeAdvisory(a) {
41
+ if (!a || typeof a !== 'object') return a;
42
+ const { id, published, ...rest } = a;
43
+ const out = {
44
+ vendor: rest.vendor,
45
+ advisory_id: rest.advisory_id ?? id ?? null,
46
+ url: rest.url,
47
+ severity: rest.severity ?? 'unknown',
48
+ published_date: rest.published_date ?? published ?? null,
49
+ };
50
+ for (const [k, v] of Object.entries(rest)) if (!(k in out)) out[k] = v;
51
+ return out;
52
+ }
53
+
37
54
  function _num(x) { const n = Number(x); return Number.isFinite(n) ? n : null; }
38
55
 
39
56
  function _ordinal(n) {
@@ -114,7 +131,7 @@ function assembleEntry(facts, judgment, today) {
114
131
  if (Array.isArray(entry[k])) entry[k] = [...new Set(entry[k])];
115
132
  if (Array.isArray(entry.vendor_advisories)) {
116
133
  const seenUrl = new Set();
117
- entry.vendor_advisories = entry.vendor_advisories.filter((a) => {
134
+ entry.vendor_advisories = entry.vendor_advisories.map(normalizeAdvisory).filter((a) => {
118
135
  const u = a && a.url;
119
136
  if (!u || seenUrl.has(u)) return !u;
120
137
  seenUrl.add(u);
@@ -25,6 +25,63 @@ function hasPlaceholderLanguage(str) {
25
25
  return false;
26
26
  }
27
27
 
28
+ // Curation-pipeline wording in shipped prose: text that cites the input bundle a
29
+ // curator worked from ("Packet: ...", "the packet names ...") or quotes a catalog
30
+ // field name as its source. Each pattern is a construction a network packet cannot
31
+ // form, so "packet data", "the packet socket (AF_PACKET)" and "Packet Storm" do not match.
32
+ const PIPELINE_WORDING = [
33
+ /(?:^|[.;:!?,]['"’”)\]]*\s+|\(\s*)(?:the )?packet:/i,
34
+ /\b(?:per(?: the)?|(?:in|from|follows) the|this|own) packet:/i,
35
+ /\bpacket:\s*(?:cisa[_ ]kev|active_exploitation|patch_available|live_patch|cwe_refs|cvss|vector|attack_vector|rwep|affected(?:_versions)?|poc_available)\b/i,
36
+ /\bPacket fields?\s*(?::|for\s+(?:CVE-|this\b))/,
37
+ /\bPacket vector\b/,
38
+ /\bpacket(?:'s)? (?:attack_vector|live_patch_notes|cisa_kev|affected_versions|poc_description|patch_available|active_exploitation_notes|vendor_update_paths|cwe_refs|rwep_\w+)\b/i,
39
+ /\b[Tt]he packet (?:records|names|registers|supplies|lists|says|states|reports|marks|confirms|describes)\b/,
40
+ /\b(?:per|according to) the packet\b/i,
41
+ // A possessive followed by a curation noun, a catalog field identifier or a
42
+ // framework key. Words a network packet can also own (path, delivery, length,
43
+ // boundary) are left out.
44
+ /\bpacket's\s+(?:own|vector|stated|attack(?:\s+(?:vector|path))?|exploitation|remediation|live[- ]?patch|livepatch|chain|fix(?:ed)?|attacker|outcome|affected|flaw(?:-remediation)?|precondition|primitive|rwep|exploit|kev|gaps?|description|cit(?:ing|ed)|confirmed|defect|cwe\b|escalation|caf|recorded|requiredaction|product|essential(?:-eight)?|framing|cvss|reachability|timeline|chained|campaign|exposure|actor|interim|named|attribution|title|targeting|coverage|end-of-life|guidance|observed|recommended|threat|public-exploit|vendor|requirement|mitigation|documented|implant|lure|post-exploitation|patch-management|references?|notes?|framework|facts|advisory|versions?(?!\s+(?:field|number|byte|bits?)\b)|summary|deadline|(?:nist-800-53|uk-caf|au-essential-8|au-ism|iso-27001|nis2|dora|eu-ai-act|cwe-)[\w.-]*|(?:active_exploitation(?:_notes)?|affected_versions|ai_discovered|ai_discovery_\w+|attack_vector|cisa_kev\w*|cvss_\w+|cwe_refs|discovery_attribution_note|epss_\w+|framework_control_gaps|known_ransomware_use|live_patch_\w+|patch_available|patch_required_reboot|poc_available|poc_description|rwep_\w+|vendor_advisories|vendor_update_paths|verification_sources))\b/i,
45
+ ];
46
+
47
+ function hasPipelineWording(str) {
48
+ if (typeof str !== "string" || str.length === 0) return false;
49
+ return PIPELINE_WORDING.some((re) => re.test(str));
50
+ }
51
+
52
+ // Every string under a value, with its dotted path.
53
+ function _strings(value, pathSoFar, out) {
54
+ if (typeof value === "string") out.push([pathSoFar, value]);
55
+ else if (Array.isArray(value)) value.forEach((v, i) => _strings(v, `${pathSoFar}[${i}]`, out));
56
+ else if (value && typeof value === "object") {
57
+ for (const k of Object.keys(value)) _strings(value[k], pathSoFar ? `${pathSoFar}.${k}` : k, out);
58
+ }
59
+ return out;
60
+ }
61
+
62
+ // One finding per curated catalog or lesson text that carries pipeline wording.
63
+ // Drafts are skipped unless opts.includeDrafts is set, as it is for a batch about
64
+ // to be written, where every submitted object is checked.
65
+ function pipelineWordingFindings(loaded, opts = {}) {
66
+ const out = [];
67
+ for (const catalog of ["cve-catalog", "zeroday-lessons"]) {
68
+ const cat = loaded[catalog];
69
+ if (!cat) continue;
70
+ for (const id of Object.keys(cat)) {
71
+ if (id === "_meta") continue;
72
+ const e = cat[id];
73
+ if (!e || (e._auto_imported === true && !opts.includeDrafts)) continue;
74
+ for (const [field, s] of _strings(e, "", [])) {
75
+ if (hasPipelineWording(s)) {
76
+ out.push({ class: "pipeline-wording", catalog, id, field,
77
+ reason: "text cites the curation input or a catalog field name instead of stating the fact and its source" });
78
+ }
79
+ }
80
+ }
81
+ }
82
+ return out;
83
+ }
84
+
28
85
  // Fields present but weak; what counts as weak is per catalog and field.
29
86
  function contentQualityFindings(loaded) {
30
87
  const out = [];
@@ -403,7 +460,8 @@ function runAllDetectors(loaded, opts = {}) {
403
460
  ...crossRefCompletenessFindings(loaded),
404
461
  ...schemaEvolutionFindings(loaded),
405
462
  ...operatorActionSlaFindings(loaded, opts),
406
- ...unusedOrphanFindings(loaded, orphanOpts)
463
+ ...unusedOrphanFindings(loaded, orphanOpts),
464
+ ...pipelineWordingFindings(loaded)
407
465
  ];
408
466
  }
409
467
 
@@ -416,11 +474,15 @@ const DETECTOR_CLASSES = [
416
474
  "cross-ref-completeness",
417
475
  "schema-evolution",
418
476
  "operator-action-sla",
419
- "unused-orphan"
477
+ "unused-orphan",
478
+ "pipeline-wording"
420
479
  ];
421
480
 
422
481
  module.exports = {
423
482
  hasPlaceholderLanguage,
483
+ hasPipelineWording,
484
+ pipelineWordingFindings,
485
+ PIPELINE_WORDING,
424
486
  daysSince,
425
487
  contentQualityFindings,
426
488
  temporalStalenessFindings,
package/manifest.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "exceptd-security",
3
- "version": "0.21.2",
3
+ "version": "0.21.4",
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",
@@ -57,7 +57,7 @@
57
57
  ],
58
58
  "last_threat_review": "2026-05-15",
59
59
  "signature": "qF31mqZPI8ZUuuVXnV05yptx+4lZe5YX6IKIybbaqHdCQ2ELUusjgRA6Hm/G2T89mpM3iCIdnKUmUkd9A6nPDw==",
60
- "signed_at": "2026-09-23T16:52:05.498Z",
60
+ "signed_at": "2026-09-27T05:23:30.369Z",
61
61
  "cwe_refs": [
62
62
  "CWE-125",
63
63
  "CWE-362",
@@ -134,7 +134,7 @@
134
134
  ],
135
135
  "last_threat_review": "2026-09-18",
136
136
  "signature": "lwK5zyS1/TyNp0/Hh2ldlto8r0Tj0P6XWs0U0pSGjbMq7ldNnnUJDe1oLCWwvTj/fcTGPLOt51ZBGlGlGugBDA==",
137
- "signed_at": "2026-09-23T16:52:05.499Z",
137
+ "signed_at": "2026-09-27T05:23:30.370Z",
138
138
  "cwe_refs": [
139
139
  "CWE-1039",
140
140
  "CWE-1426",
@@ -217,7 +217,7 @@
217
217
  ],
218
218
  "last_threat_review": "2026-09-18",
219
219
  "signature": "+zW0ui2tPBoE69HFEuTHzLJkPJD3KLpDCL1murk1N+ALuWEtx/ApgS7eZVH7BsLxVv/uHmmmfw+Uu5cNhrmQAw==",
220
- "signed_at": "2026-09-23T16:52:05.500Z",
220
+ "signed_at": "2026-09-27T05:23:30.371Z",
221
221
  "cwe_refs": [
222
222
  "CWE-22",
223
223
  "CWE-345",
@@ -271,7 +271,7 @@
271
271
  "framework_gaps": [],
272
272
  "last_threat_review": "2026-09-18",
273
273
  "signature": "zf55d/qt6fVGaqsYT1LnlcAUVcwh2qs/WBdwdAFU4pwTRp540sQoJNEo/8EPNwsCZKKwY6IOJlkMXLy/kyGRCg==",
274
- "signed_at": "2026-09-23T16:52:05.500Z"
274
+ "signed_at": "2026-09-27T05:23:30.371Z"
275
275
  },
276
276
  {
277
277
  "name": "compliance-theater",
@@ -303,7 +303,7 @@
303
303
  ],
304
304
  "last_threat_review": "2026-09-18",
305
305
  "signature": "osyCDCgT1mJoZjiodGsO/Q6ze65er7LWcMbBDcNXLPIuxpYONSnuUrKrG0kZmbVJMOdK5Jte+BOTkDbCYOsSAA==",
306
- "signed_at": "2026-09-23T16:52:05.501Z"
306
+ "signed_at": "2026-09-27T05:23:30.371Z"
307
307
  },
308
308
  {
309
309
  "name": "exploit-scoring",
@@ -334,7 +334,7 @@
334
334
  ],
335
335
  "last_threat_review": "2026-09-18",
336
336
  "signature": "p4h5ex1KPndY88cMmafXzZoz3idfI7TsdMxajjGmxPC43ZNaFnfDNfhrkQlTo42VJ+8N27ZyYNwuTCk1RtJ8Dg==",
337
- "signed_at": "2026-09-23T16:52:05.501Z"
337
+ "signed_at": "2026-09-27T05:23:30.372Z"
338
338
  },
339
339
  {
340
340
  "name": "rag-pipeline-security",
@@ -376,7 +376,7 @@
376
376
  ],
377
377
  "last_threat_review": "2026-09-18",
378
378
  "signature": "NSpytlrXh1+o4sX0EqZ746eAm3+mPfl0hgpgE5YHAMcvosOu1icbZ2aR424GrB5rASr7c/5fo+olZcBA4qx9CQ==",
379
- "signed_at": "2026-09-23T16:52:05.501Z",
379
+ "signed_at": "2026-09-27T05:23:30.372Z",
380
380
  "cwe_refs": [
381
381
  "CWE-1395",
382
382
  "CWE-1426"
@@ -443,7 +443,7 @@
443
443
  ],
444
444
  "last_threat_review": "2026-09-18",
445
445
  "signature": "/bIjyOG3vcL6sMPX0agXTVCO2Wd6/6/PBMQfjALT63ojxXMwBDz4HQTO00OSkNgvCLTOvcUM4nN4H+4yl+roCg==",
446
- "signed_at": "2026-09-23T16:52:05.502Z",
446
+ "signed_at": "2026-09-27T05:23:30.372Z",
447
447
  "cwe_refs": [
448
448
  "CWE-918"
449
449
  ],
@@ -484,7 +484,7 @@
484
484
  "framework_gaps": [],
485
485
  "last_threat_review": "2026-09-18",
486
486
  "signature": "Q40RkYhyDuzaOX02Oy/UOYEIbWMG7Jj2AIiSeUjZLrHJZcQJMsQG0YQN1/tPtzuTwip1oXf69gAe/PHuz7/uBQ==",
487
- "signed_at": "2026-09-23T16:52:05.502Z",
487
+ "signed_at": "2026-09-27T05:23:30.373Z",
488
488
  "cwe_refs": [
489
489
  "CWE-1188"
490
490
  ],
@@ -519,7 +519,7 @@
519
519
  "framework_gaps": [],
520
520
  "last_threat_review": "2026-09-18",
521
521
  "signature": "ip/6xTNuHUcdPjPQW8TFLWatHGffymsi0xHgb/Hv/umC3GpQciVWUIp0pUJ2dlnuBnmd72IjDSvpVrQZjSzPCQ==",
522
- "signed_at": "2026-09-23T16:52:05.503Z",
522
+ "signed_at": "2026-09-27T05:23:30.373Z",
523
523
  "forward_watch": [
524
524
  "New AI attack classes as ATLAS v6 publishes",
525
525
  "Post-quantum adversary capability timeline",
@@ -560,7 +560,7 @@
560
560
  "framework_gaps": [],
561
561
  "last_threat_review": "2026-09-09",
562
562
  "signature": "u/3QUr3Nh0q1tjOaHQ3yC4WIJOUoABr+6R8VStCgS4NvNBglb/JcbLYvQmFixqdURu4Qi6xtqvUw0E14b5mtDA==",
563
- "signed_at": "2026-09-23T16:52:05.503Z",
563
+ "signed_at": "2026-09-27T05:23:30.374Z",
564
564
  "d3fend_refs": [
565
565
  "D3-EAL",
566
566
  "D3-EFA",
@@ -602,7 +602,7 @@
602
602
  "framework_gaps": [],
603
603
  "last_threat_review": "2026-09-18",
604
604
  "signature": "5+DC+gAxjBkgM8OjirB3yDpcSOWSiii2zuEH1ue3VDdlvfvVrLF8ysRHUHg0AYC4Y9lByy5xJb1UWz1xnRqmAw==",
605
- "signed_at": "2026-09-23T16:52:05.503Z",
605
+ "signed_at": "2026-09-27T05:23:30.374Z",
606
606
  "forward_watch": [
607
607
  "New CISA KEV entries",
608
608
  "New ATLAS TTP additions in each ATLAS release",
@@ -671,7 +671,7 @@
671
671
  ],
672
672
  "last_threat_review": "2026-08-05",
673
673
  "signature": "r8tW6PJ8G0Sjd9nyr6rWJ11dovdH9llEe6eAldHedUKRl+vdbQd4g5Cefs2Q/xcNzoXGh3C0usNLX8jX4EaWBQ==",
674
- "signed_at": "2026-09-23T16:52:05.504Z",
674
+ "signed_at": "2026-09-27T05:23:30.375Z",
675
675
  "cwe_refs": [
676
676
  "CWE-327"
677
677
  ],
@@ -721,7 +721,7 @@
721
721
  ],
722
722
  "last_threat_review": "2026-09-18",
723
723
  "signature": "R9cbLm2pz1MupiQpWk3CtrnlZ06VQQ5gN5MWlMEbF+aFTHdK7JsSXoyLodZYDo1U+ROQ+4OH2VXo0Z+54k/KBw==",
724
- "signed_at": "2026-09-23T16:52:05.504Z"
724
+ "signed_at": "2026-09-27T05:23:30.376Z"
725
725
  },
726
726
  {
727
727
  "name": "security-maturity-tiers",
@@ -761,7 +761,7 @@
761
761
  ],
762
762
  "last_threat_review": "2026-09-18",
763
763
  "signature": "n9Emv3t+W3lhOPkrLI06Grwx9lDVdHVYT6KMXcLHGnJiTLiSrz23XWIdpJQNMjj7Prp6TFaDScZ6x6WkZuxHDA==",
764
- "signed_at": "2026-09-23T16:52:05.505Z",
764
+ "signed_at": "2026-09-27T05:23:30.376Z",
765
765
  "cwe_refs": [
766
766
  "CWE-1188"
767
767
  ],
@@ -815,7 +815,7 @@
815
815
  "framework_gaps": [],
816
816
  "last_threat_review": "2026-09-09",
817
817
  "signature": "Lb71p2XDRGmSUe4LGxiMl5HgJQ6gOVvWhjZ24dz8eBt7q+9qb0dLMMXshsfmreTjRU4ArNv50QPLZFFh9l+HCw==",
818
- "signed_at": "2026-09-23T16:52:05.505Z"
818
+ "signed_at": "2026-09-27T05:23:30.377Z"
819
819
  },
820
820
  {
821
821
  "name": "attack-surface-pentest",
@@ -891,7 +891,7 @@
891
891
  "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"
892
892
  ],
893
893
  "signature": "tBzI4lHl8F2+MeDZIOak1IYUBy8rrbgbc7M5uvodJXBKs+Rj9BmC0quk3NEcNRma8eIawUyyjU5ieFMi5MpiBQ==",
894
- "signed_at": "2026-09-23T16:52:05.505Z"
894
+ "signed_at": "2026-09-27T05:23:30.377Z"
895
895
  },
896
896
  {
897
897
  "name": "fuzz-testing-strategy",
@@ -952,7 +952,7 @@
952
952
  "OSS-Fuzz-Gen / AI-assisted harness generation becoming the default expectation for OSS maintainers"
953
953
  ],
954
954
  "signature": "1rpQIBRamlNF6gFGwycmgGLcmNalYeAZjkRKdQ0NWQW1lXQegE4sTObgDFkKCLuLSB+6j3zjzinwSQyxwxL9Dw==",
955
- "signed_at": "2026-09-23T16:52:05.506Z"
955
+ "signed_at": "2026-09-27T05:23:30.377Z"
956
956
  },
957
957
  {
958
958
  "name": "dlp-gap-analysis",
@@ -1030,7 +1030,7 @@
1030
1030
  "Quebec Law 25, India DPDPA, KSA PDPL enforcement actions naming AI-tool prompt data as in-scope personal information"
1031
1031
  ],
1032
1032
  "signature": "wKN08ODL/5Z1Kr1ySnDqj/eWY013y13LRqupqEERjMLjKMxuFiC6cLUaPjUyachML0PZAZrWYlCdfrggbNxkDg==",
1033
- "signed_at": "2026-09-23T16:52:05.506Z"
1033
+ "signed_at": "2026-09-27T05:23:30.378Z"
1034
1034
  },
1035
1035
  {
1036
1036
  "name": "supply-chain-integrity",
@@ -1114,7 +1114,7 @@
1114
1114
  "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"
1115
1115
  ],
1116
1116
  "signature": "fZ7VVjKFgQsgNNQd6m71lLY+POS/85jSZopbDwC96M+SfqSCQGW+6F9CqOhjE9vwkxoKhaKRULTfhpdbcsHhBg==",
1117
- "signed_at": "2026-09-23T16:52:05.506Z"
1117
+ "signed_at": "2026-09-27T05:23:30.378Z"
1118
1118
  },
1119
1119
  {
1120
1120
  "name": "defensive-countermeasure-mapping",
@@ -1171,7 +1171,7 @@
1171
1171
  ],
1172
1172
  "last_threat_review": "2026-06-10",
1173
1173
  "signature": "W8kg2Okd/VF521VmeVFGK2TmXkFPycuwgYdyNxLU2fMN+sR9Aals/X+Xqr/prrGEsqWnZsCInSq1TYzFr0wiDg==",
1174
- "signed_at": "2026-09-23T16:52:05.507Z"
1174
+ "signed_at": "2026-09-27T05:23:30.378Z"
1175
1175
  },
1176
1176
  {
1177
1177
  "name": "identity-assurance",
@@ -1245,7 +1245,7 @@
1245
1245
  ],
1246
1246
  "last_threat_review": "2026-05-11",
1247
1247
  "signature": "UV3458QXSkEpenzrOmdlTTfPHUD4hNyKMDHoeZDq/kiFb4mAG0ghQGTTgI9Ru8cJbSmYM1++m9N5TFIJ6JJPBg==",
1248
- "signed_at": "2026-09-23T16:52:05.507Z"
1248
+ "signed_at": "2026-09-27T05:23:30.378Z"
1249
1249
  },
1250
1250
  {
1251
1251
  "name": "ot-ics-security",
@@ -1304,7 +1304,7 @@
1304
1304
  "d3fend_refs": [],
1305
1305
  "last_threat_review": "2026-09-18",
1306
1306
  "signature": "2pmqMIfqL1VAK5ZzPY4l1wllI7tnl5ne7ML6u9qQnA3SScRR1++TPUjEaB3iLZeRanCKGgkMj8LmU96dbqYYDA==",
1307
- "signed_at": "2026-09-23T16:52:05.507Z"
1307
+ "signed_at": "2026-09-27T05:23:30.379Z"
1308
1308
  },
1309
1309
  {
1310
1310
  "name": "coordinated-vuln-disclosure",
@@ -1364,7 +1364,7 @@
1364
1364
  "NYDFS 23 NYCRR 500 amendments potentially adding explicit CVD program requirements"
1365
1365
  ],
1366
1366
  "signature": "FfzagIXtJNegSNPjLSI11fnQqxXJ4nSfPcv+IdbD3XmIfDTxnV7nTAR0tCQKqOGKpsyYEwAZP5jQzA3tIuJJBw==",
1367
- "signed_at": "2026-09-23T16:52:05.508Z"
1367
+ "signed_at": "2026-09-27T05:23:30.379Z"
1368
1368
  },
1369
1369
  {
1370
1370
  "name": "threat-modeling-methodology",
@@ -1418,7 +1418,7 @@
1418
1418
  "PASTA v2 updates incorporating AI/ML application threats"
1419
1419
  ],
1420
1420
  "signature": "0njaUBtRgD+5ys5xh1x+daPI2xhnHzZP+pielUdqEndR2/uDAuf3XIDUWnhC8LKr+33HSX3pXmqfgbXJpyqxBQ==",
1421
- "signed_at": "2026-09-23T16:52:05.508Z"
1421
+ "signed_at": "2026-09-27T05:23:30.379Z"
1422
1422
  },
1423
1423
  {
1424
1424
  "name": "webapp-security",
@@ -1501,7 +1501,7 @@
1501
1501
  ],
1502
1502
  "last_threat_review": "2026-09-18",
1503
1503
  "signature": "YhdXy2fMZubdoGemwvt8XCPFaMpcA3uVzGlGH7j+3koPuPl99VqkD1Q2gsJjs894V3CiRSWuRU75q4nIGwUAAQ==",
1504
- "signed_at": "2026-09-23T16:52:05.508Z",
1504
+ "signed_at": "2026-09-27T05:23:30.380Z",
1505
1505
  "forward_watch": [
1506
1506
  "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"
1507
1507
  ]
@@ -1562,7 +1562,7 @@
1562
1562
  ],
1563
1563
  "last_threat_review": "2026-05-15",
1564
1564
  "signature": "+x25rPi9K6Yo39Nj9ZN+PV4y0yQ9z9mNmOrBISYLsWrjqVTACCUFI+mp4w/nV6sZueEMoiar+inwE/fucbuiDw==",
1565
- "signed_at": "2026-09-23T16:52:05.508Z"
1565
+ "signed_at": "2026-09-27T05:23:30.380Z"
1566
1566
  },
1567
1567
  {
1568
1568
  "name": "sector-healthcare",
@@ -1630,7 +1630,7 @@
1630
1630
  ],
1631
1631
  "last_threat_review": "2026-09-18",
1632
1632
  "signature": "XMI/ZJn07vHRmN+zRCbYh+JH0bUaRL0KpthMVfRXGz3ELqQqeLG7eUrrnBWnJ5GhsWTuYY/dGCyDdsVyBKtNDA==",
1633
- "signed_at": "2026-09-23T16:52:05.509Z"
1633
+ "signed_at": "2026-09-27T05:23:30.380Z"
1634
1634
  },
1635
1635
  {
1636
1636
  "name": "sector-financial",
@@ -1719,7 +1719,7 @@
1719
1719
  "TIBER-EU framework v2.0 alignment with DORA TLPT RTS (JC 2024/40); cross-recognition with CBEST and iCAST"
1720
1720
  ],
1721
1721
  "signature": "gFUmQCkAfdW++Mb+UcwHTATJcZuszFA3dQSD+v3asEdYYsSFt63L03p09Y3JWN0c4JS4jAC1x08WsgYSklSCBQ==",
1722
- "signed_at": "2026-09-23T16:52:05.509Z"
1722
+ "signed_at": "2026-09-27T05:23:30.381Z"
1723
1723
  },
1724
1724
  {
1725
1725
  "name": "sector-federal-government",
@@ -1796,7 +1796,7 @@
1796
1796
  "Australia PSPF 2024 revision and ISM quarterly updates — track for Essential Eight Maturity Level requirements for federal entities"
1797
1797
  ],
1798
1798
  "signature": "eFY8sPJCCqYTLGKx+1Spc8UhXNF5Lg3PxN11++lGHBEtPJf/HWeLtrrw2CZSabeqZxdrSLEjuiJxkFo9r+VkAg==",
1799
- "signed_at": "2026-09-23T16:52:05.510Z"
1799
+ "signed_at": "2026-09-27T05:23:30.381Z"
1800
1800
  },
1801
1801
  {
1802
1802
  "name": "sector-energy",
@@ -1870,7 +1870,7 @@
1870
1870
  "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"
1871
1871
  ],
1872
1872
  "signature": "tpbR4Azrmbh9YSByEBqsb40/c6e17bKw6RDYzdW1P1gK31g+It5wOCgVvoacCv4F5SjQWIQnlrm1QWTMYYJWAA==",
1873
- "signed_at": "2026-09-23T16:52:05.510Z"
1873
+ "signed_at": "2026-09-27T05:23:30.381Z"
1874
1874
  },
1875
1875
  {
1876
1876
  "name": "sector-telecom",
@@ -1956,7 +1956,7 @@
1956
1956
  "O-RAN SFG / WG11 security specifications"
1957
1957
  ],
1958
1958
  "signature": "G7WrqBaR/Nqf4zhYdS69gBsunZJolx0saEAAd6Y+3ev8iN7mDiB5H0W+ow+YZjD74hhsJr4ks3RD/yKulavXCQ==",
1959
- "signed_at": "2026-09-23T16:52:05.510Z"
1959
+ "signed_at": "2026-09-27T05:23:30.382Z"
1960
1960
  },
1961
1961
  {
1962
1962
  "name": "api-security",
@@ -2035,7 +2035,7 @@
2035
2035
  ],
2036
2036
  "last_threat_review": "2026-09-18",
2037
2037
  "signature": "y6LfKfsHtpPT+UBrfkXVR4xO139xvzrWOGTdyeEAna1kecWDJIqKKMdSpHqR4T7KG2HCAmgLCV2cmf3B3jnkAg==",
2038
- "signed_at": "2026-09-23T16:52:05.511Z",
2038
+ "signed_at": "2026-09-27T05:23:30.382Z",
2039
2039
  "forward_watch": [
2040
2040
  "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",
2041
2041
  "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",
@@ -2131,7 +2131,7 @@
2131
2131
  "CISA KEV additions for cloud-control-plane CVEs (IMDSv1 abuses, federation token mishandling, cross-tenant boundary failures); CISA Cybersecurity Advisories for cross-cloud advisories"
2132
2132
  ],
2133
2133
  "signature": "f7b0+D4TJwd9c9ISGMFquvePueywoO92QZ172etyayBcDwYVTIiGYII67+NyaLl2+u0QG49d4QY41UPbRflrDw==",
2134
- "signed_at": "2026-09-23T16:52:05.511Z"
2134
+ "signed_at": "2026-09-27T05:23:30.383Z"
2135
2135
  },
2136
2136
  {
2137
2137
  "name": "container-runtime-security",
@@ -2203,7 +2203,7 @@
2203
2203
  ],
2204
2204
  "last_threat_review": "2026-09-18",
2205
2205
  "signature": "mN0q+CDc2WyUjgOzFwUBZBo3SbaOAvWn4CVBjLAYfWYDxm5em+vil0a5dlUWLXxviDNkeQpG0kaAv9dstqPWDg==",
2206
- "signed_at": "2026-09-23T16:52:05.512Z",
2206
+ "signed_at": "2026-09-27T05:23:30.383Z",
2207
2207
  "forward_watch": [
2208
2208
  "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"
2209
2209
  ]
@@ -2284,7 +2284,7 @@
2284
2284
  "MITRE ATLAS release 2026.06 (June 2026) added AML.T0113 (Steal Web Session Cookie), AML.T0091.001 (Use Alternate Authentication Material: Web Session Cookie) and AML.T0114 (AI Service Web Interface) to release 2026.05 and removed no technique ids. Earlier releases shipped the AML.T0010 sub-technique expansion and the agentic-AI techniques this forecast tracked (\"Publish Poisoned AI Agent Tool\", \"Escape to Host\"). Forward watch: subsequent monthly ATLAS releases, for updates to agentic-AI TTPs and MLOps-pipeline-specific techniques"
2285
2285
  ],
2286
2286
  "signature": "+DWL+I6VipjzZpvjZptUNk7jrCYhOBQqFy1ejThc4Gdr2BJ5vWYuRWclUUd4RhC58iv4S3NAgatuZOcXTOkRCg==",
2287
- "signed_at": "2026-09-23T16:52:05.513Z"
2287
+ "signed_at": "2026-09-27T05:23:30.383Z"
2288
2288
  },
2289
2289
  {
2290
2290
  "name": "incident-response-playbook",
@@ -2359,7 +2359,7 @@
2359
2359
  "NYDFS 23 NYCRR 500.17 amendments tightening ransom-payment 24h disclosure operationalization"
2360
2360
  ],
2361
2361
  "signature": "GXEqUic3Dg65QODe/2+AA5PJ2gkRLf39/AbFaZDt19GzknfhHlBxQf7LrpDX2S87JKPHzHPShRAFRxJSW90LAA==",
2362
- "signed_at": "2026-09-23T16:52:05.513Z"
2362
+ "signed_at": "2026-09-27T05:23:30.384Z"
2363
2363
  },
2364
2364
  {
2365
2365
  "name": "ransomware-response",
@@ -2439,7 +2439,7 @@
2439
2439
  ],
2440
2440
  "last_threat_review": "2026-09-18",
2441
2441
  "signature": "ULB2eBGPwh5vgOTK9m9i7Do25p48npVDpyDqjRYOfUUHoYvXkG+XxF0DdJLrs27ngQ2TyETn6X9xKp4310RGBA==",
2442
- "signed_at": "2026-09-23T16:52:05.514Z"
2442
+ "signed_at": "2026-09-27T05:23:30.384Z"
2443
2443
  },
2444
2444
  {
2445
2445
  "name": "email-security-anti-phishing",
@@ -2507,7 +2507,7 @@
2507
2507
  ],
2508
2508
  "last_threat_review": "2026-05-18",
2509
2509
  "signature": "FVBn4ex2qPIo9SHMVJ6tntoz4tVwjbIq3m6wDjjZyv2JODlS+90GBYCOkNamxxkmw/6de6SMs0YHQiF/xjo/DQ==",
2510
- "signed_at": "2026-09-23T16:52:05.514Z"
2510
+ "signed_at": "2026-09-27T05:23:30.384Z"
2511
2511
  },
2512
2512
  {
2513
2513
  "name": "age-gates-child-safety",
@@ -2582,7 +2582,7 @@
2582
2582
  "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"
2583
2583
  ],
2584
2584
  "signature": "rlHzyruu9OhkcVrYfHnMJvQf9z3rnDh5VbDQr4qCmqFXTzPqyQz9u1GvKdNiElSNXv3Qv3afvUFsvcHxOxX4DQ==",
2585
- "signed_at": "2026-09-23T16:52:05.515Z"
2585
+ "signed_at": "2026-09-27T05:23:30.385Z"
2586
2586
  },
2587
2587
  {
2588
2588
  "name": "cloud-iam-incident",
@@ -2662,7 +2662,7 @@
2662
2662
  ],
2663
2663
  "last_threat_review": "2026-05-15",
2664
2664
  "signature": "jIHvISo1VRnvLRMktdJtEIpb/jKEu5yk23WrzoZCIdhtzGdcXL10vVfycxVM6U/tHg+u/5ju/x8wreQRnYHQBQ==",
2665
- "signed_at": "2026-09-23T16:52:05.515Z",
2665
+ "signed_at": "2026-09-27T05:23:30.385Z",
2666
2666
  "forward_watch": [
2667
2667
  "AWS IAM Identity Center session-policy refresh and step-up-on-admin enforcement (anticipated 2026-H2 release)",
2668
2668
  "GCP Workload Identity Federation principal-set attribute mapping tightening (post-2026 Q3 Federation hardening guide)",
@@ -2756,7 +2756,7 @@
2756
2756
  ],
2757
2757
  "last_threat_review": "2026-05-15",
2758
2758
  "signature": "gbYSLSe+VfZy3fwKkKIIDa4ipF7lbcKTWMyEAmvdGoO4TgQKWZf5/1mAxOSj0kqkXc16ai09NsSc70NOP05RBA==",
2759
- "signed_at": "2026-09-23T16:52:05.515Z",
2759
+ "signed_at": "2026-09-27T05:23:30.385Z",
2760
2760
  "forward_watch": [
2761
2761
  "Entra ID conditional access evolution post-Midnight Blizzard — Microsoft's 2025-2026 commitments on legacy-tenant MFA enforcement and OAuth-app consent gating",
2762
2762
  "Okta IPSIE (Interoperability Profile for Secure Identity in the Enterprise) OpenID Foundation working-group output and adoption timeline",
@@ -2828,7 +2828,7 @@
2828
2828
  "d3fend_refs": [],
2829
2829
  "last_threat_review": "2026-06-02",
2830
2830
  "signature": "dOFgANMtHm64uSFRjMfeA0fWZS9ISwMTt59I2CbjaF1PgTtbtb8yg/f+3pC4eXcXIET0KPGxRRmENycfIz3rAw==",
2831
- "signed_at": "2026-09-23T16:52:05.516Z"
2831
+ "signed_at": "2026-09-27T05:23:30.386Z"
2832
2832
  },
2833
2833
  {
2834
2834
  "name": "mail-server-hardening",
@@ -2887,7 +2887,7 @@
2887
2887
  "d3fend_refs": [],
2888
2888
  "last_threat_review": "2026-06-02",
2889
2889
  "signature": "5x8RGzKo/T2IbYnFkYMZs16ThD9a5FEdrKHsnwvtMuGxdyyfZsKNIJVWw2I8O0um0UOXwwkl17Z3zhch26ymCQ==",
2890
- "signed_at": "2026-09-23T16:52:05.516Z"
2890
+ "signed_at": "2026-09-27T05:23:30.386Z"
2891
2891
  },
2892
2892
  {
2893
2893
  "name": "network-trust",
@@ -2943,7 +2943,7 @@
2943
2943
  "d3fend_refs": [],
2944
2944
  "last_threat_review": "2026-06-02",
2945
2945
  "signature": "C/RdmnGjXKreKiGkwJfUESIxUwQzisGJ9A7KBdE9cBRBHBYHkAcScV89L+Z3kOG032Qax6LeIQai7Lr3nrQBCA==",
2946
- "signed_at": "2026-09-23T16:52:05.516Z"
2946
+ "signed_at": "2026-09-27T05:23:30.386Z"
2947
2947
  },
2948
2948
  {
2949
2949
  "name": "audit-log-integrity",
@@ -2998,7 +2998,7 @@
2998
2998
  "d3fend_refs": [],
2999
2999
  "last_threat_review": "2026-06-02",
3000
3000
  "signature": "T7sFREX7P2QYrau+eTNXKkrU2aJ91dsX6GQWVJeexJ9SqbyFHtAnIKo4r6F6VdELADyVjaRXKk/fLuyUaCkGBA==",
3001
- "signed_at": "2026-09-23T16:52:05.516Z"
3001
+ "signed_at": "2026-09-27T05:23:30.386Z"
3002
3002
  },
3003
3003
  {
3004
3004
  "name": "self-update-integrity",
@@ -3052,7 +3052,7 @@
3052
3052
  "d3fend_refs": [],
3053
3053
  "last_threat_review": "2026-06-02",
3054
3054
  "signature": "OKVmNgVoGGDS8kwezWrtFk62xgYkU3B7lhGRd7xO7wfSQPbETk+aeLmkpoS8sTryzrAg7JYhJ0qDofbSQpOTCg==",
3055
- "signed_at": "2026-09-23T16:52:05.516Z"
3055
+ "signed_at": "2026-09-27T05:23:30.386Z"
3056
3056
  },
3057
3057
  {
3058
3058
  "name": "multitenancy-isolation",
@@ -3110,7 +3110,7 @@
3110
3110
  "d3fend_refs": [],
3111
3111
  "last_threat_review": "2026-06-02",
3112
3112
  "signature": "MWDxwIfhUvGAet5F1LBJnBApTBHafuW+NwysdaSYh8DmPM70bcg6v7f7qwv+zADXYc1LHdF4FoqiAcFy8TA7DA==",
3113
- "signed_at": "2026-09-23T16:52:05.517Z"
3113
+ "signed_at": "2026-09-27T05:23:30.387Z"
3114
3114
  },
3115
3115
  {
3116
3116
  "name": "decompression-dos",
@@ -3168,7 +3168,7 @@
3168
3168
  "d3fend_refs": [],
3169
3169
  "last_threat_review": "2026-06-02",
3170
3170
  "signature": "iDsEYQo/OWYUI8TbBNsS9A60Kt5XEcZ1WYKg52wuSAzgctn4W68dgMeaoNbPXq2Bon1amFKIH5uxUtU8q7I/Dw==",
3171
- "signed_at": "2026-09-23T16:52:05.517Z"
3171
+ "signed_at": "2026-09-27T05:23:30.387Z"
3172
3172
  },
3173
3173
  {
3174
3174
  "name": "log-injection-telemetry",
@@ -3223,7 +3223,7 @@
3223
3223
  "d3fend_refs": [],
3224
3224
  "last_threat_review": "2026-06-02",
3225
3225
  "signature": "1Qn1LUzL2qCvG+jEaif7uMVL/cDwyMVueZAhu5uSroQzfw1V5X2vm/t69fExGKoLnVdkfta71aZWI4Gz0tfiDQ==",
3226
- "signed_at": "2026-09-23T16:52:05.517Z"
3226
+ "signed_at": "2026-09-27T05:23:30.387Z"
3227
3227
  },
3228
3228
  {
3229
3229
  "name": "privacy-consent-ops",
@@ -3278,11 +3278,11 @@
3278
3278
  "d3fend_refs": [],
3279
3279
  "last_threat_review": "2026-06-02",
3280
3280
  "signature": "UIzZfFwZP/7Gg5IdwQQTv6oDZyzjID8lXWYL1SgiSu4JRPJYzt/vqQO1ztfEaaRdbZBi0Vao3td2aFixnhw6AQ==",
3281
- "signed_at": "2026-09-23T16:52:05.517Z"
3281
+ "signed_at": "2026-09-27T05:23:30.387Z"
3282
3282
  }
3283
3283
  ],
3284
3284
  "manifest_signature": {
3285
3285
  "algorithm": "Ed25519",
3286
- "signature_base64": "A73XbsvpC/7XnjYyebnaspv5xP+BdANBOIGjtC6h9dPCOl5TbAI0wH3/Qg2CmunCBDq1xLOUD7XHPhBBdwBWCg=="
3286
+ "signature_base64": "kkPvnCSHHCopk/uB/UDEv2mfILZG6o59FIw8KywrEocW1yK9da4G/JpvouxJ/rBs6uvRvLNiIIE0hoNUXfgNDQ=="
3287
3287
  }
3288
3288
  }