@blamejs/exceptd-skills 0.12.26 → 0.12.27
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 +38 -0
- package/bin/exceptd.js +73 -1
- package/data/_indexes/_meta.json +2 -2
- package/lib/flag-suggest.js +4 -0
- package/lib/playbook-runner.js +117 -10
- package/manifest-snapshot.json +9 -2
- package/manifest-snapshot.sha256 +1 -1
- package/manifest.json +41 -41
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.12.27 — 2026-05-15
|
|
4
|
+
|
|
5
|
+
**Patch: opt-in `--bundle-deterministic` mode for reproducible CSAF + OpenVEX + close-envelope bytes. Closes cycle 6 III P2-E + cycle 7 CCC bundle-non-determinism finding.**
|
|
6
|
+
|
|
7
|
+
### New flags
|
|
8
|
+
|
|
9
|
+
- **`--bundle-deterministic`** (boolean, off by default) — when set, the bundle-emit path produces byte-stable output for the same inputs. CSAF `tracking.initial_release_date` / `current_release_date` / `generator.date` / `revision_history[0].date`, OpenVEX top-level `timestamp` + per-statement `timestamp`, close-envelope `acceptance_date` + `regression_schedule.next_run` + `generated_at` all freeze to a single epoch. Auto-generated session IDs derive deterministically from `sha256(playbook_id ∥ evidence_hash ∥ engine_version)` rather than `crypto.randomBytes`. CSAF `vulnerabilities[]` + OpenVEX `statements[]` arrays sort by primary id.
|
|
10
|
+
- **`--bundle-epoch <ISO-8601>`** (value-bearing, optional) — operator-supplied freeze epoch. When omitted, the deterministic mode falls back to `playbook._meta.last_threat_review` (the canonical "this catalog was last reviewed at" timestamp). Honored only when `--bundle-deterministic` is set.
|
|
11
|
+
|
|
12
|
+
Both flags wired for `run`, `ci`, `run-all`, `ai-run`, `ingest`. Per-verb help blocks document them.
|
|
13
|
+
|
|
14
|
+
### Why
|
|
15
|
+
|
|
16
|
+
- **CI bundle diffing**: `git diff` over `evidence_package.bundle_body` against a baseline becomes signal-bearing only when drift is signal, not noise. Pre-v0.12.27 the same evidence produced ~640 bytes of timestamp drift across CSAF + OpenVEX + close-envelope per run.
|
|
17
|
+
- **Auditor evidence reuse**: ISO 27001 / SOC 2 audits expect re-emit against the same submission to produce byte-equal evidence.
|
|
18
|
+
- **SLSA / Sigstore alignment**: reproducible build evidence requires deterministic outputs the verifier can hash and compare.
|
|
19
|
+
|
|
20
|
+
CSAF 2.0 §3.1.11.2-5 permits identical `initial_release_date` / `current_release_date` for never-revised advisories; freezing to a catalog epoch is spec-compliant. The strict-validator pass (BSI CSAF Validator) accepts the deterministic-mode output unchanged.
|
|
21
|
+
|
|
22
|
+
### Default-mode regression guard
|
|
23
|
+
|
|
24
|
+
When neither flag is set, bundle output is byte-identical to v0.12.26 — no existing operator sees a behavioral change. A regression test pins this: two consecutive runs in default mode produce different CSAF `tracking.initial_release_date` values, asserting the determinism is opt-in and cannot accidentally activate.
|
|
25
|
+
|
|
26
|
+
### Test coverage
|
|
27
|
+
|
|
28
|
+
`tests/bundle-determinism.test.js` (new, 7 exact-code tests):
|
|
29
|
+
1. Two runs same inputs + same epoch → byte-identical CSAF/OpenVEX/summary
|
|
30
|
+
2. Different `--bundle-epoch` → bundles differ only in timestamp fields
|
|
31
|
+
3. Different evidence → bundles differ in `vulnerabilities[]` length; timestamps frozen
|
|
32
|
+
4. Default mode → regression-guard timestamp drift
|
|
33
|
+
5. `--bundle-epoch invalid-iso` → exit 1 + structured error
|
|
34
|
+
6. `--bundle-deterministic` without `--bundle-epoch` falls back to `playbook._meta.last_threat_review`
|
|
35
|
+
7. Array sort: random-order CVE evidence → `vulnerabilities[]` always ascending by `cve_id`
|
|
36
|
+
|
|
37
|
+
Existing CSAF + OpenVEX + CLI test suites pass unchanged (53/53 + 30/30; no default-mode regression).
|
|
38
|
+
|
|
39
|
+
Test count: 1058 pass (5 skipped). Predeploy gates: 14/14. Skills: 39/39 signed.
|
|
40
|
+
|
|
3
41
|
## 0.12.26 — 2026-05-15
|
|
4
42
|
|
|
5
43
|
**Patch: sector-telecom skill ships, with supporting framework-gap and ATLAS catalog scaffolding. Closes the cycle 8 LLL P1 finding that the unmodeled RWEP signal from Salt Typhoon-class campaigns was the highest gap in the catalog.**
|
package/bin/exceptd.js
CHANGED
|
@@ -909,6 +909,11 @@ function dispatchPlaybook(cmd, argv) {
|
|
|
909
909
|
"force-overwrite", "no-stream", "block-on-jurisdiction-clock",
|
|
910
910
|
"force-replay",
|
|
911
911
|
"json-stdout-only", "fix", "human", "json", "strict-preconditions",
|
|
912
|
+
// v0.12.27: --bundle-deterministic opts the bundle build into
|
|
913
|
+
// byte-stable output (frozen timestamps, deterministic session_id
|
|
914
|
+
// fallback, sorted vulnerabilities[] / statements[]). Pairs with
|
|
915
|
+
// --bundle-epoch <ISO> for the frozen timestamp value.
|
|
916
|
+
"bundle-deterministic",
|
|
912
917
|
// v0.12.9: doctor --shipped-tarball runs the verify-shipped-tarball
|
|
913
918
|
// gate alongside --signatures. doctor --registry-check + --signatures
|
|
914
919
|
// were already accepted; explicit registration removes the silent
|
|
@@ -1266,6 +1271,55 @@ function dispatchPlaybook(cmd, argv) {
|
|
|
1266
1271
|
runOpts.csafStatus = cs;
|
|
1267
1272
|
}
|
|
1268
1273
|
|
|
1274
|
+
// --bundle-deterministic + --bundle-epoch (v0.12.27): opt-in deterministic
|
|
1275
|
+
// bundle emit. When set, CSAF / OpenVEX / close-envelope timestamps freeze
|
|
1276
|
+
// to the supplied epoch (or the playbook's last_threat_review fallback),
|
|
1277
|
+
// the auto-generated session_id derives from sha256(playbook + evidence_hash
|
|
1278
|
+
// + engine_version) when the operator did not pass --session-id, and
|
|
1279
|
+
// vulnerabilities[] / statements[] sort deterministically. Opt-in so the
|
|
1280
|
+
// default emit path stays byte-identical to pre-v0.12.27 output.
|
|
1281
|
+
if (args["bundle-deterministic"] !== undefined && args["bundle-deterministic"] !== false) {
|
|
1282
|
+
if (!BUNDLE_FLAG_RELEVANT_VERBS.has(cmd)) {
|
|
1283
|
+
return emitError(
|
|
1284
|
+
`${cmd}: --bundle-deterministic is irrelevant on this verb (no bundle is assembled). --bundle-deterministic only applies to verbs that drive phases 5-7: ${[...BUNDLE_FLAG_RELEVANT_VERBS].sort().join(", ")}.`,
|
|
1285
|
+
{ verb: cmd, flag: "bundle-deterministic", error_class: "irrelevant-flag", accepted_verbs: [...BUNDLE_FLAG_RELEVANT_VERBS].sort() },
|
|
1286
|
+
pretty
|
|
1287
|
+
);
|
|
1288
|
+
}
|
|
1289
|
+
runOpts.bundleDeterministic = true;
|
|
1290
|
+
}
|
|
1291
|
+
if (args["bundle-epoch"] !== undefined) {
|
|
1292
|
+
if (!BUNDLE_FLAG_RELEVANT_VERBS.has(cmd)) {
|
|
1293
|
+
return emitError(
|
|
1294
|
+
`${cmd}: --bundle-epoch is irrelevant on this verb (no bundle is assembled). --bundle-epoch only applies to verbs that drive phases 5-7: ${[...BUNDLE_FLAG_RELEVANT_VERBS].sort().join(", ")}.`,
|
|
1295
|
+
{ verb: cmd, flag: "bundle-epoch", error_class: "irrelevant-flag", accepted_verbs: [...BUNDLE_FLAG_RELEVANT_VERBS].sort() },
|
|
1296
|
+
pretty
|
|
1297
|
+
);
|
|
1298
|
+
}
|
|
1299
|
+
const epoch = args["bundle-epoch"];
|
|
1300
|
+
if (typeof epoch !== "string") {
|
|
1301
|
+
return emitError(
|
|
1302
|
+
`${cmd}: --bundle-epoch must be a string ISO-8601 timestamp.`,
|
|
1303
|
+
{ verb: cmd, flag: "bundle-epoch", provided: typeof epoch },
|
|
1304
|
+
pretty
|
|
1305
|
+
);
|
|
1306
|
+
}
|
|
1307
|
+
// Reuse validateIsoSince — the same calendar-shape gate used for --since.
|
|
1308
|
+
const isoErr = validateIsoSince(epoch);
|
|
1309
|
+
if (isoErr) {
|
|
1310
|
+
return emitError(
|
|
1311
|
+
`${cmd}: --bundle-epoch must be a parseable ISO-8601 calendar timestamp (e.g. 2026-01-01T00:00:00Z). Got: ${JSON.stringify(epoch).slice(0, 80)}`,
|
|
1312
|
+
{ verb: cmd, flag: "bundle-epoch", provided: epoch.slice(0, 80) },
|
|
1313
|
+
pretty
|
|
1314
|
+
);
|
|
1315
|
+
}
|
|
1316
|
+
// Normalise to a full ISO timestamp so downstream consumers don't have
|
|
1317
|
+
// to handle the date-only shape. Date-only inputs render as
|
|
1318
|
+
// YYYY-MM-DDT00:00:00.000Z; full timestamps round-trip unchanged modulo
|
|
1319
|
+
// ms precision (Date.prototype.toISOString always emits ms).
|
|
1320
|
+
runOpts.bundleEpoch = new Date(epoch).toISOString();
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1269
1323
|
// --ack: operator acknowledges the jurisdiction obligations surfaced by
|
|
1270
1324
|
// govern. Captured in attestation; downstream tooling can check whether
|
|
1271
1325
|
// consent was explicit vs. implicit. AGENTS.md says the AI should surface
|
|
@@ -1512,6 +1566,16 @@ Flags:
|
|
|
1512
1566
|
publisher trust anchor — i.e. the operator's
|
|
1513
1567
|
organisation, NOT the tooling vendor. Must be an
|
|
1514
1568
|
http://… or https://… URL, ≤256 chars.
|
|
1569
|
+
--bundle-deterministic Emit byte-stable CSAF / OpenVEX / close envelope.
|
|
1570
|
+
Freezes tracking + timestamp fields to a single
|
|
1571
|
+
epoch, derives session_id from evidence hash when
|
|
1572
|
+
not supplied via --session-id, and sorts
|
|
1573
|
+
vulnerabilities[] / statements[] ascending.
|
|
1574
|
+
Off by default; opt-in for reproducible-build
|
|
1575
|
+
pipelines + diff-friendly attestation review.
|
|
1576
|
+
--bundle-epoch <ISO> Frozen epoch for --bundle-deterministic. ISO-8601
|
|
1577
|
+
calendar timestamp (date or date+time). Falls back
|
|
1578
|
+
to the playbook's last_threat_review when omitted.
|
|
1515
1579
|
--diff-from-latest Compare evidence_hash against the most recent prior
|
|
1516
1580
|
attestation for the same playbook in
|
|
1517
1581
|
.exceptd/attestations/. Emits status: unchanged | drifted.
|
|
@@ -1589,6 +1653,8 @@ Flags:
|
|
|
1589
1653
|
CSAF document.publisher.namespace (§3.1.7.4). The
|
|
1590
1654
|
operator's organisation URL, NOT the tooling vendor.
|
|
1591
1655
|
Must be an http://… or https://… URL, ≤256 chars.
|
|
1656
|
+
--bundle-deterministic Emit byte-stable bundles (frozen timestamps).
|
|
1657
|
+
--bundle-epoch <ISO> Frozen epoch for --bundle-deterministic.
|
|
1592
1658
|
--pretty Indented JSON output.
|
|
1593
1659
|
|
|
1594
1660
|
Exit codes: 0 PASS, 1 framework, 4 blocked, 7 SESSION_ID_COLLISION,
|
|
@@ -1716,6 +1782,8 @@ Flags:
|
|
|
1716
1782
|
CSAF document.publisher.namespace (§3.1.7.4). The
|
|
1717
1783
|
operator's organisation URL, NOT the tooling vendor.
|
|
1718
1784
|
Must be an http://… or https://… URL, ≤256 chars.
|
|
1785
|
+
--bundle-deterministic Emit byte-stable bundles for reproducible pipelines.
|
|
1786
|
+
--bundle-epoch <ISO> Frozen epoch for --bundle-deterministic.
|
|
1719
1787
|
--evidence <file|-> Single-shot mode: pre-supplied submission JSON.
|
|
1720
1788
|
--operator <name> Bind the attestation to a specific identity.
|
|
1721
1789
|
--ack Mark explicit operator consent (jurisdiction clock).
|
|
@@ -1794,6 +1862,8 @@ Flags:
|
|
|
1794
1862
|
--publisher-namespace <url>
|
|
1795
1863
|
CSAF document.publisher.namespace (§3.1.7.4). The
|
|
1796
1864
|
operator's organisation URL, NOT the tooling vendor.
|
|
1865
|
+
--bundle-deterministic Emit byte-stable bundles across per-playbook runs.
|
|
1866
|
+
--bundle-epoch <ISO> Frozen epoch for --bundle-deterministic.
|
|
1797
1867
|
--json Force single-line JSON (overrides any TTY heuristics).
|
|
1798
1868
|
--pretty Indented JSON output (implies --json).
|
|
1799
1869
|
|
|
@@ -1874,7 +1944,9 @@ Flags (selected — see \`exceptd run --help\` for the full list):
|
|
|
1874
1944
|
--publisher-namespace <url>
|
|
1875
1945
|
CSAF document.publisher.namespace (§3.1.7.4). The
|
|
1876
1946
|
operator's organisation URL, NOT the tooling vendor.
|
|
1877
|
-
Must be an http://… or https://… URL, ≤256 chars
|
|
1947
|
+
Must be an http://… or https://… URL, ≤256 chars.
|
|
1948
|
+
--bundle-deterministic Emit byte-stable bundles across the multi-run set.
|
|
1949
|
+
--bundle-epoch <ISO> Frozen epoch for --bundle-deterministic.`,
|
|
1878
1950
|
};
|
|
1879
1951
|
process.stdout.write((cmds[verb] || `${verb} — no per-verb help available; see \`exceptd help\` for the full list.`) + "\n");
|
|
1880
1952
|
}
|
package/data/_indexes/_meta.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema_version": "1.1.0",
|
|
3
|
-
"generated_at": "2026-05-15T22:
|
|
3
|
+
"generated_at": "2026-05-15T22:38:59.213Z",
|
|
4
4
|
"generator": "scripts/build-indexes.js",
|
|
5
5
|
"source_count": 51,
|
|
6
6
|
"source_hashes": {
|
|
7
|
-
"manifest.json": "
|
|
7
|
+
"manifest.json": "9862095ee05729021d2dd51765c370ed24377e73c536b237817ef7ce4a7ba437",
|
|
8
8
|
"data/atlas-ttps.json": "db52a797f6ba7c9a61fd7b1225ebbc268ddf21abe29a106c4246c2ed2e617b86",
|
|
9
9
|
"data/attack-techniques.json": "6b45448aa42cc6664376c93da73356624708e935c12589ee8c776a10215bce3a",
|
|
10
10
|
"data/cve-catalog.json": "a2acad16f5e3856b07019fa00110e9dcb38ec5cc71b318d0e164bfcba7f4f644",
|
package/lib/flag-suggest.js
CHANGED
|
@@ -79,21 +79,25 @@ const VERB_FLAG_ALLOWLIST = Object.freeze({
|
|
|
79
79
|
'mode', 'air-gap', 'force-stale', 'operator', 'ack', 'csaf-status',
|
|
80
80
|
'publisher-namespace', 'vex', 'all', 'scope', 'required', 'format',
|
|
81
81
|
'strict-preconditions', 'block-on-jurisdiction-clock', 'tlp',
|
|
82
|
+
'bundle-deterministic', 'bundle-epoch',
|
|
82
83
|
],
|
|
83
84
|
'run-all': [
|
|
84
85
|
'evidence', 'evidence-dir', 'session-id', 'force-overwrite', 'attestation-root',
|
|
85
86
|
'mode', 'air-gap', 'force-stale', 'operator', 'ack', 'csaf-status',
|
|
86
87
|
'publisher-namespace', 'vex', 'scope', 'strict-preconditions', 'tlp',
|
|
88
|
+
'bundle-deterministic', 'bundle-epoch',
|
|
87
89
|
],
|
|
88
90
|
'ai-run': [
|
|
89
91
|
'evidence', 'no-stream', 'session-id', 'force-overwrite', 'attestation-root',
|
|
90
92
|
'operator', 'ack', 'csaf-status', 'publisher-namespace', 'air-gap',
|
|
91
93
|
'mode', 'force-stale', 'tlp',
|
|
94
|
+
'bundle-deterministic', 'bundle-epoch',
|
|
92
95
|
],
|
|
93
96
|
ingest: [
|
|
94
97
|
'evidence', 'session-id', 'force-overwrite', 'attestation-root', 'operator',
|
|
95
98
|
'ack', 'csaf-status', 'publisher-namespace', 'air-gap', 'force-stale',
|
|
96
99
|
'strict-preconditions',
|
|
100
|
+
'bundle-deterministic', 'bundle-epoch',
|
|
97
101
|
],
|
|
98
102
|
brief: ['all', 'scope', 'directives', 'flat', 'phase'],
|
|
99
103
|
discover: ['scan-only', 'scope'],
|
package/lib/playbook-runner.js
CHANGED
|
@@ -1515,6 +1515,13 @@ function close(playbookId, directiveId, analyzeResult, validateResult, agentSign
|
|
|
1515
1515
|
// bypass run() (e.g. unit tests).
|
|
1516
1516
|
const sessionId = runOpts.session_id || crypto.randomBytes(8).toString('hex');
|
|
1517
1517
|
|
|
1518
|
+
// v0.12.27: when opt-in deterministic bundle mode is set, resolve the
|
|
1519
|
+
// single frozen epoch used by every timestamp surface below. Cached for
|
|
1520
|
+
// the whole close() call so notification_actions, regression_schedule,
|
|
1521
|
+
// and the bundle emitter all agree on the same Date.
|
|
1522
|
+
const deterministic = runOpts.bundleDeterministic === true;
|
|
1523
|
+
const frozenEpoch = deterministic ? resolveFrozenEpoch(runOpts, playbook) : null;
|
|
1524
|
+
|
|
1518
1525
|
// notification_actions — compute ISO deadlines from clock_starts events.
|
|
1519
1526
|
// v0.11.12 (#123): enrich each entry with the matched obligation's
|
|
1520
1527
|
// jurisdiction/regulation/window_hours/evidence_required fields. The
|
|
@@ -1605,7 +1612,10 @@ function close(playbookId, directiveId, analyzeResult, validateResult, agentSign
|
|
|
1605
1612
|
framework_id: playbook.domain.frameworks_in_scope[0] || 'unspecified',
|
|
1606
1613
|
control_id: analyzeResult.framework_gap_mapping?.[0]?.claimed_control || 'unspecified',
|
|
1607
1614
|
ciso_name: agentSignals.ciso_name || '<CISO NAME>',
|
|
1608
|
-
|
|
1615
|
+
// v0.12.27: deterministic mode roots acceptance_date in the
|
|
1616
|
+
// frozen epoch so two runs against the same evidence emit the
|
|
1617
|
+
// same auditor-facing date.
|
|
1618
|
+
acceptance_date: (deterministic ? frozenEpoch : new Date().toISOString()).slice(0, 10),
|
|
1609
1619
|
duration_expiry: agentSignals.duration_expiry || 'until vendor patch'
|
|
1610
1620
|
})
|
|
1611
1621
|
};
|
|
@@ -1628,7 +1638,11 @@ function close(playbookId, directiveId, analyzeResult, validateResult, agentSign
|
|
|
1628
1638
|
// spurious millisecond drift on tracking.initial_release_date /
|
|
1629
1639
|
// timestamp / current_release_date.
|
|
1630
1640
|
const evidencePackage = c.evidence_package ? (() => {
|
|
1631
|
-
|
|
1641
|
+
// v0.12.27: deterministic mode pins issuedAt to the frozen epoch so
|
|
1642
|
+
// CSAF tracking.{initial_release_date,current_release_date,
|
|
1643
|
+
// generator.date,revision_history[0].date} and OpenVEX timestamp +
|
|
1644
|
+
// statements[].timestamp all collapse to a single, byte-stable value.
|
|
1645
|
+
const issuedAt = deterministic ? frozenEpoch : new Date().toISOString();
|
|
1632
1646
|
const builtFormats = new Map();
|
|
1633
1647
|
const buildOnce = (format) => {
|
|
1634
1648
|
if (!builtFormats.has(format)) {
|
|
@@ -1680,11 +1694,27 @@ function close(playbookId, directiveId, analyzeResult, validateResult, agentSign
|
|
|
1680
1694
|
} : { enabled: false };
|
|
1681
1695
|
|
|
1682
1696
|
// regression_schedule
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1697
|
+
//
|
|
1698
|
+
// v0.12.27: deterministic mode re-derives next_run from the frozen epoch
|
|
1699
|
+
// rather than wall-clock-now-at-validate-time. Without this, two runs
|
|
1700
|
+
// against the same evidence diverge on next_run by the interval between
|
|
1701
|
+
// the two `validate()` invocations. Frozen base + the same interval set
|
|
1702
|
+
// = byte-identical schedule.
|
|
1703
|
+
const regressionSchedule = c.regression_schedule ? (() => {
|
|
1704
|
+
let nextRun = validateResult.regression_next_run;
|
|
1705
|
+
if (deterministic) {
|
|
1706
|
+
// Re-derive against the validate phase's trigger set (not the
|
|
1707
|
+
// close phase's regression_schedule subtree — close has no triggers
|
|
1708
|
+
// of its own, just the canonical interval declared upstream).
|
|
1709
|
+
const v = resolvedPhase(playbook, directiveId, 'validate');
|
|
1710
|
+
nextRun = frozenRegressionNextRun(v.regression_trigger || [], new Date(frozenEpoch));
|
|
1711
|
+
}
|
|
1712
|
+
return {
|
|
1713
|
+
next_run: nextRun,
|
|
1714
|
+
trigger: c.regression_schedule.trigger,
|
|
1715
|
+
notify_on_skip: c.regression_schedule.notify_on_skip !== false
|
|
1716
|
+
};
|
|
1717
|
+
})() : null;
|
|
1688
1718
|
|
|
1689
1719
|
// feeds_into chaining — full analyze result is exposed so conditions can
|
|
1690
1720
|
// reference `analyze.compliance_theater_check.verdict` etc.
|
|
@@ -1996,6 +2026,40 @@ function getEngineVersion() {
|
|
|
1996
2026
|
return _CACHED_PKG_VERSION;
|
|
1997
2027
|
}
|
|
1998
2028
|
|
|
2029
|
+
// v0.12.27: deterministic-bundle epoch resolution. Priority:
|
|
2030
|
+
// 1. runOpts.bundleEpoch (operator-supplied --bundle-epoch <ISO>)
|
|
2031
|
+
// 2. playbook._meta.last_threat_review (the freshness anchor that already
|
|
2032
|
+
// gates every shipped playbook — stable across re-runs of the same
|
|
2033
|
+
// catalog version)
|
|
2034
|
+
// 3. '1970-01-01T00:00:00Z' fallback (effectively impossible in practice
|
|
2035
|
+
// because every shipped playbook carries last_threat_review, but
|
|
2036
|
+
// guarantees the deterministic path never crashes on a malformed
|
|
2037
|
+
// playbook).
|
|
2038
|
+
// Returns a full ISO-8601 timestamp (date-only inputs are normalised).
|
|
2039
|
+
function resolveFrozenEpoch(runOpts, playbook) {
|
|
2040
|
+
const raw = runOpts && runOpts.bundleEpoch
|
|
2041
|
+
? runOpts.bundleEpoch
|
|
2042
|
+
: (playbook && playbook._meta && playbook._meta.last_threat_review)
|
|
2043
|
+
|| '1970-01-01T00:00:00Z';
|
|
2044
|
+
try { return new Date(raw).toISOString(); }
|
|
2045
|
+
catch { return '1970-01-01T00:00:00Z'; }
|
|
2046
|
+
}
|
|
2047
|
+
|
|
2048
|
+
// Recompute regression_schedule.next_run against a frozen `now` so two
|
|
2049
|
+
// deterministic-mode runs of the same playbook produce byte-identical
|
|
2050
|
+
// schedules. Mirrors computeRegressionNextRun but with an injected base
|
|
2051
|
+
// date. Returns the soonest ISO timestamp or null when no interval-based
|
|
2052
|
+
// trigger fired.
|
|
2053
|
+
function frozenRegressionNextRun(triggers, frozenNow) {
|
|
2054
|
+
let soonest = null;
|
|
2055
|
+
for (const t of (triggers || [])) {
|
|
2056
|
+
const parsed = parseInterval(t.interval, frozenNow);
|
|
2057
|
+
if (!parsed || !parsed.date) continue;
|
|
2058
|
+
if (!soonest || parsed.date < soonest) soonest = parsed.date;
|
|
2059
|
+
}
|
|
2060
|
+
return soonest ? soonest.toISOString() : null;
|
|
2061
|
+
}
|
|
2062
|
+
|
|
1999
2063
|
// Operator-supplied identity strings (--operator) and publisher namespace
|
|
2000
2064
|
// URLs (--publisher-namespace) flow into operator-facing CSAF surfaces.
|
|
2001
2065
|
// Strip ASCII control characters as defence in depth — bin/exceptd.js
|
|
@@ -2410,7 +2474,19 @@ function buildEvidenceBundle(format, playbook, analyze, validate, agentSignals,
|
|
|
2410
2474
|
if (branches.length > 0) tree.branches = branches;
|
|
2411
2475
|
return tree;
|
|
2412
2476
|
})(),
|
|
2413
|
-
vulnerabilities:
|
|
2477
|
+
vulnerabilities: (function () {
|
|
2478
|
+
// v0.12.27: deterministic mode sorts vulnerabilities[] by their
|
|
2479
|
+
// primary identifier (cve_id for CVE entries, ids[0].text otherwise)
|
|
2480
|
+
// ascending. Default mode preserves insertion order so existing
|
|
2481
|
+
// operators see byte-identical output to pre-v0.12.27.
|
|
2482
|
+
const all = [...cveVulns, ...indicatorVulns];
|
|
2483
|
+
if (runOpts && runOpts.bundleDeterministic === true) {
|
|
2484
|
+
const keyOf = (v) => (typeof v.cve === 'string' && v.cve)
|
|
2485
|
+
|| (Array.isArray(v.ids) && v.ids[0] && typeof v.ids[0].text === 'string' ? v.ids[0].text : '');
|
|
2486
|
+
return all.slice().sort((a, b) => keyOf(a).localeCompare(keyOf(b)));
|
|
2487
|
+
}
|
|
2488
|
+
return all;
|
|
2489
|
+
})(),
|
|
2414
2490
|
exceptd_extension: {
|
|
2415
2491
|
classification: analyze._detect_classification,
|
|
2416
2492
|
rwep: analyze.rwep,
|
|
@@ -2642,7 +2718,17 @@ function buildEvidenceBundle(format, playbook, analyze, validate, agentSignals,
|
|
|
2642
2718
|
author: 'exceptd',
|
|
2643
2719
|
timestamp: issued,
|
|
2644
2720
|
version: 1,
|
|
2645
|
-
statements:
|
|
2721
|
+
statements: (function () {
|
|
2722
|
+
// v0.12.27: deterministic mode sorts statements[] by
|
|
2723
|
+
// vulnerability['@id'] ascending. Insertion order otherwise.
|
|
2724
|
+
const all = [...cveStatements, ...indicatorStatements];
|
|
2725
|
+
if (runOpts && runOpts.bundleDeterministic === true) {
|
|
2726
|
+
const keyOf = (s) => (s && s.vulnerability && typeof s.vulnerability['@id'] === 'string')
|
|
2727
|
+
? s.vulnerability['@id'] : '';
|
|
2728
|
+
return all.slice().sort((a, b) => keyOf(a).localeCompare(keyOf(b)));
|
|
2729
|
+
}
|
|
2730
|
+
return all;
|
|
2731
|
+
})(),
|
|
2646
2732
|
};
|
|
2647
2733
|
}
|
|
2648
2734
|
|
|
@@ -2948,7 +3034,28 @@ function run(playbookId, directiveId, agentSubmission = {}, runOpts = {}) {
|
|
|
2948
3034
|
// Without the single-source-of-truth, close() would mint its own id
|
|
2949
3035
|
// and operators correlating attestation files to embedded bundle URNs
|
|
2950
3036
|
// would see mismatches.
|
|
2951
|
-
|
|
3037
|
+
//
|
|
3038
|
+
// v0.12.27: when runOpts.bundleDeterministic is set AND the operator did
|
|
3039
|
+
// not pass --session-id, derive the session_id from the submission shape
|
|
3040
|
+
// so two runs against identical evidence produce the same id (and
|
|
3041
|
+
// therefore the same CSAF tracking.id / OpenVEX @id / attestation file
|
|
3042
|
+
// name). Mirrors the evidence_hash path further down but is computed
|
|
3043
|
+
// here so close() can thread it through. Operator-supplied --session-id
|
|
3044
|
+
// still wins on collision.
|
|
3045
|
+
let sessionId;
|
|
3046
|
+
if (runOpts.session_id) {
|
|
3047
|
+
sessionId = runOpts.session_id;
|
|
3048
|
+
} else if (runOpts.bundleDeterministic) {
|
|
3049
|
+
const submissionDigest = crypto.createHash('sha256')
|
|
3050
|
+
.update(canonicalStringify(extractSubmissionForHash(agentSubmission)))
|
|
3051
|
+
.digest('hex');
|
|
3052
|
+
sessionId = crypto.createHash('sha256')
|
|
3053
|
+
.update(`${playbookId}\0${submissionDigest}\0${getEngineVersion()}`)
|
|
3054
|
+
.digest('hex')
|
|
3055
|
+
.slice(0, 16);
|
|
3056
|
+
} else {
|
|
3057
|
+
sessionId = crypto.randomBytes(8).toString('hex');
|
|
3058
|
+
}
|
|
2952
3059
|
const cachedRunOpts = { ...runOpts, _playbookCache: playbook, session_id: sessionId };
|
|
2953
3060
|
// Run-time error accumulator for evalCondition regex failures and other
|
|
2954
3061
|
// non-fatal anomalies surfaced into analyze.runtime_errors[].
|
package/manifest-snapshot.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_comment": "Auto-generated by scripts/refresh-manifest-snapshot.js — do not hand-edit. Public skill surface used by check-manifest-snapshot.js to detect breaking removals.",
|
|
3
|
-
"_generated_at": "2026-05-15T22:
|
|
3
|
+
"_generated_at": "2026-05-15T22:38:13.114Z",
|
|
4
4
|
"atlas_version": "5.1.0",
|
|
5
5
|
"skill_count": 39,
|
|
6
6
|
"skills": [
|
|
@@ -1570,7 +1570,14 @@
|
|
|
1570
1570
|
"uk tsa 2021",
|
|
1571
1571
|
"volt typhoon"
|
|
1572
1572
|
],
|
|
1573
|
-
"data_deps": [
|
|
1573
|
+
"data_deps": [
|
|
1574
|
+
"atlas-ttps.json",
|
|
1575
|
+
"cve-catalog.json",
|
|
1576
|
+
"cwe-catalog.json",
|
|
1577
|
+
"d3fend-catalog.json",
|
|
1578
|
+
"framework-control-gaps.json",
|
|
1579
|
+
"global-frameworks.json"
|
|
1580
|
+
],
|
|
1574
1581
|
"atlas_refs": [
|
|
1575
1582
|
"AML.T0040"
|
|
1576
1583
|
],
|
package/manifest-snapshot.sha256
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
259bbbc7ec375bfb21c2e8fe4c397cca265b33b357e19282d34acff932752237 manifest-snapshot.json
|
package/manifest.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "exceptd-security",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.27",
|
|
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",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
],
|
|
53
53
|
"last_threat_review": "2026-05-01",
|
|
54
54
|
"signature": "N6H4u/u1fCFE6f/3QVkAr2cumZvLNE+xYBC91CCxKoeaSKm5zqbwzb2mvFDk9XKUegUy5W6npLFGi75yxNMIAg==",
|
|
55
|
-
"signed_at": "2026-05-15T22:
|
|
55
|
+
"signed_at": "2026-05-15T22:38:12.653Z",
|
|
56
56
|
"cwe_refs": [
|
|
57
57
|
"CWE-125",
|
|
58
58
|
"CWE-362",
|
|
@@ -116,7 +116,7 @@
|
|
|
116
116
|
],
|
|
117
117
|
"last_threat_review": "2026-05-01",
|
|
118
118
|
"signature": "Xen6ojQGzT4AZUN/WtuQon+gT2UrJyX50nrZwEdxLw5aiz8gDaeMkWo/Bic+h4NFEF7MRd7uDTm0dvKgWnlRBA==",
|
|
119
|
-
"signed_at": "2026-05-15T22:
|
|
119
|
+
"signed_at": "2026-05-15T22:38:12.655Z",
|
|
120
120
|
"cwe_refs": [
|
|
121
121
|
"CWE-1039",
|
|
122
122
|
"CWE-1426",
|
|
@@ -179,7 +179,7 @@
|
|
|
179
179
|
],
|
|
180
180
|
"last_threat_review": "2026-05-01",
|
|
181
181
|
"signature": "IDhdamTvyWfnz7SvIMrVMz2cwLuiP2/Iw2iYHFNbI1O302XnrGyIVsJcoKZa5QFClBYPiABVt+yI5HEuLxMCBw==",
|
|
182
|
-
"signed_at": "2026-05-15T22:
|
|
182
|
+
"signed_at": "2026-05-15T22:38:12.655Z",
|
|
183
183
|
"cwe_refs": [
|
|
184
184
|
"CWE-22",
|
|
185
185
|
"CWE-345",
|
|
@@ -225,7 +225,7 @@
|
|
|
225
225
|
"framework_gaps": [],
|
|
226
226
|
"last_threat_review": "2026-05-01",
|
|
227
227
|
"signature": "cPRRTsNQT1MYR3cE5O3KdC4MB037EMc0fsMIbOyfOv16sR+DkiXmAhQOjlIC47HngHz3vhLI+rbqItN91VWpBg==",
|
|
228
|
-
"signed_at": "2026-05-15T22:
|
|
228
|
+
"signed_at": "2026-05-15T22:38:12.656Z"
|
|
229
229
|
},
|
|
230
230
|
{
|
|
231
231
|
"name": "compliance-theater",
|
|
@@ -256,7 +256,7 @@
|
|
|
256
256
|
],
|
|
257
257
|
"last_threat_review": "2026-05-01",
|
|
258
258
|
"signature": "79NrFMRsqGsipWeE5ETQSVICGO4BjTJYgyir+PSaNVFpkLqLcwZd8Dr1V7iwX0H0fXFL3WpPz35gtrYCEG32BQ==",
|
|
259
|
-
"signed_at": "2026-05-15T22:
|
|
259
|
+
"signed_at": "2026-05-15T22:38:12.656Z"
|
|
260
260
|
},
|
|
261
261
|
{
|
|
262
262
|
"name": "exploit-scoring",
|
|
@@ -285,7 +285,7 @@
|
|
|
285
285
|
],
|
|
286
286
|
"last_threat_review": "2026-05-01",
|
|
287
287
|
"signature": "O7YIzAOQtSCFD0pyUdF0otYy9xwksrRGCLnSw5aMMGOs0SYeYA1JsMX5XLxNOQJC8tURC21HgQc/yx22jLtvAw==",
|
|
288
|
-
"signed_at": "2026-05-15T22:
|
|
288
|
+
"signed_at": "2026-05-15T22:38:12.656Z"
|
|
289
289
|
},
|
|
290
290
|
{
|
|
291
291
|
"name": "rag-pipeline-security",
|
|
@@ -322,7 +322,7 @@
|
|
|
322
322
|
],
|
|
323
323
|
"last_threat_review": "2026-05-01",
|
|
324
324
|
"signature": "ai6ebp9pz7dBigm2rQvQ0SklhDZtHqP3exKtolbEBiN0shQScypJfDBaQN2J3aoOC4dZjjTgIZvGfWLmBxrxBA==",
|
|
325
|
-
"signed_at": "2026-05-15T22:
|
|
325
|
+
"signed_at": "2026-05-15T22:38:12.657Z",
|
|
326
326
|
"cwe_refs": [
|
|
327
327
|
"CWE-1395",
|
|
328
328
|
"CWE-1426"
|
|
@@ -379,7 +379,7 @@
|
|
|
379
379
|
],
|
|
380
380
|
"last_threat_review": "2026-05-01",
|
|
381
381
|
"signature": "BkDjyCF53MAATVfzERmIhEhi474eWloxD0qyw9Gvw+VFE8aH3pOi+yeCpc0kq0vHAVmAEszwxBKEcuLkJbmSBg==",
|
|
382
|
-
"signed_at": "2026-05-15T22:
|
|
382
|
+
"signed_at": "2026-05-15T22:38:12.657Z",
|
|
383
383
|
"d3fend_refs": [
|
|
384
384
|
"D3-CA",
|
|
385
385
|
"D3-CSPP",
|
|
@@ -414,7 +414,7 @@
|
|
|
414
414
|
"framework_gaps": [],
|
|
415
415
|
"last_threat_review": "2026-05-01",
|
|
416
416
|
"signature": "DxfXhSyoAGUo1emHh0uIIcg324ZreBYxmFdBDVAKOOuPmMlfN4RqNc/JGDSfVmMv5CjgYCUcSmkcYB0A5lk0Cg==",
|
|
417
|
-
"signed_at": "2026-05-15T22:
|
|
417
|
+
"signed_at": "2026-05-15T22:38:12.657Z",
|
|
418
418
|
"cwe_refs": [
|
|
419
419
|
"CWE-1188"
|
|
420
420
|
]
|
|
@@ -442,7 +442,7 @@
|
|
|
442
442
|
"framework_gaps": [],
|
|
443
443
|
"last_threat_review": "2026-05-01",
|
|
444
444
|
"signature": "rFQ82v+1oAHWixWcGwokKhjZHfXUf6N7EfSgldhQ5Jrbiy3kv5CIbnOCsI6zPWyErSnpKVeBFTabJXnzLrzDCQ==",
|
|
445
|
-
"signed_at": "2026-05-15T22:
|
|
445
|
+
"signed_at": "2026-05-15T22:38:12.658Z"
|
|
446
446
|
},
|
|
447
447
|
{
|
|
448
448
|
"name": "global-grc",
|
|
@@ -474,7 +474,7 @@
|
|
|
474
474
|
"framework_gaps": [],
|
|
475
475
|
"last_threat_review": "2026-05-01",
|
|
476
476
|
"signature": "7yVjZkanFMKDQqXdX4B/7oLc2Rz72xHC1zscYd8F/+e5UAbR7ikK8Bn5EKZt3aBEOhHPAviSQNCMxpZD9U00CA==",
|
|
477
|
-
"signed_at": "2026-05-15T22:
|
|
477
|
+
"signed_at": "2026-05-15T22:38:12.658Z"
|
|
478
478
|
},
|
|
479
479
|
{
|
|
480
480
|
"name": "zeroday-gap-learn",
|
|
@@ -501,7 +501,7 @@
|
|
|
501
501
|
"framework_gaps": [],
|
|
502
502
|
"last_threat_review": "2026-05-01",
|
|
503
503
|
"signature": "VlPR7yY39hEwDJYYKPgHAOeax9LU0X7eIrR8L7zMFJWS0SdKTalOXXJtD9GppByftnkYAAdryZ8tHQ/KWLtaBQ==",
|
|
504
|
-
"signed_at": "2026-05-15T22:
|
|
504
|
+
"signed_at": "2026-05-15T22:38:12.659Z"
|
|
505
505
|
},
|
|
506
506
|
{
|
|
507
507
|
"name": "pqc-first",
|
|
@@ -553,7 +553,7 @@
|
|
|
553
553
|
],
|
|
554
554
|
"last_threat_review": "2026-05-01",
|
|
555
555
|
"signature": "V+qn5FqUlETfsEjvvi6jZGuQdqLFtFejfgPA6KSYxSlBXBTbOBXP3BGk5S+ba9akIzgbKh1j9VGB1MqsIt56DA==",
|
|
556
|
-
"signed_at": "2026-05-15T22:
|
|
556
|
+
"signed_at": "2026-05-15T22:38:12.659Z",
|
|
557
557
|
"cwe_refs": [
|
|
558
558
|
"CWE-327"
|
|
559
559
|
],
|
|
@@ -600,7 +600,7 @@
|
|
|
600
600
|
],
|
|
601
601
|
"last_threat_review": "2026-05-01",
|
|
602
602
|
"signature": "WCNz19186cER1eEhCophTIbnL3ltS3FC98I1rfv463aRnuVxPB3sUlD9xHTbxTM2rUABhqKijhdkWiMh2uKxCQ==",
|
|
603
|
-
"signed_at": "2026-05-15T22:
|
|
603
|
+
"signed_at": "2026-05-15T22:38:12.659Z"
|
|
604
604
|
},
|
|
605
605
|
{
|
|
606
606
|
"name": "security-maturity-tiers",
|
|
@@ -637,7 +637,7 @@
|
|
|
637
637
|
],
|
|
638
638
|
"last_threat_review": "2026-05-01",
|
|
639
639
|
"signature": "zjq6ACAHD46xvhvQJKlrCPh5xDCuBuIWBI+QJB8RxcudpC7p7I1pqv+BY8DZdsAgU4tquCU8KC+xlduMIk3/DQ==",
|
|
640
|
-
"signed_at": "2026-05-15T22:
|
|
640
|
+
"signed_at": "2026-05-15T22:38:12.660Z",
|
|
641
641
|
"cwe_refs": [
|
|
642
642
|
"CWE-1188"
|
|
643
643
|
]
|
|
@@ -672,7 +672,7 @@
|
|
|
672
672
|
"framework_gaps": [],
|
|
673
673
|
"last_threat_review": "2026-05-11",
|
|
674
674
|
"signature": "/lGgWehCMQUXjI6w4FUa+5wrbyRnct+txvVcXA+D2/ZEkoJKh+J/psO3j5HPf7Hpv+Y5SmkH71CoO+9qilyVDQ==",
|
|
675
|
-
"signed_at": "2026-05-15T22:
|
|
675
|
+
"signed_at": "2026-05-15T22:38:12.660Z"
|
|
676
676
|
},
|
|
677
677
|
{
|
|
678
678
|
"name": "attack-surface-pentest",
|
|
@@ -743,7 +743,7 @@
|
|
|
743
743
|
"PTES revision incorporating AI-surface enumeration"
|
|
744
744
|
],
|
|
745
745
|
"signature": "RqQMwOKK7xjG9e/Ls4986NOrDwKz/nQmpw1DwNJwV2nlOztyo7MgxUG3kTuLbuW3qCrrkO+CbpBA5nGS1cmKBQ==",
|
|
746
|
-
"signed_at": "2026-05-15T22:
|
|
746
|
+
"signed_at": "2026-05-15T22:38:12.660Z"
|
|
747
747
|
},
|
|
748
748
|
{
|
|
749
749
|
"name": "fuzz-testing-strategy",
|
|
@@ -803,7 +803,7 @@
|
|
|
803
803
|
"OSS-Fuzz-Gen / AI-assisted harness generation becoming the default expectation for OSS maintainers"
|
|
804
804
|
],
|
|
805
805
|
"signature": "+ELdD+1AY5DymBitH7wU65CS60NY1nDoLowJAFn7cE5Gr/5jy9BTkyxsm7PEXaSlXWMOkTf/HQ+uyzyxUVD/Bw==",
|
|
806
|
-
"signed_at": "2026-05-15T22:
|
|
806
|
+
"signed_at": "2026-05-15T22:38:12.661Z"
|
|
807
807
|
},
|
|
808
808
|
{
|
|
809
809
|
"name": "dlp-gap-analysis",
|
|
@@ -878,7 +878,7 @@
|
|
|
878
878
|
"Quebec Law 25, India DPDPA, KSA PDPL enforcement actions naming AI-tool prompt data as in-scope personal information"
|
|
879
879
|
],
|
|
880
880
|
"signature": "vL5XeQOk7vwX0sLMuKghj6XLnXsqKcGpCUNMui9HwqnWyNQwgSRGu+JFqP7ZqpP3SUYRZHcVlWhXeTJHyOtiAA==",
|
|
881
|
-
"signed_at": "2026-05-15T22:
|
|
881
|
+
"signed_at": "2026-05-15T22:38:12.661Z"
|
|
882
882
|
},
|
|
883
883
|
{
|
|
884
884
|
"name": "supply-chain-integrity",
|
|
@@ -955,7 +955,7 @@
|
|
|
955
955
|
"OpenSSF model-signing — emerging Sigstore-based signing standard for ML model weights; track for production adoption"
|
|
956
956
|
],
|
|
957
957
|
"signature": "jp3MxKukV7zW47eX3VcAIMG5WxypMDcfHqwYDodI9YQgTxEojCrRcMSApaoZHTdD3yTQC1JtkXeKxU6K3C5NCg==",
|
|
958
|
-
"signed_at": "2026-05-15T22:
|
|
958
|
+
"signed_at": "2026-05-15T22:38:12.661Z"
|
|
959
959
|
},
|
|
960
960
|
{
|
|
961
961
|
"name": "defensive-countermeasure-mapping",
|
|
@@ -1012,7 +1012,7 @@
|
|
|
1012
1012
|
],
|
|
1013
1013
|
"last_threat_review": "2026-05-11",
|
|
1014
1014
|
"signature": "XZigwq8X/csfrdG10O6Q1V5q0zUqSQGd3QrjRKkZ4fkaodG4mZahYuIQqxc8rU9jjtGAm9LtBXYB+I5csqj9Bw==",
|
|
1015
|
-
"signed_at": "2026-05-15T22:
|
|
1015
|
+
"signed_at": "2026-05-15T22:38:12.662Z"
|
|
1016
1016
|
},
|
|
1017
1017
|
{
|
|
1018
1018
|
"name": "identity-assurance",
|
|
@@ -1079,7 +1079,7 @@
|
|
|
1079
1079
|
"d3fend_refs": [],
|
|
1080
1080
|
"last_threat_review": "2026-05-11",
|
|
1081
1081
|
"signature": "k0HrsZMBxiPWB1jl4dRwhv/R5IsqbZ+SLDv1Jx3/sRl51JyXjtm8vyogTNhSwsl5/IkaRakqIPJFRFRl5h/9CQ==",
|
|
1082
|
-
"signed_at": "2026-05-15T22:
|
|
1082
|
+
"signed_at": "2026-05-15T22:38:12.662Z"
|
|
1083
1083
|
},
|
|
1084
1084
|
{
|
|
1085
1085
|
"name": "ot-ics-security",
|
|
@@ -1135,7 +1135,7 @@
|
|
|
1135
1135
|
"d3fend_refs": [],
|
|
1136
1136
|
"last_threat_review": "2026-05-11",
|
|
1137
1137
|
"signature": "oHxjumOhk8y86WcwhAX8sSWIlPzt60KfTMn4DCJLeRrrQd5+i54fVADKAdZ3vOqfDN+DexO0uX4f5dLPtacRCQ==",
|
|
1138
|
-
"signed_at": "2026-05-15T22:
|
|
1138
|
+
"signed_at": "2026-05-15T22:38:12.662Z"
|
|
1139
1139
|
},
|
|
1140
1140
|
{
|
|
1141
1141
|
"name": "coordinated-vuln-disclosure",
|
|
@@ -1187,7 +1187,7 @@
|
|
|
1187
1187
|
"NYDFS 23 NYCRR 500 amendments potentially adding explicit CVD program requirements"
|
|
1188
1188
|
],
|
|
1189
1189
|
"signature": "UCiNjncvhkZItmLQA/Sm1/NCsOiLMwdCjfUw+067v4NIxhaMMaqRrAeD3KgMyEtov7m2Hq2kfwYSt5+DQsYDCQ==",
|
|
1190
|
-
"signed_at": "2026-05-15T22:
|
|
1190
|
+
"signed_at": "2026-05-15T22:38:12.663Z"
|
|
1191
1191
|
},
|
|
1192
1192
|
{
|
|
1193
1193
|
"name": "threat-modeling-methodology",
|
|
@@ -1237,7 +1237,7 @@
|
|
|
1237
1237
|
"PASTA v2 updates incorporating AI/ML application threats"
|
|
1238
1238
|
],
|
|
1239
1239
|
"signature": "V9kl8Cf8UMjNFyn3D/fSyhWHLeXWlx3WV/jT9jdF9SrjfDqymimuTt2o91cZ2FOEJndAH9V0JGXB13Ohz8K4CQ==",
|
|
1240
|
-
"signed_at": "2026-05-15T22:
|
|
1240
|
+
"signed_at": "2026-05-15T22:38:12.663Z"
|
|
1241
1241
|
},
|
|
1242
1242
|
{
|
|
1243
1243
|
"name": "webapp-security",
|
|
@@ -1311,7 +1311,7 @@
|
|
|
1311
1311
|
"d3fend_refs": [],
|
|
1312
1312
|
"last_threat_review": "2026-05-11",
|
|
1313
1313
|
"signature": "ENSL4MJSNXhriKsTVBjg2jTc7JTtb6mxqbfBw/SVVajPMkLMcLBk4Gem9LhZWZ8DSqyWLnFO2d6hlz5q8bjuCg==",
|
|
1314
|
-
"signed_at": "2026-05-15T22:
|
|
1314
|
+
"signed_at": "2026-05-15T22:38:12.663Z"
|
|
1315
1315
|
},
|
|
1316
1316
|
{
|
|
1317
1317
|
"name": "ai-risk-management",
|
|
@@ -1361,7 +1361,7 @@
|
|
|
1361
1361
|
"d3fend_refs": [],
|
|
1362
1362
|
"last_threat_review": "2026-05-11",
|
|
1363
1363
|
"signature": "8E82UwKFNraXV/MKAbiUV6gUryYuN+Ff/kiv1aW4/XtriShdTyt/UgRuQJ8LXGXl0jMH8hRJ/xTAV8LOJqexDA==",
|
|
1364
|
-
"signed_at": "2026-05-15T22:
|
|
1364
|
+
"signed_at": "2026-05-15T22:38:12.663Z"
|
|
1365
1365
|
},
|
|
1366
1366
|
{
|
|
1367
1367
|
"name": "sector-healthcare",
|
|
@@ -1421,7 +1421,7 @@
|
|
|
1421
1421
|
"d3fend_refs": [],
|
|
1422
1422
|
"last_threat_review": "2026-05-11",
|
|
1423
1423
|
"signature": "BDuLcpTeFp2BNSf1q4rYOhYKNhlgd3o5RZ0Uw9xW5olyYxPbZSgqekQ+6Ggaec09s7y6sqR37GS0vuAMdbrdDQ==",
|
|
1424
|
-
"signed_at": "2026-05-15T22:
|
|
1424
|
+
"signed_at": "2026-05-15T22:38:12.664Z"
|
|
1425
1425
|
},
|
|
1426
1426
|
{
|
|
1427
1427
|
"name": "sector-financial",
|
|
@@ -1502,7 +1502,7 @@
|
|
|
1502
1502
|
"TIBER-EU framework v2.0 alignment with DORA TLPT RTS (JC 2024/40); cross-recognition with CBEST and iCAST"
|
|
1503
1503
|
],
|
|
1504
1504
|
"signature": "w12QqGBlRDaDVYug9uQVmEbxR7+gX23rOKZSjlt3XcszYDHBCRiP4cBRKMuEguu44DCaQsg+Btu4vAVMlss9Dg==",
|
|
1505
|
-
"signed_at": "2026-05-15T22:
|
|
1505
|
+
"signed_at": "2026-05-15T22:38:12.664Z"
|
|
1506
1506
|
},
|
|
1507
1507
|
{
|
|
1508
1508
|
"name": "sector-federal-government",
|
|
@@ -1571,7 +1571,7 @@
|
|
|
1571
1571
|
"Australia PSPF 2024 revision and ISM quarterly updates — track for Essential Eight Maturity Level requirements for federal entities"
|
|
1572
1572
|
],
|
|
1573
1573
|
"signature": "nMsyJ+rp5fM8/VjC7zsZyDjOC4hpxB+noT1VX7W0HBlq5t3SY56cwOGApwES/kBcCuf4qexKY376OxUr93zvCQ==",
|
|
1574
|
-
"signed_at": "2026-05-15T22:
|
|
1574
|
+
"signed_at": "2026-05-15T22:38:12.665Z"
|
|
1575
1575
|
},
|
|
1576
1576
|
{
|
|
1577
1577
|
"name": "sector-energy",
|
|
@@ -1636,7 +1636,7 @@
|
|
|
1636
1636
|
"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"
|
|
1637
1637
|
],
|
|
1638
1638
|
"signature": "L1moEqEGkBkqY/3ohJcfqrlJn40UurDCyb2MOP/IwTAeZD+QbVZ17/drdsydkJ6qSXPiyiE6u8HDfZsDS13NBQ==",
|
|
1639
|
-
"signed_at": "2026-05-15T22:
|
|
1639
|
+
"signed_at": "2026-05-15T22:38:12.665Z"
|
|
1640
1640
|
},
|
|
1641
1641
|
{
|
|
1642
1642
|
"name": "sector-telecom",
|
|
@@ -1722,7 +1722,7 @@
|
|
|
1722
1722
|
"O-RAN SFG / WG11 security specifications"
|
|
1723
1723
|
],
|
|
1724
1724
|
"signature": "VKLuoRkFq7lNXqySipwzPSaiHaqemHQ2cReemF/Xy9hUpD9orQaTVZWClOA4lzoF6d2eQ/CeS///Jjnj4g9dCg==",
|
|
1725
|
-
"signed_at": "2026-05-15T22:
|
|
1725
|
+
"signed_at": "2026-05-15T22:38:12.666Z"
|
|
1726
1726
|
},
|
|
1727
1727
|
{
|
|
1728
1728
|
"name": "api-security",
|
|
@@ -1791,7 +1791,7 @@
|
|
|
1791
1791
|
"d3fend_refs": [],
|
|
1792
1792
|
"last_threat_review": "2026-05-11",
|
|
1793
1793
|
"signature": "JHGu5OI35payaFR1At3XZIX4HnflgF3lI9vk/XsHpu0loWHtbTiA/SrNzTuWO+be8aIfd36uNz7WnJNwBTCHDA==",
|
|
1794
|
-
"signed_at": "2026-05-15T22:
|
|
1794
|
+
"signed_at": "2026-05-15T22:38:12.666Z"
|
|
1795
1795
|
},
|
|
1796
1796
|
{
|
|
1797
1797
|
"name": "cloud-security",
|
|
@@ -1872,7 +1872,7 @@
|
|
|
1872
1872
|
"CISA KEV additions for cloud-control-plane CVEs (IMDSv1 abuses, federation token mishandling, cross-tenant boundary failures); CISA Cybersecurity Advisories for cross-cloud advisories"
|
|
1873
1873
|
],
|
|
1874
1874
|
"signature": "UEn0305KAEqIfYOdzadLBdPG/PJ+3sJ/8ubvPFNcXfqXp2uOWTfqGUqY65PApA992VEEa1RBQt5R7Nyhd/OjDQ==",
|
|
1875
|
-
"signed_at": "2026-05-15T22:
|
|
1875
|
+
"signed_at": "2026-05-15T22:38:12.666Z"
|
|
1876
1876
|
},
|
|
1877
1877
|
{
|
|
1878
1878
|
"name": "container-runtime-security",
|
|
@@ -1934,7 +1934,7 @@
|
|
|
1934
1934
|
"d3fend_refs": [],
|
|
1935
1935
|
"last_threat_review": "2026-05-11",
|
|
1936
1936
|
"signature": "lPd9tHAskNapjrWwFWhsb8ntAL0xovDCIGElsOCyjcafzby4ArwRw5Lq28sfNloJZAhMN+AWj+lDdFytiUQHCQ==",
|
|
1937
|
-
"signed_at": "2026-05-15T22:
|
|
1937
|
+
"signed_at": "2026-05-15T22:38:12.667Z"
|
|
1938
1938
|
},
|
|
1939
1939
|
{
|
|
1940
1940
|
"name": "mlops-security",
|
|
@@ -2005,7 +2005,7 @@
|
|
|
2005
2005
|
"MITRE ATLAS v5.2 — track AML.T0010 sub-technique expansion and any new MLOps-pipeline-specific TTPs"
|
|
2006
2006
|
],
|
|
2007
2007
|
"signature": "U+HyElcP007FIblXUE/nFpj/rZ5z3VohsvxRCWEuuJDLdOnsXYEadb7ccr3X7S4aRG2MC4T2KtVtgbKIuO5QDw==",
|
|
2008
|
-
"signed_at": "2026-05-15T22:
|
|
2008
|
+
"signed_at": "2026-05-15T22:38:12.667Z"
|
|
2009
2009
|
},
|
|
2010
2010
|
{
|
|
2011
2011
|
"name": "incident-response-playbook",
|
|
@@ -2067,7 +2067,7 @@
|
|
|
2067
2067
|
"NYDFS 23 NYCRR 500.17 amendments tightening ransom-payment 24h disclosure operationalization"
|
|
2068
2068
|
],
|
|
2069
2069
|
"signature": "XB3TVjNRBlqqbIhatFoYtTJHTS51nVt9k7DVrb2roUflLDjbCnaTbrpztA2oqJyyxwgnLlX+K7NW8oYOYEMeCg==",
|
|
2070
|
-
"signed_at": "2026-05-15T22:
|
|
2070
|
+
"signed_at": "2026-05-15T22:38:12.667Z"
|
|
2071
2071
|
},
|
|
2072
2072
|
{
|
|
2073
2073
|
"name": "email-security-anti-phishing",
|
|
@@ -2120,7 +2120,7 @@
|
|
|
2120
2120
|
"d3fend_refs": [],
|
|
2121
2121
|
"last_threat_review": "2026-05-11",
|
|
2122
2122
|
"signature": "RiCryJEd66T2NNcSo/mZTd3sGWDycE3C37guLJanLdVL5co35DrPFmIl8qy3ZM/y+Wzg5vpny8VKgr1//1/bCA==",
|
|
2123
|
-
"signed_at": "2026-05-15T22:
|
|
2123
|
+
"signed_at": "2026-05-15T22:38:12.668Z"
|
|
2124
2124
|
},
|
|
2125
2125
|
{
|
|
2126
2126
|
"name": "age-gates-child-safety",
|
|
@@ -2188,11 +2188,11 @@
|
|
|
2188
2188
|
"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"
|
|
2189
2189
|
],
|
|
2190
2190
|
"signature": "MMWvg3lIf5ygm31zyf1E43t3W9MfRbMBBPrqlj1wOa8AxVJL8LICnAXfmyJ/TNJXwpF+rfZeDdoxXkql8wmtBA==",
|
|
2191
|
-
"signed_at": "2026-05-15T22:
|
|
2191
|
+
"signed_at": "2026-05-15T22:38:12.668Z"
|
|
2192
2192
|
}
|
|
2193
2193
|
],
|
|
2194
2194
|
"manifest_signature": {
|
|
2195
2195
|
"algorithm": "Ed25519",
|
|
2196
|
-
"signature_base64": "
|
|
2196
|
+
"signature_base64": "hRjCIjBncoCecBmhExyEZhUaTyUAe0s3pbLg1Oj7eHaSsdEfynFJ2RvW+LqpEPokeS6HgaU9ORyC4LMNBiWeAQ=="
|
|
2197
2197
|
}
|
|
2198
2198
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blamejs/exceptd-skills",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.27",
|
|
4
4
|
"description": "AI security skills grounded in mid-2026 threat reality, not stale framework documentation. 38 skills, 10 catalogs, 34 jurisdictions, pre-computed indexes, Ed25519-signed.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai-security",
|
package/sbom.cdx.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"bomFormat": "CycloneDX",
|
|
3
3
|
"specVersion": "1.6",
|
|
4
|
-
"serialNumber": "urn:uuid:
|
|
4
|
+
"serialNumber": "urn:uuid:c26c612d-400e-4270-9716-299e76224a35",
|
|
5
5
|
"version": 1,
|
|
6
6
|
"metadata": {
|
|
7
|
-
"timestamp": "2026-05-15T22:
|
|
7
|
+
"timestamp": "2026-05-15T22:38:14.241Z",
|
|
8
8
|
"tools": [
|
|
9
9
|
{
|
|
10
10
|
"name": "hand-written",
|
|
@@ -13,10 +13,10 @@
|
|
|
13
13
|
}
|
|
14
14
|
],
|
|
15
15
|
"component": {
|
|
16
|
-
"bom-ref": "pkg:npm/@blamejs/exceptd-skills@0.12.
|
|
16
|
+
"bom-ref": "pkg:npm/@blamejs/exceptd-skills@0.12.27",
|
|
17
17
|
"type": "application",
|
|
18
18
|
"name": "@blamejs/exceptd-skills",
|
|
19
|
-
"version": "0.12.
|
|
19
|
+
"version": "0.12.27",
|
|
20
20
|
"description": "AI security skills grounded in mid-2026 threat reality, not stale framework documentation. 38 skills, 10 catalogs, 34 jurisdictions, pre-computed indexes, Ed25519-signed.",
|
|
21
21
|
"licenses": [
|
|
22
22
|
{
|
|
@@ -25,11 +25,11 @@
|
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
],
|
|
28
|
-
"purl": "pkg:npm/%40blamejs/exceptd-skills@0.12.
|
|
28
|
+
"purl": "pkg:npm/%40blamejs/exceptd-skills@0.12.27",
|
|
29
29
|
"externalReferences": [
|
|
30
30
|
{
|
|
31
31
|
"type": "distribution",
|
|
32
|
-
"url": "https://www.npmjs.com/package/@blamejs/exceptd-skills/v/0.12.
|
|
32
|
+
"url": "https://www.npmjs.com/package/@blamejs/exceptd-skills/v/0.12.27"
|
|
33
33
|
},
|
|
34
34
|
{
|
|
35
35
|
"type": "vcs",
|