@blamejs/exceptd-skills 0.19.32 → 0.19.34
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/CHANGELOG.md +22 -0
- package/bin/exceptd.js +896 -2824
- package/data/_indexes/_meta.json +8 -8
- package/data/_indexes/activity-feed.json +2 -2
- package/data/_indexes/catalog-summaries.json +7 -7
- package/data/_indexes/chains.json +60118 -0
- package/data/attack-techniques.json +267 -7
- package/data/cve-catalog.json +9991 -3
- package/data/cwe-catalog.json +109 -2
- package/data/framework-control-gaps.json +578 -3
- package/data/zeroday-lessons.json +8330 -1
- package/lib/auto-discovery.js +56 -286
- package/lib/canonical-eq.js +7 -40
- package/lib/citation-resolve.js +22 -70
- package/lib/collectors/ai-api.js +20 -54
- package/lib/collectors/cicd-pipeline-compromise.js +40 -108
- package/lib/collectors/citation-hygiene.js +72 -210
- package/lib/collectors/containers.js +41 -130
- package/lib/collectors/cred-stores.js +31 -115
- package/lib/collectors/crypto-codebase.js +55 -138
- package/lib/collectors/crypto.js +24 -54
- package/lib/collectors/hardening.js +20 -78
- package/lib/collectors/kernel.js +16 -46
- package/lib/collectors/library-author.js +57 -206
- package/lib/collectors/mcp.js +24 -70
- package/lib/collectors/runtime.js +24 -86
- package/lib/collectors/sbom.js +34 -106
- package/lib/collectors/scan-excludes.js +31 -138
- package/lib/collectors/secrets.js +62 -178
- package/lib/cross-ref-api.js +39 -123
- package/lib/currency-severity.js +8 -27
- package/lib/cve-batch.js +13 -21
- package/lib/cve-cli.js +13 -20
- package/lib/cve-curation.js +72 -239
- package/lib/cve-regression-watcher.js +29 -152
- package/lib/cvss.js +13 -54
- package/lib/doctor-bucketing.js +3 -19
- package/lib/exit-codes.js +10 -42
- package/lib/flag-suggest.js +7 -25
- package/lib/framework-gap.js +35 -114
- package/lib/gap-detectors.js +37 -159
- package/lib/id-validation.js +9 -30
- package/lib/job-queue.js +13 -36
- package/lib/lint-skills.js +64 -232
- package/lib/playbook-runner.js +693 -2095
- package/lib/prefetch.js +100 -376
- package/lib/refresh-external.js +199 -627
- package/lib/refresh-network.js +75 -307
- package/lib/rfc-cli.js +23 -68
- package/lib/scoring.js +77 -145
- package/lib/sign.js +43 -229
- package/lib/source-advisories.js +43 -194
- package/lib/source-ghsa.js +37 -120
- package/lib/source-osv.js +94 -266
- package/lib/ttp-mapper.js +14 -24
- package/lib/upstream-check-cli.js +10 -28
- package/lib/upstream-check.js +19 -44
- package/lib/validate-catalog-meta.js +17 -61
- package/lib/validate-cve-catalog.js +43 -119
- package/lib/validate-indexes.js +25 -76
- package/lib/validate-package.js +16 -62
- package/lib/validate-playbooks.js +69 -275
- package/lib/validate-vendor.js +16 -49
- package/lib/verify.js +56 -286
- package/lib/version-pins.js +5 -34
- package/lib/worker-pool.js +11 -30
- package/lib/xml-tokenizer.js +47 -152
- package/manifest.json +53 -53
- package/orchestrator/dispatcher.js +17 -68
- package/orchestrator/event-bus.js +11 -74
- package/orchestrator/index.js +138 -412
- package/orchestrator/pipeline.js +28 -85
- package/orchestrator/scanner.js +34 -138
- package/orchestrator/scheduler.js +20 -84
- package/package.json +2 -2
- package/sbom.cdx.json +253 -253
- package/scripts/audit-catalog-gaps.js +9 -62
- package/scripts/audit-cross-skill.js +5 -31
- package/scripts/audit-perf.js +6 -16
- package/scripts/backfill-theater-test.js +7 -64
- package/scripts/bootstrap.js +12 -44
- package/scripts/build-indexes.js +40 -154
- package/scripts/builders/activity-feed.js +4 -14
- package/scripts/builders/catalog-summaries.js +3 -10
- package/scripts/builders/currency.js +7 -20
- package/scripts/builders/cwe-chains.js +7 -30
- package/scripts/builders/did-ladders.js +6 -13
- package/scripts/builders/frequency.js +5 -19
- package/scripts/builders/jurisdiction-clocks.js +6 -25
- package/scripts/builders/recipes.js +6 -14
- package/scripts/builders/section-offsets.js +13 -51
- package/scripts/builders/stale-content.js +7 -28
- package/scripts/builders/summary-cards.js +8 -29
- package/scripts/builders/theater-fingerprints.js +12 -27
- package/scripts/builders/token-budget.js +4 -31
- package/scripts/check-agents-md-collectors.js +11 -54
- package/scripts/check-catalog-gap-budget.js +15 -32
- package/scripts/check-changelog-extract.js +18 -48
- package/scripts/check-codebase-patterns-currency.js +6 -22
- package/scripts/check-codebase-patterns.js +50 -143
- package/scripts/check-epss-consistency.js +9 -64
- package/scripts/check-framework-gap-coverage.js +13 -31
- package/scripts/check-manifest-snapshot.js +13 -73
- package/scripts/check-sbom-currency.js +44 -142
- package/scripts/check-test-count.js +15 -52
- package/scripts/check-test-coverage.js +66 -197
- package/scripts/check-test-subjects.js +21 -62
- package/scripts/check-ttp-references.js +14 -38
- package/scripts/check-ttp-upstream.js +8 -40
- package/scripts/check-version-bump.js +9 -61
- package/scripts/check-version-tags.js +20 -121
- package/scripts/predeploy.js +38 -184
- package/scripts/refresh-manifest-snapshot.js +16 -38
- package/scripts/refresh-mitre-atlas.js +3 -8
- package/scripts/refresh-mitre-attack.js +1 -8
- package/scripts/refresh-mitre-d3fend.js +3 -9
- package/scripts/refresh-mitre-ics-attack.js +3 -8
- package/scripts/refresh-reverse-refs.js +27 -94
- package/scripts/refresh-rfc-index.js +2 -10
- package/scripts/refresh-sbom.js +31 -161
- package/scripts/refresh-upstream-catalogs.js +40 -137
- package/scripts/release.js +69 -232
- package/scripts/run-e2e-scenarios.js +24 -71
- package/scripts/sync-manifest-metadata.js +10 -34
- package/scripts/sync-package-description.js +8 -17
- package/scripts/validate-vendor-online.js +13 -44
- package/scripts/verify-shipped-tarball.js +35 -140
|
@@ -1,44 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* 1. missing-context entries that exist but lack one of the
|
|
9
|
-
* documented context-search fields (e.g. RFC
|
|
10
|
-
* without abstract; ATT&CK technique without
|
|
11
|
-
* platforms; CVE without iocs)
|
|
12
|
-
*
|
|
13
|
-
* 2. dangling-ref forward references from one catalog into
|
|
14
|
-
* another that do not resolve (e.g. CVE
|
|
15
|
-
* entry's cwe_refs cites CWE-XXX but the
|
|
16
|
-
* local cwe-catalog does not carry that ID)
|
|
17
|
-
*
|
|
18
|
-
* 3. draft-debt per-catalog count of _auto_imported rows
|
|
19
|
-
* relative to operator-curated rows. High
|
|
20
|
-
* draft-debt = bulk-imported surface that has
|
|
21
|
-
* not been refined yet.
|
|
22
|
-
*
|
|
23
|
-
* Output: structured JSON to stdout (default) or human-readable summary
|
|
24
|
-
* with `--pretty`. Returns exit 0 in --warn-only mode (default); exit
|
|
25
|
-
* 1 in --strict mode if any class triggers.
|
|
26
|
-
*
|
|
27
|
-
* Usage:
|
|
28
|
-
* node scripts/audit-catalog-gaps.js # JSON
|
|
29
|
-
* node scripts/audit-catalog-gaps.js --pretty # human
|
|
30
|
-
* node scripts/audit-catalog-gaps.js --strict # exit 1 on gap
|
|
31
|
-
* node scripts/audit-catalog-gaps.js --catalog cve # one catalog
|
|
32
|
-
* node scripts/audit-catalog-gaps.js --class missing-context
|
|
33
|
-
*
|
|
34
|
-
* npm: `npm run audit-catalog-gaps`
|
|
35
|
-
*
|
|
36
|
-
* Design note: the gap analyzer is a separate detection plane from
|
|
37
|
-
* lib/validate-cve-catalog.js (schema validation, predeploy gate) and
|
|
38
|
-
* scripts/refresh-reverse-refs.js (forward/reverse-ref currency). The
|
|
39
|
-
* validator polices what's strictly required by the schema; the gap
|
|
40
|
-
* analyzer polices the recommended-but-not-required context envelope
|
|
41
|
-
* that lets an AI consumer find an entry by topic instead of by ID.
|
|
4
|
+
* Walks every data/*.json catalog for gaps: entries missing a documented context
|
|
5
|
+
* field, cross-catalog refs that do not resolve, and per-catalog draft debt.
|
|
6
|
+
* Warn-only by default; --strict exits 1 when any class triggers. Distinct from
|
|
7
|
+
* lib/validate-cve-catalog.js, which polices what the schema strictly requires.
|
|
42
8
|
*/
|
|
43
9
|
|
|
44
10
|
const fs = require("fs");
|
|
@@ -48,10 +14,7 @@ const ROOT = path.join(__dirname, "..");
|
|
|
48
14
|
const DATA = path.join(ROOT, "data");
|
|
49
15
|
const TODAY = new Date().toISOString().slice(0, 10);
|
|
50
16
|
|
|
51
|
-
// Per-catalog required context fields
|
|
52
|
-
// field path (dot-separated for nested) and a non-emptiness predicate.
|
|
53
|
-
// Pillar / Class / Pillar-abstraction CWEs and similar can opt out via
|
|
54
|
-
// the suppression key on the entry (_gap_skip: { fields: [...] }).
|
|
17
|
+
// Per-catalog required context fields; an entry opts out with _gap_skip: { fields: [...] }.
|
|
55
18
|
const SPEC = {
|
|
56
19
|
"cve-catalog": {
|
|
57
20
|
file: "cve-catalog.json",
|
|
@@ -133,11 +96,6 @@ const SPEC = {
|
|
|
133
96
|
{ field: "control_name", check: (v) => typeof v === "string" && v.length > 0, label: "control_name" },
|
|
134
97
|
{ field: "real_requirement", check: (v) => typeof v === "string" && v.length > 20, label: "real_requirement (>20 chars)" },
|
|
135
98
|
{ field: "theater_test", check: (v) => v && typeof v.claim === "string" && typeof v.test === "string", label: "theater_test{claim,test}" },
|
|
136
|
-
// evidence_cves is required UNLESS the entry declares forward_looking:true.
|
|
137
|
-
// v0.13.19 used per-entry _gap_skip annotations on 84 framework gaps;
|
|
138
|
-
// v0.13.20 replaces that with a first-class schema field operators can
|
|
139
|
-
// see in the JSON. The check honors forward_looking via the entry
|
|
140
|
-
// parameter — see the SCHEMA_FORWARD_LOOKING block in inspect().
|
|
141
99
|
{ field: "evidence_cves", check: (v, entry) => (entry && entry.forward_looking === true) || (Array.isArray(v) && v.length > 0), label: "evidence_cves (or forward_looking:true)" }
|
|
142
100
|
],
|
|
143
101
|
refs: []
|
|
@@ -180,10 +138,7 @@ function inspect(catalogKey) {
|
|
|
180
138
|
const skip = e._gap_skip && Array.isArray(e._gap_skip.fields) ? new Set(e._gap_skip.fields) : new Set();
|
|
181
139
|
for (const r of spec.required_context) {
|
|
182
140
|
if (skip.has(r.field)) continue;
|
|
183
|
-
//
|
|
184
|
-
// inspect class-level schema flags (forward_looking, etc.). The
|
|
185
|
-
// legacy check-functions only consumed the value; new ones can
|
|
186
|
-
// opt into entry-aware evaluation.
|
|
141
|
+
// The second argument lets a check consult entry-level flags like forward_looking.
|
|
187
142
|
if (!r.check(e[r.field], e)) {
|
|
188
143
|
report.missing_context.push({ id, field: r.field, label: r.label });
|
|
189
144
|
}
|
|
@@ -199,7 +154,6 @@ function inspectRefs(allCatalogs) {
|
|
|
199
154
|
const attCat = allCatalogs["attack-techniques"];
|
|
200
155
|
const atlCat = allCatalogs["atlas-ttps"];
|
|
201
156
|
const fwCat = allCatalogs["framework-control-gaps"];
|
|
202
|
-
// Build presence sets keyed by id (sans _meta).
|
|
203
157
|
const cweSet = new Set(Object.keys(cweCat).filter((k) => k !== "_meta"));
|
|
204
158
|
const attSet = new Set(Object.keys(attCat).filter((k) => k !== "_meta"));
|
|
205
159
|
const atlSet = new Set(Object.keys(atlCat).filter((k) => k !== "_meta"));
|
|
@@ -246,7 +200,6 @@ function emitPretty(report) {
|
|
|
246
200
|
if (r.missing_context.length === 0) {
|
|
247
201
|
lines.push(" ✓ context complete on every entry");
|
|
248
202
|
} else {
|
|
249
|
-
// Group by field for tidier output.
|
|
250
203
|
const byField = new Map();
|
|
251
204
|
for (const m of r.missing_context) {
|
|
252
205
|
if (!byField.has(m.field)) byField.set(m.field, []);
|
|
@@ -278,7 +231,6 @@ function emitPretty(report) {
|
|
|
278
231
|
const pct = r.entries === 0 ? 0 : ((r.auto_imported / r.entries) * 100).toFixed(1);
|
|
279
232
|
lines.push(` ${r.catalog.padEnd(28)} ${r.auto_imported} / ${r.entries} (${pct}%)`);
|
|
280
233
|
}
|
|
281
|
-
// v0.13.21 extended findings sections.
|
|
282
234
|
const ext = report.extended_findings || {};
|
|
283
235
|
const extClasses = Object.keys(ext).sort();
|
|
284
236
|
if (extClasses.length > 0) {
|
|
@@ -297,11 +249,7 @@ function emitPretty(report) {
|
|
|
297
249
|
return lines.join("\n");
|
|
298
250
|
}
|
|
299
251
|
|
|
300
|
-
//
|
|
301
|
-
// extended detection classes for gaps the v0.13.19 detector did not
|
|
302
|
-
// surface (content-quality / temporal-staleness / logical-consistency /
|
|
303
|
-
// cross-ref-completeness / schema-evolution / operator-action-sla /
|
|
304
|
-
// unused-orphan). Each is implemented in lib/gap-detectors.js.
|
|
252
|
+
// Names `--class` accepts; the extended ones are implemented in lib/gap-detectors.js.
|
|
305
253
|
const VALID_CLASSES = new Set([
|
|
306
254
|
"missing-context", "dangling-ref", "draft-debt",
|
|
307
255
|
"content-quality", "temporal-staleness", "logical-consistency",
|
|
@@ -334,12 +282,11 @@ function main() {
|
|
|
334
282
|
perCatalog.push(inspect(k));
|
|
335
283
|
allLoaded[k] = loadCatalog(SPEC[k].file);
|
|
336
284
|
}
|
|
337
|
-
//
|
|
285
|
+
// The cross-ref pass needs every catalog, even when --catalog scopes the audit.
|
|
338
286
|
for (const k of Object.keys(SPEC)) if (!allLoaded[k]) allLoaded[k] = loadCatalog(SPEC[k].file);
|
|
339
287
|
const dangling = opts.catalog && opts.catalog !== "cve-catalog" ? [] : inspectRefs(allLoaded);
|
|
340
288
|
|
|
341
|
-
//
|
|
342
|
-
// cross-catalog by nature); --class scoping filters down to one.
|
|
289
|
+
// --catalog mutes the extended detectors; they are cross-catalog by nature.
|
|
343
290
|
const extendedFindings = opts.catalog
|
|
344
291
|
? []
|
|
345
292
|
: EXTENDED_DETECTORS.runAllDetectors(allLoaded, {});
|
|
@@ -1,29 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* Comprehensive cross-skill accuracy / bug audit. Run after any
|
|
6
|
-
* skill add / rename / dispatch-rewire. Surfaces:
|
|
7
|
-
*
|
|
8
|
-
* - manifest paths that don't exist on disk
|
|
9
|
-
* - skill directories on disk with no manifest entry
|
|
10
|
-
* - frontmatter `name` drift from manifest `name`
|
|
11
|
-
* - skills missing from the researcher dispatch table
|
|
12
|
-
* - skills missing from AGENTS.md Quick Skill Reference
|
|
13
|
-
* - version drift between package.json / manifest.json / CHANGELOG.md
|
|
14
|
-
* - manifest-snapshot.json drift from manifest.json
|
|
15
|
-
* - sbom.cdx.json drift from live skill / catalog counts
|
|
16
|
-
* - broken ref: any cwe_refs / d3fend_refs / framework_gaps / atlas_refs /
|
|
17
|
-
* rfc_refs / dlp_refs that doesn't resolve in its catalog
|
|
18
|
-
* - RFC catalog reverse-references that drift from manifest forward-refs
|
|
19
|
-
* - skill-update-loop "Affected skills" blocks referencing nonexistent skills
|
|
20
|
-
* - stale references to renamed skills in any tracked file
|
|
21
|
-
* - trigger collisions between skills (informational)
|
|
22
|
-
* - README badge count drift
|
|
23
|
-
*
|
|
24
|
-
* Exit non-zero on any finding (excluding trigger collisions which are informational).
|
|
25
|
-
*
|
|
26
|
-
* Usage: node scripts/audit-cross-skill.js
|
|
3
|
+
* Cross-skill accuracy audit: manifest, skill files, catalogs and docs must
|
|
4
|
+
* agree. Exits non-zero on any finding; trigger collisions are informational.
|
|
27
5
|
*/
|
|
28
6
|
|
|
29
7
|
const fs = require("fs");
|
|
@@ -196,7 +174,7 @@ for (const f of trackedDocs) {
|
|
|
196
174
|
const body = fs.readFileSync(ABS(f), "utf8");
|
|
197
175
|
for (const tok of staleTokens) {
|
|
198
176
|
if (body.includes(tok)) {
|
|
199
|
-
// CHANGELOG legitimately records the rename
|
|
177
|
+
// The CHANGELOG legitimately records the rename.
|
|
200
178
|
if (f === "CHANGELOG.md") continue;
|
|
201
179
|
note(`STALE RENAME REF in ${f}: contains "${tok}"`);
|
|
202
180
|
}
|
|
@@ -228,11 +206,8 @@ if (badgeMatch && Number(badgeMatch[1]) !== skills.length) {
|
|
|
228
206
|
const jurBadge = readme.match(/jurisdictions-(\d+)-/);
|
|
229
207
|
const liveJurs = (() => {
|
|
230
208
|
const g = JSON.parse(fs.readFileSync(ABS("data/global-frameworks.json"), "utf8"));
|
|
231
|
-
//
|
|
232
|
-
//
|
|
233
|
-
// ISO, CSA, CIS) is a counted entry, matching the README badge and the
|
|
234
|
-
// catalog-summary index. Only `_`-prefixed keys (_meta, _notification_summary,
|
|
235
|
-
// _patch_sla_summary) are metadata and excluded.
|
|
209
|
+
// Every non-metadata top-level entry, GLOBAL included — matches the README
|
|
210
|
+
// badge and the catalog-summary index.
|
|
236
211
|
return Object.keys(g).filter((k) => !k.startsWith("_")).length;
|
|
237
212
|
})();
|
|
238
213
|
if (jurBadge && Number(jurBadge[1]) !== liveJurs) {
|
|
@@ -249,7 +224,6 @@ if (cntClaim) {
|
|
|
249
224
|
}
|
|
250
225
|
}
|
|
251
226
|
|
|
252
|
-
// Output
|
|
253
227
|
console.log("\n=== CROSS-SKILL AUDIT ===");
|
|
254
228
|
console.log(`Skills: ${skills.length}`);
|
|
255
229
|
console.log(`Catalogs: ${liveCatalogs}`);
|
package/scripts/audit-perf.js
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* scripts/audit-perf.js
|
|
4
|
-
*
|
|
5
|
-
* Micro-benchmarks the hot paths a skill / orchestrator / audit
|
|
6
|
-
* actually exercises. Times each operation so we can decide what's
|
|
7
|
-
* worth pre-computing into a seeded index.
|
|
3
|
+
* scripts/audit-perf.js — micro-benchmarks the hot paths a skill, orchestrator
|
|
4
|
+
* or audit exercises, to decide what is worth pre-computing into a seeded index.
|
|
8
5
|
*
|
|
9
6
|
* Usage: node scripts/audit-perf.js
|
|
10
7
|
*/
|
|
@@ -29,13 +26,11 @@ console.log("\n=== exceptd hot-path performance ===\n");
|
|
|
29
26
|
console.log("Operation Time");
|
|
30
27
|
console.log("-".repeat(70));
|
|
31
28
|
|
|
32
|
-
// 1. Load manifest
|
|
33
29
|
const manifest = bench("load manifest.json (parse)", () =>
|
|
34
30
|
JSON.parse(fs.readFileSync(ABS("manifest.json"), "utf8"))
|
|
35
31
|
);
|
|
36
32
|
const skills = manifest.skills;
|
|
37
33
|
|
|
38
|
-
// 2. Load every data catalog
|
|
39
34
|
const catalogs = [
|
|
40
35
|
"cve-catalog.json",
|
|
41
36
|
"atlas-ttps.json",
|
|
@@ -54,12 +49,11 @@ const catalogObjs = bench(`load all ${catalogs.length} data catalogs`, () => {
|
|
|
54
49
|
return out;
|
|
55
50
|
});
|
|
56
51
|
|
|
57
|
-
// 3. Read every skill body
|
|
58
52
|
bench(`read all ${skills.length} skill.md bodies`, () => {
|
|
59
53
|
for (const s of skills) fs.readFileSync(ABS(s.path), "utf8");
|
|
60
54
|
});
|
|
61
55
|
|
|
62
|
-
//
|
|
56
|
+
// The linter's expensive operation.
|
|
63
57
|
function parseFm(text) {
|
|
64
58
|
if (!text.startsWith("---")) return null;
|
|
65
59
|
const end = text.indexOf("\n---", 3);
|
|
@@ -90,7 +84,7 @@ bench(`parse all ${skills.length} skill frontmatters`, () => {
|
|
|
90
84
|
for (const s of skills) parseFm(fs.readFileSync(ABS(s.path), "utf8"));
|
|
91
85
|
});
|
|
92
86
|
|
|
93
|
-
//
|
|
87
|
+
// The lookup the dispatcher performs.
|
|
94
88
|
const flatTriggers = [];
|
|
95
89
|
for (const s of skills) for (const t of s.triggers || []) flatTriggers.push([t.toLowerCase(), s.name]);
|
|
96
90
|
bench("trigger string-match against all skills (single query)", () => {
|
|
@@ -98,16 +92,14 @@ bench("trigger string-match against all skills (single query)", () => {
|
|
|
98
92
|
return flatTriggers.filter(([t]) => t.includes(q) || q.includes(t));
|
|
99
93
|
});
|
|
100
94
|
|
|
101
|
-
// 6. Cross-reference lookup: which skills cite a given CWE?
|
|
102
95
|
bench("xref: which skills cite CWE-79? (linear scan)", () => {
|
|
103
96
|
const refSet = "CWE-79";
|
|
104
97
|
return skills.filter((s) => (s.cwe_refs || []).includes(refSet)).map((s) => s.name);
|
|
105
98
|
});
|
|
106
99
|
|
|
107
|
-
// 7. Multi-hop chain: CVE → CWE → ATLAS → framework_gaps for one CVE
|
|
108
100
|
const cve = catalogObjs["cve-catalog.json"]["CVE-2026-31431"];
|
|
109
101
|
bench("multi-hop chain: CVE-2026-31431 → CWE → ATLAS → frameworks", () => {
|
|
110
|
-
//
|
|
102
|
+
// CVE → the citing skills' CWE refs → their ATLAS refs → their framework gaps.
|
|
111
103
|
const skillsCiting = skills.filter((s) =>
|
|
112
104
|
(catalogObjs["cve-catalog.json"]["CVE-2026-31431"].evidence_cves || []).length > 0 // dummy filter
|
|
113
105
|
);
|
|
@@ -123,7 +115,6 @@ bench("multi-hop chain: CVE-2026-31431 → CWE → ATLAS → frameworks", () =>
|
|
|
123
115
|
return { cwes: [...cwes], atlases: [...atlases], fws: [...fws] };
|
|
124
116
|
});
|
|
125
117
|
|
|
126
|
-
// 8. Forward_watch aggregator (read 38 skill files, parse frontmatter, union all forward_watch)
|
|
127
118
|
bench(`watchlist aggregator (full scan, ${skills.length} skills)`, () => {
|
|
128
119
|
const watch = new Set();
|
|
129
120
|
for (const s of skills) {
|
|
@@ -133,9 +124,8 @@ bench(`watchlist aggregator (full scan, ${skills.length} skills)`, () => {
|
|
|
133
124
|
return watch.size;
|
|
134
125
|
});
|
|
135
126
|
|
|
136
|
-
// 9. Full cross-skill audit
|
|
137
127
|
bench("full cross-skill audit script (subprocess overhead included)", () => {
|
|
138
|
-
//
|
|
128
|
+
// Simulated: load the manifest, catalogs and skill files, walk every refset.
|
|
139
129
|
for (const s of skills) {
|
|
140
130
|
fs.readFileSync(ABS(s.path), "utf8");
|
|
141
131
|
for (const f of s.cwe_refs || []) { /* lookup */ }
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// One-shot backfill of theater_test field
|
|
3
|
-
// Hard Rule #6: every compliance-framework finding
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
// Per-entry tests are authored against the entry's framework + control_name +
|
|
7
|
-
// real_requirement so each one discriminates the named framework's paper
|
|
8
|
-
// language from the named real-world threat.
|
|
2
|
+
// One-shot backfill of the theater_test field in data/framework-control-gaps.json.
|
|
3
|
+
// Hard Rule #6: every compliance-framework finding carries a specific test that
|
|
4
|
+
// tells paper compliance from actual security.
|
|
9
5
|
|
|
10
6
|
const fs = require('fs');
|
|
11
7
|
const path = require('path');
|
|
@@ -14,15 +10,10 @@ const CATALOG_PATH = path.resolve(__dirname, '..', 'data', 'framework-control-ga
|
|
|
14
10
|
|
|
15
11
|
const PAPER = 'compliance-theater';
|
|
16
12
|
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
// uses. Where two entries share the same audit pattern (e.g. several NIST
|
|
20
|
-
// 800-53 SI-* controls), the tests are similar in shape but worded against
|
|
21
|
-
// the specific control text — never literally copy-pasted.
|
|
13
|
+
// entry-key → theater_test, hand-authored and grouped by framework family so
|
|
14
|
+
// each test speaks the language an auditor for that framework uses.
|
|
22
15
|
const TESTS = {
|
|
23
|
-
// ---------------------------------------------------------------------
|
|
24
16
|
// Universal / cross-framework AI gaps
|
|
25
|
-
// ---------------------------------------------------------------------
|
|
26
17
|
'ALL-AI-PIPELINE-INTEGRITY': {
|
|
27
18
|
claim: "We monitor our AI providers for security and treat model updates like any other vendor change.",
|
|
28
19
|
test: "Pull the change-control register for the last 4 quarters; filter for entries where the affected asset is an externally hosted LLM, embedding model, or AI provider API. Count how many record (a) the model version pinned at the time, (b) a behavioural regression suite executed against the new version, and (c) the provider changelog reviewed with sign-off. Theater verdict if fewer than 90% of provider-side model updates produced an in-scope change-control entry, or if any sampled entry lacks a regression-suite artifact.",
|
|
@@ -42,9 +33,7 @@ const TESTS = {
|
|
|
42
33
|
verdict_when_failed: PAPER
|
|
43
34
|
},
|
|
44
35
|
|
|
45
|
-
// ---------------------------------------------------------------------
|
|
46
36
|
// Australian frameworks (Essential 8, ISM)
|
|
47
|
-
// ---------------------------------------------------------------------
|
|
48
37
|
'AU-Essential-8-App-Hardening': {
|
|
49
38
|
claim: "We hardened user applications per Essential Eight Maturity Level 2; browsers and Office are locked down.",
|
|
50
39
|
test: "Take the operator's hardened-application list. Confirm whether it enumerates AI coding assistants (Copilot, Cursor, Claude Code, Windsurf), MCP servers, and AI-tool config files (.claude/settings.json, .cursor/mcp.json, .vscode/settings.json:chat.tools.autoApprove) as in-scope. Pick a developer endpoint at random; verify those config files are integrity-monitored with the same alerting profile as security-sensitive files. Theater verdict if AI assistants are absent from the hardened-application list or if a config-file modification on the sampled endpoint would not generate an integrity alert.",
|
|
@@ -70,9 +59,7 @@ const TESTS = {
|
|
|
70
59
|
verdict_when_failed: PAPER
|
|
71
60
|
},
|
|
72
61
|
|
|
73
|
-
// ---------------------------------------------------------------------
|
|
74
62
|
// CIS Controls
|
|
75
|
-
// ---------------------------------------------------------------------
|
|
76
63
|
'CIS-Controls-v8-Control7': {
|
|
77
64
|
claim: "We meet CIS Control 7 IG3 by remediating critical vulnerabilities within one month.",
|
|
78
65
|
test: "Pull the vulnerability register for the past 12 months. Filter for CVEs that appeared on CISA KEV with public PoC during the period. For each, measure (a) time from KEV listing to verified mitigation, and (b) whether the mitigation was a live patch, configuration change, or isolation. Theater verdict if any KEV+PoC entry exceeded 4h to verified mitigation or if 'monthly cadence' was applied to a KEV-listed CVE.",
|
|
@@ -80,9 +67,7 @@ const TESTS = {
|
|
|
80
67
|
verdict_when_failed: PAPER
|
|
81
68
|
},
|
|
82
69
|
|
|
83
|
-
// ---------------------------------------------------------------------
|
|
84
70
|
// CMMC / FedRAMP
|
|
85
|
-
// ---------------------------------------------------------------------
|
|
86
71
|
'CMMC-2.0-Level-2': {
|
|
87
72
|
claim: "We are CMMC Level 2 attested across all 110 NIST 800-171 controls; CUI is protected end-to-end.",
|
|
88
73
|
test: "Walk the 3.4.1 (CM) asset inventory and check for AI assistants and MCP servers with CUI-adjacent access. Then inspect 3.13 system-and-communications protections to confirm AI-API egress is enumerated as a CUI exfiltration channel with monitoring. Theater verdict if AI assistants are absent from the asset inventory, or if AI-API egress at the CUI boundary has no monitoring rule, or if cross-walks to UK DEF STAN / AU DISP for joint programmes are missing.",
|
|
@@ -96,9 +81,7 @@ const TESTS = {
|
|
|
96
81
|
verdict_when_failed: PAPER
|
|
97
82
|
},
|
|
98
83
|
|
|
99
|
-
// ---------------------------------------------------------------------
|
|
100
84
|
// CWE / SBOM standards
|
|
101
|
-
// ---------------------------------------------------------------------
|
|
102
85
|
'CWE-Top-25-2024-meta': {
|
|
103
86
|
claim: "Our SAST/DAST coverage maps to the CWE Top 25; we test for the most dangerous weaknesses.",
|
|
104
87
|
test: "Pull the SAST/DAST rule pack and enumerate which CWE IDs each rule targets. Confirm rules exist for AI-specific CWE classes (CWE-1039 model integrity, CWE-1395 dependency on vulnerable third-party component, prompt-injection class CWEs). Run the rule pack against a known-vulnerable test fixture containing prompt-injection patterns. Theater verdict if AI-relevant CWE IDs are absent from the rule pack, or if the fixture run produces zero findings on the planted prompt-injection.",
|
|
@@ -118,9 +101,7 @@ const TESTS = {
|
|
|
118
101
|
verdict_when_failed: PAPER
|
|
119
102
|
},
|
|
120
103
|
|
|
121
|
-
// ---------------------------------------------------------------------
|
|
122
104
|
// EU DORA family
|
|
123
|
-
// ---------------------------------------------------------------------
|
|
124
105
|
'DORA-Art28': {
|
|
125
106
|
claim: "Our DORA Art. 28 ICT third-party register covers all critical or important function dependencies.",
|
|
126
107
|
test: "From the Art. 28 register, sample 5 third-party ICT services consumed in CIF (critical or important function) flows. For each, verify presence of build-provenance metadata (SLSA producer identifier, workflow file hash, cache key surface). Check for monthly producer-side cache verification evidence. Theater verdict if any sampled CIF dependency lacks build-provenance metadata, or if cache verification has not run in the last 90 days.",
|
|
@@ -164,9 +145,7 @@ const TESTS = {
|
|
|
164
145
|
verdict_when_failed: PAPER
|
|
165
146
|
},
|
|
166
147
|
|
|
167
|
-
// ---------------------------------------------------------------------
|
|
168
148
|
// EU AI Act
|
|
169
|
-
// ---------------------------------------------------------------------
|
|
170
149
|
'EU-AI-Act-Art-15': {
|
|
171
150
|
claim: "Our high-risk AI system meets the EU AI Act Art. 15 'appropriate level of cybersecurity'.",
|
|
172
151
|
test: "Request the cybersecurity test pack. Confirm presence of (a) prompt-injection red-team results bound to OWASP LLM Top 10, (b) RAG-corpus integrity test results, (c) model-extraction-resistance assessment, (d) MCP/plugin trust verification log. Then check incident-reporting bridge to NIS2 + DORA. Theater verdict if any of (a)-(d) are absent or older than 12 months, or if the bridge to NIS2/DORA notification clocks is undocumented.",
|
|
@@ -198,9 +177,7 @@ const TESTS = {
|
|
|
198
177
|
verdict_when_failed: PAPER
|
|
199
178
|
},
|
|
200
179
|
|
|
201
|
-
// ---------------------------------------------------------------------
|
|
202
180
|
// EU CRA
|
|
203
|
-
// ---------------------------------------------------------------------
|
|
204
181
|
'EU-CRA-Art13': {
|
|
205
182
|
claim: "We satisfy EU CRA Art. 13 essential cybersecurity requirements with technical documentation on file.",
|
|
206
183
|
test: "Request the canonical build-pipeline definition for the most recent release. Confirm publication alongside the release artifact (workflow file hash, runner attestation, secrets scope). Pick the release-being-installed at a downstream operator; verify its build pipeline matches the published definition by comparing producer-side hashes. Confirm the incident-notification clock starts from FIRST awareness (not from confirmed exploit). Theater verdict if pipeline definitions are unpublished, hashes diverge, or the clock policy starts later than first awareness.",
|
|
@@ -208,9 +185,7 @@ const TESTS = {
|
|
|
208
185
|
verdict_when_failed: PAPER
|
|
209
186
|
},
|
|
210
187
|
|
|
211
|
-
// ---------------------------------------------------------------------
|
|
212
188
|
// HIPAA
|
|
213
|
-
// ---------------------------------------------------------------------
|
|
214
189
|
'HIPAA-Security-Rule-164.312(a)(1)': {
|
|
215
190
|
claim: "We meet HIPAA 164.312(a)(1) access controls; PHI is access-controlled with unique user IDs.",
|
|
216
191
|
test: "Inventory AI providers in use; for each consuming PHI, locate a BAA covering prompt retention + training opt-out + breach notification within HIPAA timelines. Inspect prompt-flow telemetry for PHI; confirm DLP minimisation runs pre-egress. Confirm AI agent sessions have controls separate from human user controls. Theater verdict if any AI provider consuming PHI lacks a BAA, if DLP is absent on prompt egress, or if AI agent sessions inherit human controls without separation.",
|
|
@@ -242,9 +217,7 @@ const TESTS = {
|
|
|
242
217
|
verdict_when_failed: PAPER
|
|
243
218
|
},
|
|
244
219
|
|
|
245
|
-
// ---------------------------------------------------------------------
|
|
246
220
|
// HITRUST
|
|
247
|
-
// ---------------------------------------------------------------------
|
|
248
221
|
'HITRUST-CSF-v11.4-09.l': {
|
|
249
222
|
claim: "We meet HITRUST CSF 09.l outsourced services management for all third-party providers.",
|
|
250
223
|
test: "Pull the third-party register. Filter for AI providers; confirm AI vendors are inventoried separately from general SaaS. Spot-check 5 AI vendors for AI-specific contractual clauses (prompt retention, training opt-out, residency, model version pinning, prompt-breach notification). Search for self-signup AI usage on developer endpoints; confirm a policy prohibits it for in-scope data. Theater verdict if AI is bucketed inside generic SaaS, if any sampled AI vendor lacks AI-specific clauses, or if self-signup AI is in evidence on a developer endpoint that touches in-scope data.",
|
|
@@ -252,9 +225,7 @@ const TESTS = {
|
|
|
252
225
|
verdict_when_failed: PAPER
|
|
253
226
|
},
|
|
254
227
|
|
|
255
|
-
// ---------------------------------------------------------------------
|
|
256
228
|
// IEC 62443 / NIST 800-82 / NERC CIP — OT / ICS
|
|
257
|
-
// ---------------------------------------------------------------------
|
|
258
229
|
'IEC-62443-3-3': {
|
|
259
230
|
claim: "Our IACS architecture meets IEC 62443-3-3 system security requirements.",
|
|
260
231
|
test: "Inspect the zone-and-conduit diagram. Confirm AI operator assistants and AI-API egress paths from the corporate-to-OT boundary are enumerated as conduits with documented security levels. Sample 3 OT operator workstations; confirm any installed AI assistants are inventoried and that prompt-injection-class threats appear in the threat model. Theater verdict if AI conduits are absent from the zone diagram, or if AI assistants on OT operator workstations are not threat-modelled.",
|
|
@@ -274,9 +245,7 @@ const TESTS = {
|
|
|
274
245
|
verdict_when_failed: PAPER
|
|
275
246
|
},
|
|
276
247
|
|
|
277
|
-
// ---------------------------------------------------------------------
|
|
278
248
|
// ISO 27001 / ISO 27017 / ISO 23894 / ISO 42001
|
|
279
|
-
// ---------------------------------------------------------------------
|
|
280
249
|
'ISO-27001-2022-A.8.16': {
|
|
281
250
|
claim: "Our monitoring activities under ISO 27001:2022 A.8.16 cover all in-scope systems.",
|
|
282
251
|
test: "From the SIEM event-source inventory, confirm AI-API egress events, MCP server invocations, and AI-agent action audit logs are ingested. Sample one alert from each class in the past 30 days; confirm an analyst reviewed it. Theater verdict if any of those source classes are missing from the SIEM, or if no AI/MCP-related alert has been triaged in the past 90 days despite traffic being present.",
|
|
@@ -320,9 +289,7 @@ const TESTS = {
|
|
|
320
289
|
verdict_when_failed: PAPER
|
|
321
290
|
},
|
|
322
291
|
|
|
323
|
-
// ---------------------------------------------------------------------
|
|
324
292
|
// NIS2
|
|
325
|
-
// ---------------------------------------------------------------------
|
|
326
293
|
'NIS2-Art21-incident-handling': {
|
|
327
294
|
claim: "We can meet NIS2 Art. 21 incident handling obligations including the 24h early warning.",
|
|
328
295
|
test: "Run a tabletop with a synthetic significant-incident inject affecting an essential-service flow at T0. Stopwatch elapsed time to a Competent Authority early warning containing initial assessment, severity, and impact. Theater verdict if elapsed exceeds 24h, if no on-call is named to start the clock, or if the playbook has not been exercised in the past 12 months.",
|
|
@@ -348,9 +315,7 @@ const TESTS = {
|
|
|
348
315
|
verdict_when_failed: PAPER
|
|
349
316
|
},
|
|
350
317
|
|
|
351
|
-
// ---------------------------------------------------------------------
|
|
352
318
|
// NIST SPs and AI RMF
|
|
353
|
-
// ---------------------------------------------------------------------
|
|
354
319
|
'NIST-800-115': {
|
|
355
320
|
claim: "Our pen-test methodology aligns with NIST SP 800-115 technical guidance.",
|
|
356
321
|
test: "Pull the most recent pen-test report. Confirm coverage of AI/MCP attack surfaces (prompt injection, MCP plugin trust, RAG corpus integrity, AI-API egress). Confirm the testing methodology document references AI-specific test classes and tooling. Theater verdict if AI/MCP testing is absent from the methodology, or if the pen-test report contains no AI-class findings despite AI being in production.",
|
|
@@ -436,9 +401,7 @@ const TESTS = {
|
|
|
436
401
|
verdict_when_failed: PAPER
|
|
437
402
|
},
|
|
438
403
|
|
|
439
|
-
// ---------------------------------------------------------------------
|
|
440
404
|
// OWASP family
|
|
441
|
-
// ---------------------------------------------------------------------
|
|
442
405
|
'OWASP-ASVS-v5.0-V14': {
|
|
443
406
|
claim: "Our application meets OWASP ASVS v5.0 V14 configuration controls.",
|
|
444
407
|
test: "For any AI-mediated feature, confirm V14-equivalent controls cover prompt-isolation, output-sanitisation, and tool-grant defaults. Confirm SDK pinning and provider-version pinning where supported. Theater verdict if AI-feature configuration management is informal (no pinned versions, no documented prompt-isolation policy).",
|
|
@@ -476,9 +439,7 @@ const TESTS = {
|
|
|
476
439
|
verdict_when_failed: PAPER
|
|
477
440
|
},
|
|
478
441
|
|
|
479
|
-
// ---------------------------------------------------------------------
|
|
480
442
|
// PCI DSS family
|
|
481
|
-
// ---------------------------------------------------------------------
|
|
482
443
|
'PCI-DSS-4.0-6.3.3': {
|
|
483
444
|
claim: "We address security vulnerabilities in custom and bespoke software per PCI DSS 6.3.3.",
|
|
484
445
|
test: "Confirm the SDLC includes prompt-injection-class CWE coverage in code review for AI-mediated features. Inspect change tickets for AI-feature changes; confirm reviewer attestation includes AI-class threat sign-off. Theater verdict if AI-mediated changes bypass the prompt-injection threat-review gate.",
|
|
@@ -510,9 +471,7 @@ const TESTS = {
|
|
|
510
471
|
verdict_when_failed: PAPER
|
|
511
472
|
},
|
|
512
473
|
|
|
513
|
-
// ---------------------------------------------------------------------
|
|
514
474
|
// PSD2 / PTES
|
|
515
|
-
// ---------------------------------------------------------------------
|
|
516
475
|
'PSD2-RTS-SCA': {
|
|
517
476
|
claim: "Our payment authentication satisfies PSD2 RTS-SCA strong customer authentication requirements.",
|
|
518
477
|
test: "Inventory payment-initiation flows. For any AI-mediated initiation (agent-initiated transactions, copilot-drafted payments), confirm an explicit delegated-authority attestation per transaction class with scope (amount, counterparty, frequency). Confirm a distinct audit indicator marks AI-mediated transactions. Theater verdict if AI initiations inherit the human-user SCA evidence path without delegated-authority attestation.",
|
|
@@ -526,9 +485,7 @@ const TESTS = {
|
|
|
526
485
|
verdict_when_failed: PAPER
|
|
527
486
|
},
|
|
528
487
|
|
|
529
|
-
// ---------------------------------------------------------------------
|
|
530
488
|
// SLSA
|
|
531
|
-
// ---------------------------------------------------------------------
|
|
532
489
|
'SLSA-v1.0-Build-L3': {
|
|
533
490
|
claim: "Our build pipeline is SLSA Build L3 with non-falsifiable provenance signed by a hardened build platform.",
|
|
534
491
|
test: "Pull the SLSA provenance attestation for the most-recent release. Confirm the build platform is hosted/hardened, the attestation is signed, and the materials cover the full source-of-truth. Then confirm AI-authorship attestation (per-block provenance for AI-generated code with reviewer identity) is present. Confirm any model artefacts shipped have a Model Track equivalent attestation. Theater verdict if attestations exist but AI-authored diffs lack reviewer attestation, or if model artefacts ship at SLSA L0/L1 equivalent without explicit model-track attestation.",
|
|
@@ -536,9 +493,7 @@ const TESTS = {
|
|
|
536
493
|
verdict_when_failed: PAPER
|
|
537
494
|
},
|
|
538
495
|
|
|
539
|
-
// ---------------------------------------------------------------------
|
|
540
496
|
// SOC 2
|
|
541
|
-
// ---------------------------------------------------------------------
|
|
542
497
|
'SOC2-CC6-logical-access': {
|
|
543
498
|
claim: "Our SOC 2 CC6 logical and physical access controls cover all in-scope systems.",
|
|
544
499
|
test: "Sample AI-agent invocation flows. Confirm authorisation-context evidence per invocation (scope, tools, data sensitivity). Confirm prompt logging captures sufficient detail for post-incident analysis (input chain, output, tool calls). Confirm anomaly detection alerts on AI-agent actions outside baseline. Theater verdict if AI-agent actions are not separately authorised, prompts are unlogged, or anomaly detection is absent.",
|
|
@@ -570,9 +525,7 @@ const TESTS = {
|
|
|
570
525
|
verdict_when_failed: PAPER
|
|
571
526
|
},
|
|
572
527
|
|
|
573
|
-
// ---------------------------------------------------------------------
|
|
574
528
|
// SWIFT CSCF
|
|
575
|
-
// ---------------------------------------------------------------------
|
|
576
529
|
'SWIFT-CSCF-v2026-1.1': {
|
|
577
530
|
claim: "Our SWIFT secure zone is segregated and protected per CSCF v2026 1.1.",
|
|
578
531
|
test: "Inspect the secure-zone policy. Confirm explicit prohibition or strict gating of LLM assistants inside the secure zone. Confirm AI-API egress from administrative jump zones is enumerated as a named conduit with monitoring. Confirm AI-generated MT/MX message drafts are flagged as a distinct review class. Cross-walk to DORA Art. 28 register. Theater verdict if LLM assistants are silently permitted, AI-API egress is unmonitored, or no DORA cross-walk exists.",
|
|
@@ -580,9 +533,7 @@ const TESTS = {
|
|
|
580
533
|
verdict_when_failed: PAPER
|
|
581
534
|
},
|
|
582
535
|
|
|
583
|
-
// ---------------------------------------------------------------------
|
|
584
536
|
// UK CAF
|
|
585
|
-
// ---------------------------------------------------------------------
|
|
586
537
|
'UK-CAF-A1': {
|
|
587
538
|
claim: "Our governance satisfies UK CAF A1 with board-level cyber risk accountability.",
|
|
588
539
|
test: "Pull the board governance pack. Confirm an AI-systems-in-use inventory is reviewed at board cadence, an MCP/plugin trust register exists, and accountability for AI security outcomes maps to a named executive in the NIS2/CCRA scope. Theater verdict if AI is absent from board-pack contents, or if AI accountability is unassigned at executive level.",
|
|
@@ -626,9 +577,7 @@ const TESTS = {
|
|
|
626
577
|
verdict_when_failed: PAPER
|
|
627
578
|
},
|
|
628
579
|
|
|
629
|
-
// ---------------------------------------------------------------------
|
|
630
580
|
// VEX
|
|
631
|
-
// ---------------------------------------------------------------------
|
|
632
581
|
'VEX-CSAF-v2.1': {
|
|
633
582
|
claim: "We publish VEX statements via OASIS CSAF 2.1 for our products.",
|
|
634
583
|
test: "Pull the published CSAF 2.1 documents. Confirm AI-component identifier scheme presence (model + version + adapters + tokenizer). Confirm at least one VEX statement covers an AI-class vulnerability (jailbreak, prompt injection, embedding inversion). Confirm chaining of base-model VEX statements to derived-model VEX statements where applicable. Theater verdict if AI components are absent from the identifier scheme, or if no AI-class VEX statements exist despite AI components shipping.",
|
|
@@ -636,9 +585,7 @@ const TESTS = {
|
|
|
636
585
|
verdict_when_failed: PAPER
|
|
637
586
|
},
|
|
638
587
|
|
|
639
|
-
// ---------------------------------------------------------------------
|
|
640
588
|
// FCC / Telecom
|
|
641
|
-
// ---------------------------------------------------------------------
|
|
642
589
|
'FCC-CPNI-4.1': {
|
|
643
590
|
claim: "Our annual CPNI certification satisfies FCC CPNI obligations.",
|
|
644
591
|
test: "Confirm quarterly LI-gateway activation auditing (Salt-Typhoon/PRC threat model). Confirm gNB firmware hash attestation and signaling-anomaly baselines per PLMN-pair. Pull the most recent CPNI certification; confirm those operational artefacts are referenced. Theater verdict if certification is annual-only without LI-gateway/firmware-hash/signaling artefacts.",
|
|
@@ -676,9 +623,7 @@ const TESTS = {
|
|
|
676
623
|
verdict_when_failed: PAPER
|
|
677
624
|
},
|
|
678
625
|
|
|
679
|
-
// ---------------------------------------------------------------------
|
|
680
626
|
// Federated identity / IdP
|
|
681
|
-
// ---------------------------------------------------------------------
|
|
682
627
|
'NIST-800-53-IA-5-Federated': {
|
|
683
628
|
claim: "Our IA-5 authenticator management covers federated identity providers.",
|
|
684
629
|
test: "Inspect IdP control-plane: continuous attestation of token-signing certificate fingerprints, claim-transformation rule baseline with per-modification change-control attestation, management-API-token inventory with TTL + scope + source-IP enforcement. Theater verdict if attestation is snapshot-only (quarterly) rather than continuous, or if management-API tokens lack TTL/scope/source-IP enforcement.",
|
|
@@ -734,9 +679,7 @@ const TESTS = {
|
|
|
734
679
|
verdict_when_failed: PAPER
|
|
735
680
|
},
|
|
736
681
|
|
|
737
|
-
// ---------------------------------------------------------------------
|
|
738
682
|
// Ransomware playbook entries (RANSOMWARE-GAP-*)
|
|
739
|
-
// ---------------------------------------------------------------------
|
|
740
683
|
'OFAC-SDN-Payment-Block': {
|
|
741
684
|
claim: "Our incident response covers OFAC sanctions screening before any ransomware payment.",
|
|
742
685
|
test: "Run a tabletop where the inject is a ransomware demand from an attribution-likely-sanctioned actor. Stopwatch the workflow: attribution-evidence package assembled → cross-jurisdiction lookup (OFAC SDN + EU 2014/833 + UK OFSI + AU DFAT + JP MOF) → counsel-signed attestation → pay/restore decision. Theater verdict if any cross-jurisdiction list is missing, counsel-signed attestation is unrehearsed, or the tabletop has not been exercised in the past 12 months.",
|
|
@@ -796,8 +739,8 @@ function backfill() {
|
|
|
796
739
|
process.exit(2);
|
|
797
740
|
}
|
|
798
741
|
|
|
799
|
-
//
|
|
800
|
-
//
|
|
742
|
+
// Two-space indent and a trailing newline, matching the catalog on disk, so
|
|
743
|
+
// the rewrite diffs only where a theater_test landed.
|
|
801
744
|
const out = JSON.stringify(data, null, 2) + '\n';
|
|
802
745
|
fs.writeFileSync(CATALOG_PATH, out);
|
|
803
746
|
console.log(`Updated ${updated}/${keys.length} entries with theater_test.`);
|