@blamejs/exceptd-skills 0.12.21 → 0.12.23
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 +18 -12
- package/ARCHITECTURE.md +2 -2
- package/CHANGELOG.md +103 -24
- package/CONTEXT.md +126 -69
- package/README.md +7 -7
- package/bin/exceptd.js +687 -295
- package/data/_indexes/_meta.json +4 -4
- package/data/_indexes/stale-content.json +10 -3
- package/data/playbooks/ai-api.json +1 -1
- package/data/playbooks/containers.json +1 -1
- package/data/playbooks/cred-stores.json +1 -1
- package/data/playbooks/crypto-codebase.json +1 -1
- package/data/playbooks/crypto.json +1 -1
- package/data/playbooks/hardening.json +1 -1
- package/data/playbooks/kernel.json +1 -1
- package/data/playbooks/mcp.json +1 -1
- package/data/playbooks/runtime.json +3 -1
- package/data/playbooks/sbom.json +1 -1
- package/data/playbooks/secrets.json +15 -1
- package/lib/auto-discovery.js +2 -2
- package/lib/cross-ref-api.js +12 -11
- package/lib/cve-curation.js +18 -19
- package/lib/lint-skills.js +5 -5
- package/lib/playbook-runner.js +406 -274
- package/lib/prefetch.js +21 -21
- package/lib/refresh-external.js +15 -18
- package/lib/refresh-network.js +39 -13
- package/lib/scoring.js +8 -7
- package/lib/sign.js +10 -11
- package/lib/source-osv.js +7 -7
- package/lib/validate-catalog-meta.js +1 -1
- package/lib/validate-cve-catalog.js +3 -3
- package/lib/verify.js +63 -22
- package/manifest.json +41 -41
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
- package/scripts/verify-shipped-tarball.js +22 -18
- package/skills/threat-model-currency/skill.md +1 -1
package/AGENTS.md
CHANGED
|
@@ -44,7 +44,7 @@ Also read [CONTEXT.md](CONTEXT.md) for a complete orientation to the skill syste
|
|
|
44
44
|
| New `phases.detect.indicators[].id` in a playbook | Quoted indicator id literal in `tests/e2e-scenarios/*/expect.json` or `tests/*.test.js` |
|
|
45
45
|
| New / changed `iocs` field on a CVE entry | CVE id and the word `iocs` in the same test file |
|
|
46
46
|
|
|
47
|
-
Mechanical enforcement lives in `scripts/check-test-coverage.js` and runs as the
|
|
47
|
+
Mechanical enforcement lives in `scripts/check-test-coverage.js` and runs as the 13th gate of `npm run predeploy` (also the `Diff coverage` job in `ci.yml`). Docs (`*.md`), workflow YAML, and skill body changes are allowlisted — skill bodies are covered by the Ed25519 signature gate (Hard Rule #13), workflows surface a manual-review flag rather than a hard finding. Whitespace-only diffs are ignored.
|
|
48
48
|
|
|
49
49
|
The gate is blocking: a covered surface change without a covering test reference fails the predeploy run and the `Diff coverage` CI job. Never bypass with `--no-verify` or `--warn-only` — add the covering test first. This rule is additive to Hard Rule #11 (no-MVP ban): a new playbook indicator or CLI surface that ships without a regression test is the same shape of incomplete-feature ship that #11 forbids, applied to the test layer.
|
|
50
50
|
|
|
@@ -52,7 +52,7 @@ Also read [CONTEXT.md](CONTEXT.md) for a complete orientation to the skill syste
|
|
|
52
52
|
|
|
53
53
|
## Seven-phase playbook contract
|
|
54
54
|
|
|
55
|
-
exceptd ships investigation playbooks under `data/playbooks/*.json` (schema: `lib/schemas/playbook.schema.json`; reference playbook: `data/playbooks/kernel.json`). Each playbook defines a **seven-phase** investigation that splits cleanly between exceptd (knowledge + GRC layer) and the host AI assistant (artifact collection + indicator evaluation). The host AI invokes the runner via
|
|
55
|
+
exceptd ships investigation playbooks under `data/playbooks/*.json` (schema: `lib/schemas/playbook.schema.json`; reference playbook: `data/playbooks/kernel.json`). Each playbook defines a **seven-phase** investigation that splits cleanly between exceptd (knowledge + GRC layer) and the host AI assistant (artifact collection + indicator evaluation). The host AI invokes the runner via the `exceptd brief` / `exceptd run` / `exceptd ai-run` verbs or, for in-process callers, `require('@blamejs/exceptd-skills/lib/playbook-runner.js')`. exceptd owns **govern, direct, analyze, validate, close**; the AI owns **look, detect**. Phases run strictly in order — never reorder, never skip.
|
|
56
56
|
|
|
57
57
|
### The seven phases
|
|
58
58
|
|
|
@@ -88,8 +88,8 @@ Operator asks: "is this host vulnerable to Copy Fail?" AI invokes `node lib/play
|
|
|
88
88
|
|
|
89
89
|
### CLI invocation
|
|
90
90
|
|
|
91
|
-
- **
|
|
92
|
-
- **
|
|
91
|
+
- **CLI verb:** `exceptd run <playbook> --evidence <file>` walks the full seven phases against operator-supplied evidence. `exceptd brief <playbook>` returns Phase 2 threat context for prep; `exceptd ai-run` is the streaming variant for AI agents. `exceptd ci` is the gate-only variant for CI pipelines (exit 8 on lock contention, 6 on tampered attestations).
|
|
92
|
+
- **Library entry point:** `require('@blamejs/exceptd-skills/lib/playbook-runner.js')` exposes the same engine for in-process callers — schema reference at `lib/schemas/playbook.schema.json`.
|
|
93
93
|
|
|
94
94
|
Schema reference: `lib/schemas/playbook.schema.json`. Reference playbook (read this before authoring a new one): `data/playbooks/kernel.json`.
|
|
95
95
|
|
|
@@ -133,14 +133,20 @@ Cross-cutting playbook `framework` is the natural correlation layer — many pla
|
|
|
133
133
|
|
|
134
134
|
| Verb | What it does |
|
|
135
135
|
|---|---|
|
|
136
|
-
| `exceptd
|
|
137
|
-
| `exceptd
|
|
138
|
-
| `exceptd
|
|
139
|
-
| `exceptd
|
|
140
|
-
| `exceptd run
|
|
141
|
-
| `exceptd
|
|
142
|
-
| `exceptd
|
|
143
|
-
| `exceptd
|
|
136
|
+
| `exceptd brief --all` | Grouped-by-scope summary of all 13 playbooks. `--scope <type>` filters. `--directives` expands directive IDs/titles per playbook. `--flat` for non-grouped. Legacy alias: `exceptd plan` (deprecated, scheduled for removal in v0.13). |
|
|
137
|
+
| `exceptd brief <pb>` | Phase 2 threat-context briefing — threat context, RWEP thresholds, skill chain, token budget, jurisdiction obligations. |
|
|
138
|
+
| `exceptd run <pb> --evidence <file>` | Phases 5-7 (analyze + validate + close) from agent evidence. Auto-detect cwd when no playbook positional. `--vex <file>` drops CycloneDX/OpenVEX `not_affected` CVEs. `--diff-from-latest` for drift mode. `--force-stale` overrides currency hard-block. |
|
|
139
|
+
| `exceptd ai-run <pb>` | Streaming variant of `run` for AI agents; emits phase-by-phase NDJSON. |
|
|
140
|
+
| `exceptd run-all` | Multi-playbook batch run. `--scope <type>` filters. |
|
|
141
|
+
| `exceptd ci` | Top-level CI gate for a single playbook with exit-code semantics. Preferred over `run --ci`. |
|
|
142
|
+
| `exceptd discover` | Repo discovery — scans cwd and surfaces matching playbooks + collection hints. |
|
|
143
|
+
| `exceptd ask <pb> <question>` | Read-only Q&A against a playbook's directives, indicators, and threat context. |
|
|
144
|
+
| `exceptd attest diff <sid>` | Replay analyze against a stored evidence bundle for drift detection. `--against <other-sid>` compares two sessions. `--playbook <id>` + `--since <ISO>` accepted with `--latest`. Legacy alias: `exceptd reattest` (deprecated, scheduled for removal in v0.13). |
|
|
145
|
+
| `exceptd attest verify <sid>` | Verify a persisted attestation's signature + evidence hash. |
|
|
146
|
+
| `exceptd attest list` | Inventory `.exceptd/attestations/` — newest first. `--playbook <id>` filters. |
|
|
147
|
+
| `exceptd attest show <sid>` | Print the attestation body. |
|
|
148
|
+
| `exceptd doctor` | Health checks. `--signatures` verifies Ed25519 chains; `--cves` / `--rfcs` check catalog currency; `--fix` repairs recoverable state. |
|
|
149
|
+
| `exceptd lint` | Skill format lint — frontmatter completeness, required body sections, signature presence. |
|
|
144
150
|
|
|
145
151
|
All verbs support `--help` for per-verb usage. JSON output by default; `--pretty` for indented.
|
|
146
152
|
|
package/ARCHITECTURE.md
CHANGED
|
@@ -173,7 +173,7 @@ Tracks PoC status, weaponization stage, and AI-assist factor per CVE. Updated wh
|
|
|
173
173
|
|
|
174
174
|
### `data/cwe-catalog.json`
|
|
175
175
|
|
|
176
|
-
|
|
176
|
+
55 CWE entries pinned to **CWE v4.17**. Covers the Top 25 Most Dangerous Software Weaknesses (2024 release) plus AI- and supply-chain-relevant weakness classes (prompt-injection-as-trust-boundary failure, training data integrity, dependency confusion, untrusted artifact ingestion). Each entry records root-cause description, common consequences, mitigation patterns, and the CVEs in `cve-catalog.json` that instantiate the weakness. Skills cite CWE IDs in `cwe_refs` to anchor a finding to a stable weakness taxonomy rather than to a single CVE; the CWE provides the durable root-cause lens that survives across exploit generations.
|
|
177
177
|
|
|
178
178
|
`_meta.cwe_version` pins the version; on a CWE release, audit IDs for renames or deprecations, bump `last_threat_review` on affected skills, and update `_meta`.
|
|
179
179
|
|
|
@@ -234,7 +234,7 @@ Framework lag scoring and gap report generation.
|
|
|
234
234
|
|
|
235
235
|
### `scripts/check-test-coverage.js`
|
|
236
236
|
|
|
237
|
-
Diff-coverage analyzer. Walks the staged/working-tree diff for the changed-surface shapes Hard Rule #15 enforces (CLI verbs, CLI flags, `module.exports` identifiers, new playbook indicator IDs, CVE `iocs` fields) and asserts that each change has a covering test reference somewhere under `tests/`. Skill bodies, docs, and workflow YAML are allowlisted. Runs as the
|
|
237
|
+
Diff-coverage analyzer. Walks the staged/working-tree diff for the changed-surface shapes Hard Rule #15 enforces (CLI verbs, CLI flags, `module.exports` identifiers, new playbook indicator IDs, CVE `iocs` fields) and asserts that each change has a covering test reference somewhere under `tests/`. Skill bodies, docs, and workflow YAML are allowlisted. Runs as the 13th gate of `npm run predeploy` (and the `Diff coverage` job in `ci.yml`). Direct invocation: `npm run diff-coverage`.
|
|
238
238
|
|
|
239
239
|
### `scripts/check-sbom-currency.js`
|
|
240
240
|
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,95 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.12.23 — 2026-05-15
|
|
4
|
+
|
|
5
|
+
**Patch: doc-vs-code reconciliation, trust-chain pin loader hardening, attest list/show replay isolation, global-first framework coverage backfill.**
|
|
6
|
+
|
|
7
|
+
### Trust chain
|
|
8
|
+
|
|
9
|
+
- **`loadExpectedFingerprintFirstLine` refuses UTF-16LE / UTF-16BE pin files.** Saving `keys/EXPECTED_FINGERPRINT` via PowerShell `Set-Content -Encoding UTF16LE` (or any tool emitting a UTF-16 BOM) previously caused every consumer (verify, refresh-network, verify-shipped-tarball, attest pin) to decode the file as UTF-8 mojibake; the first line never matched a live fingerprint and operators saw no signal that the encoding was wrong. The loader now detects the FF FE / FE FF byte signatures, returns null, and routes through the existing "no-pin" warn-and-continue path so the error is surfaced without bricking the gate. UTF-8 and UTF-8-with-BOM remain supported.
|
|
10
|
+
- **`KEYS_ROTATED=1` override now emits a `process.emitWarning('EXCEPTD_KEYS_ROTATED_OVERRIDE', ...)`** at every site that accepts the bypass (`bin/exceptd.js` attestation pin, `lib/refresh-network.js` refresh-network swap gate). Previously the env var was a silent skip; operators who set it once for a legitimate rotation and forgot to commit the new pin had no surface signal on subsequent runs. The mismatch values are echoed in the warning so log scrapers can confirm intended rotation. `lib/verify.js` and `scripts/verify-shipped-tarball.js` already emitted warnings at this gate and are unchanged.
|
|
11
|
+
|
|
12
|
+
### Engine + CLI
|
|
13
|
+
|
|
14
|
+
- **`attest list` and `attest show` filter `kind: 'replay'` records out of the session attestations array.** v0.12.22 added signed `replay-<iso>.json` audit records under `.exceptd/attestations/<sid>/`, which the listing/show loops were treating as additional sessions (or duplicate attestation entries) with `evidence_hash: null` and `captured_at: null`. Records are now partitioned by parsed `kind` field — replay records appear under a new `attestation_replays[]` array on `attest show` output and are omitted entirely from `attest list`. Gating on the parsed `kind` field (not filename prefix) closes the rename-smuggle vector.
|
|
15
|
+
- **`--session-id .` / `..` / all-dots refused after regex pass.** The `/^[A-Za-z0-9._-]{1,64}$/` validator accepted any string of dots, which resolved into or above the attestation root. The CLI now explicitly refuses all-dots session ids with a structured error.
|
|
16
|
+
|
|
17
|
+
### Help text and exit-code surface
|
|
18
|
+
|
|
19
|
+
- **`ingest`, `ai-run`, and `run-all` help blocks document `--csaf-status` and `--publisher-namespace`.** v0.12.22's `BUNDLE_FLAG_RELEVANT_VERBS` set wired the flags into all five bundle-emitting verbs but only the `run` and `ci` help blocks listed them; operators on the other three verbs had to read the source to find them.
|
|
20
|
+
- **Exit-code tables completed across the help surface.** Top-level `exceptd help` for `ci` now lists 0/1/2/3/4/5/6/8 instead of 0/2/3/4/5/1. Per-verb tables for `ci`, `attest verify`, and `reattest` now document `6 — TAMPERED` and `8 — LOCK_CONTENTION` where applicable. `run --help` adds a `6-7 — reserved` line so the gap doesn't read as accidental.
|
|
21
|
+
|
|
22
|
+
### Hard Rule #5 — global-first coverage
|
|
23
|
+
|
|
24
|
+
- **Eleven playbooks backfilled with UK CAF + AU Essential 8 / ACSC / ISM clauses** in `phases.direct.framework_lag_declaration` (`secrets`, `ai-api`, `containers`, `cred-stores`, `crypto`, `kernel`, `mcp`, `runtime`, `sbom` — both CAF and E8 added; `crypto-codebase` — E8 added on top of existing CAF; `hardening` — CAF added on top of existing E8). The v0.12.21 entry claimed this coverage was already in place; only `framework.json` and `library-author.json` actually had it. All 13 playbooks now declare CAF + E8 framework-lag posture alongside NIST and ISO.
|
|
25
|
+
|
|
26
|
+
### Operator-facing docs
|
|
27
|
+
|
|
28
|
+
- **README, AGENTS.md, ARCHITECTURE.md, and CONTEXT.md reconciled with the v0.11+ canonical CLI surface.** The deprecation banner heading on legacy v0.10.x verbs now states "scheduled for removal in v0.13" (not "removed in v0.12" — the verbs remain registered with deprecation warnings). README body examples replace `exceptd verify` / `exceptd scan` / `validate-cves` / `validate-rfcs` with `exceptd doctor --signatures` / `exceptd discover` / `doctor --cves` / `doctor --rfcs`. AGENTS.md CLI reference table replaces the stale v0.10.x verb set (`plan`/`govern`/`direct`/`look`/`ingest`/`reattest`/`list-attestations`) with the v0.11+ canonical surface (`brief`/`run`/`ai-run`/`run-all`/`ci`/`discover`/`ask`/`reattest <sid>`/`attest verify|list|show`/`doctor`/`lint`). CONTEXT.md catalog inventory aligned with actual catalog state (10 CVE, 62 framework-control-gap, 35 jurisdictions, 55 CWE, 28 D3FEND, 31 RFC, 22 DLP entries) and a new "Playbooks and the Seven-Phase Contract" section enumerates the 13 playbooks and the govern → direct → look → detect → analyze → validate → close contract.
|
|
29
|
+
- **Predeploy gate count corrected from "15" to "14"** across AGENTS.md, ARCHITECTURE.md, and README. The predeploy gate set ships 14 gates per `scripts/predeploy.js`; the "15th" framing was an off-by-one carryover from an earlier draft of the diff-coverage gate that landed as the 13th rather than appended. The diff-coverage gate position is also corrected from "14th" to "13th" in AGENTS.md Hard Rule #15 and ARCHITECTURE.md (the validate-playbooks gate sits at position 14).
|
|
30
|
+
- **AGENTS.md CLI reference table now lists `brief --all` and `attest diff <sid>`** as canonical, with `plan` and `reattest` marked as deprecated aliases scheduled for removal in v0.13 (consistent with how the v0.10.x `govern`/`direct`/`look` verbs are surfaced).
|
|
31
|
+
- **AGENTS.md "Seven-phase playbook contract" intro** drops the "direct CLI verbs are landing in a follow-up task" prose — the verbs landed in v0.11.0. Points readers at `exceptd brief` / `exceptd run` / `exceptd ai-run` plus the library entry point at `lib/playbook-runner.js`.
|
|
32
|
+
- **CONTEXT.md phase-contract table** now references `exceptd brief <playbook> --phase {govern,direct,look}` for phases 1-3 (was `exceptd govern|direct|look`); the "How to Walk a Playbook" onboarding section is rewritten against the same canonical surface.
|
|
33
|
+
- **ARCHITECTURE.md CWE entry count** corrected from 51 to 55 (matches `data/cwe-catalog.json` and CONTEXT.md).
|
|
34
|
+
- **Jurisdiction count corrected from "37" / "34" to "35"** in the README badge, status copy, and catalog footnote. `data/global-frameworks.json` has 38 top-level keys but three are `_meta` / `_notification_summary` / `_patch_sla_summary` aggregates; the actual jurisdiction count is 35.
|
|
35
|
+
|
|
36
|
+
### Operations
|
|
37
|
+
|
|
38
|
+
- **`.github/workflows/atlas-currency.yml` declares `permissions:` at the job level** instead of the workflow root. Matches the project's OpenSSF Scorecard `TokenPermissionsID` posture (job-scoped least-privilege); top-level permission grants were the only remaining outlier across the repo's workflow set.
|
|
39
|
+
|
|
40
|
+
### Internal
|
|
41
|
+
|
|
42
|
+
- **Source-comment slot-token scrub broadened** to cover bare audit slot-tokens (`KK P1-N`, `R-F8`, `S P1-A`, etc.) without the leading `audit` prefix. Previous scrubs only matched `(audit|Audit)\s+[A-Z]+`; the new sweep covers comment-only references across `bin/`, `lib/`, `scripts/`, and `tests/`. Test logic and code logic untouched.
|
|
43
|
+
- **`tests/audit-mm-nn-fixes.test.js` tightened** — the UTF-16BE odd-length-payload refusal test was asserting `notEqual(r.status, 0)`, the exact coincidence-passing-tests anti-pattern the project rule explicitly forbids. Changed to `assert.equal(r.status, 1)`.
|
|
44
|
+
|
|
45
|
+
Test count and predeploy gates land alongside this entry; see the predeploy log on the release commit.
|
|
46
|
+
|
|
47
|
+
## 0.12.22 — 2026-05-15
|
|
48
|
+
|
|
49
|
+
## 0.12.22 — 2026-05-15
|
|
50
|
+
|
|
51
|
+
**Patch: trust-chain attestation sidecar redesign, CSAF spec-compliance fixes, CLI flag scoping, concurrency exit-code surface.**
|
|
52
|
+
|
|
53
|
+
### Trust chain
|
|
54
|
+
|
|
55
|
+
- **`.sig` sidecar shape reduced to signed-bytes only.** The previous shape carried `signed_at`, `signs_path`, and `signs_sha256` alongside the Ed25519 signature — but those fields were NOT covered by the signature (the signature signs the attestation file bytes, not the sidecar). An attacker who captured any valid sidecar could rewrite `signed_at` to lie about freshness or `signs_path` to point at a sibling attestation in the same session directory, and the signature still verified. Sidecar now carries `{algorithm, signature_base64, note}` (signed) or `{algorithm, signed: false, note}` (unsigned) only. Operators reading freshness use filesystem mtime; the attestation file's own `captured_at` field is signed.
|
|
56
|
+
- **`cmdReattest --force-replay` persists the override as a signed `replay-<isoZ>.json`** in the session directory alongside `attestation.json`. The previous shape emitted the override metadata only to stdout, so the audit trail vanished when the shell closed. `attest verify <session-id>` surfaces both the original attestation and any replay records so an auditor sees the full chain.
|
|
57
|
+
- **Sidecar verifier enforces `algorithm === 'Ed25519'` strictly.** Both `verifyAttestationSidecar` and `cmdAttest verify` previously fell through to `crypto.verify` for any non-`"unsigned"` algorithm value. A `null`, `"RSA-PSS"`, array, or omitted-field sidecar now surfaces `tamper_class: 'algorithm-unsupported'` and exits 6. Matches the strict gate already in place at `verifyManifestSignature`.
|
|
58
|
+
- **`hasReadableStdin` Windows fallback tightened to strict `=== false`** to close the wrapped-test-harness hang regression. The helper now requires `process.stdin.isTTY === false` (not falsy) on Windows when fstat reports size 0 on a non-FIFO non-socket non-character descriptor. POSIX pipes/FIFOs/sockets remain trusted via the `isFIFO()`/`isSocket()`/`isCharacterDevice()` probes added in v0.12.21.
|
|
59
|
+
- **`keys/EXPECTED_FINGERPRINT` pin loaders strip UTF-8 BOM.** Four sites (`bin/exceptd.js`, `lib/verify.js`, `lib/refresh-network.js`, `scripts/verify-shipped-tarball.js`) now share a single `loadExpectedFingerprintFirstLine` helper that strips a leading `U+FEFF` before splitting on newlines. A pin file saved via Notepad with `files.encoding: utf8bom` previously broke every verify path; the helper closes that DoS-by-encoding-roundtrip class.
|
|
60
|
+
- **`sanitizeOperatorText` (library entry point) NFC-normalizes and rejects Unicode `\p{C}`** (Cc/Cf/Cs/Co/Cn). The CLI-level guard added in v0.12.21 only fired on operator-supplied `--operator` input; library callers of `buildEvidenceBundle` bypassed the sanitization. The helper now uniformly returns null for inputs containing bidi-control / zero-width / surrogate / private-use / unassigned characters or empty-after-strip, and caps at 256 codepoints (not 256 UTF-16 code units, so astral-plane characters don't smuggle past).
|
|
61
|
+
|
|
62
|
+
### Bundles (CSAF / SARIF / OpenVEX)
|
|
63
|
+
|
|
64
|
+
- **CSAF `cvss_v3` block emitted only for `CVSS:3.0` / `CVSS:3.1` vectors.** Catalog entries carrying `CVSS:2.0/` or `CVSS:4.0/` vectors previously produced a `cvss_v3.version` of `'2.0'` / `'4.0'`, which violates the CSAF 2.0 schema enum `["3.0", "3.1"]`. Strict validators (BSI CSAF Validator) rejected the bundle. The block is now omitted for non-v3 vectors and a `bundle_cvss_v3_version_unsupported` runtime warning surfaces in `analyze.runtime_errors[]` so operators see the gap.
|
|
65
|
+
- **CSAF `vulnerabilities[].ids[]` routes `RUSTSEC-*` to `system_name: 'RUSTSEC'`**. Previously RUSTSEC advisories fell through to `system_name: 'OSV'` — mis-attributing the authority. Unknown prefixes (any advisory id not in the GHSA / MAL / OSV / SNYK / RUSTSEC set) now emit `system_name: 'exceptd-unknown'` so downstream tooling sees the authority wasn't recognized.
|
|
66
|
+
- **Non-string `cve_id` no longer emits literal `"null"` text.** Catalog entries whose `cve_id` is `null` / `undefined` / non-string are now omitted from `vulnerabilities[]` entirely, with a `bundle_cve_id_missing` runtime warning. Strict validators no longer see ghost vulnerabilities keyed on `text: "null"`.
|
|
67
|
+
|
|
68
|
+
### CLI
|
|
69
|
+
|
|
70
|
+
- **`--csaf-status` and `--publisher-namespace` refused on info-only verbs**. The flags were previously validated then silently dropped when invoked against `brief`, `list`, `attest`, `discover`, `doctor`, `lint`, etc. — same UX-trap class as the v0.12.21 `--ack` fix. The flags now refuse with a structured error pointing at the verb set that actually consumes them (`run`, `ci`, `run-all`, `ai-run`). Error messages also use the actual invoked verb as the prefix instead of a hardcoded `"run:"`.
|
|
71
|
+
- **`cmdRunMulti` consent gate now per-playbook**. The single-playbook `cmdRun` correctly gates `operator_consent` persistence on `classification === 'detected'`, but `cmdRunMulti` was persisting consent unconditionally across every iteration regardless of the iteration's own classification. Per-playbook consent gating now mirrors the single-run shape; mixed-classification `run-all --ack` runs persist consent only into the detected-playbook attestations.
|
|
72
|
+
- **UTF-16BE `readJsonFile` no longer leaks uninitialized buffer bytes.** The decoder used `Buffer.allocUnsafe` (uninitialized heap memory) and silently skipped the trailing byte on odd-length payloads — the decoded string then included whatever bytes happened to be on the heap at allocation time. Now uses `Buffer.alloc` (zero-initialized) and refuses odd-length payloads with a clear truncation error.
|
|
73
|
+
- **`run` and `ci` help text documents `--csaf-status` and `--publisher-namespace`**.
|
|
74
|
+
|
|
75
|
+
### Concurrency
|
|
76
|
+
|
|
77
|
+
- **`persistAttestation` lock contention exits 8 (`LOCK_CONTENTION`)** distinct from generic exit 1. The v0.12.21 entry claimed callers could distinguish lock-busy from hard failure via the `lock_contention: true` field, but `emit()`'s auto-mapping collapsed the exit code to 1. The function now sets `process.exitCode = 8` before returning, with `exit_code: 8` echoed in the result body. Exit-code table in `run --help` documents the code.
|
|
78
|
+
- **`acquireLock` reclaims same-PID stale lockfiles** older than 30 seconds. The previous PID-liveness probe skipped reclaim when the lockfile's recorded PID matched the current process's PID — but a same-process leak across multiple `run()` invocations left the lockfile orphaned indefinitely. The mtime-staleness check now allows reclaim while preserving legitimate reentrancy on fresh same-PID lockfiles.
|
|
79
|
+
|
|
80
|
+
### Test quality
|
|
81
|
+
|
|
82
|
+
- **5 exit-code assertions tightened from `notEqual(r.status, 0)` to exact-value `assert.equal(r.status, 1)`** across the CSAF and CLI-flag regression suites. Closes the same coincidence-passing-tests regression the v0.12.21 entry's tightening pass left half-done.
|
|
83
|
+
- **CVE-curation tests no longer mutate `data/cve-catalog.json`** in the repo root. Three tests previously injected synthetic `CVE-9999-*` drafts into the live catalog with a `finally{}` restore — a Ctrl-C between mutation and restoration leaked state into the repo. The refresh tests now use the existing `--catalog <path>` flag against a tempdir copy; the validate test uses the in-process module API directly.
|
|
84
|
+
- **Three e2e expect.json files** (`14-framework-jurisdiction-gap`, `16-containers-root-user`, `19-crypto-rsa-2048-eol`) now assert `phases.close.jurisdiction_notifications[0].jurisdiction` is populated. Field-presence-without-content was the previous shape.
|
|
85
|
+
|
|
86
|
+
### Catalog + skill content
|
|
87
|
+
|
|
88
|
+
- **`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`).
|
|
89
|
+
- **`skills/threat-model-currency/skill.md`** inline `last_threat_review` date aligned to frontmatter (`2026-05-14`).
|
|
90
|
+
|
|
91
|
+
Test count: 941 → 995 (992 pass + 3 skipped). Predeploy gates: 14/14. Skills: 38/38 signed; manifest envelope signed.
|
|
92
|
+
|
|
3
93
|
## 0.12.21 — 2026-05-14
|
|
4
94
|
|
|
5
95
|
**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.**
|
|
@@ -8,7 +98,7 @@
|
|
|
8
98
|
|
|
9
99
|
`CVE-2026-46300` (Fragnesia) added — a Linux kernel local privilege escalation disclosed 2026-05-13 by William Bowling / V12 security team. CVSS 7.8 / AV:L. The flaw is in the kernel XFRM ESP-in-TCP path: `skb_try_coalesce()` fails to propagate `SKBFL_SHARED_FRAG` when transferring paged fragments between socket buffers. An unprivileged user can deterministically rewrite read-only page-cache pages without modifying on-disk bytes — no race condition required. A public proof-of-concept demonstrates root shell via `/usr/bin/su`. Mitigation: blacklist or unload `esp4`, `esp6`, `rxrpc` kernel modules (the same set already documented for CVE-2026-31431); AlmaLinux + CloudLinux ship patched kernels in testing; live-patch is available via Canonical Livepatch, kpatch, kGraft, and CloudLinux KernelCare. RWEP today: 20 (will jump to 45 on CISA KEV listing).
|
|
10
100
|
|
|
11
|
-
The `kernel`, `runtime`, and `hardening` playbooks now reference Fragnesia in `domain.cve_refs[]`.
|
|
101
|
+
The `kernel`, `runtime`, and `hardening` playbooks now reference Fragnesia in `domain.cve_refs[]`. Six skills carry cross-references: `kernel-lpe-triage`, `exploit-scoring`, `compliance-theater`, `framework-gap-analysis`, `zeroday-gap-learn`, `threat-model-currency`. `data/zeroday-lessons.json` adds three new control requirements that codify the lesson: page-cache integrity verification (file-integrity tools hashing on-disk bytes miss this class), bug-family mitigation persistence (operators who blacklisted modules for the parent bug remain mitigated for the sequel), and scanner paper-compliance test (a "patched" vulnerability-scanner report based on kernel-package version misses the module-unload mitigation surface).
|
|
12
102
|
|
|
13
103
|
### Trust chain
|
|
14
104
|
|
|
@@ -68,10 +158,9 @@ The `kernel`, `runtime`, and `hardening` playbooks now reference Fragnesia in `d
|
|
|
68
158
|
|
|
69
159
|
### Tests
|
|
70
160
|
|
|
71
|
-
- New
|
|
72
|
-
-
|
|
73
|
-
- `
|
|
74
|
-
- `tests/operator-bugs.test.js` — `#87 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.
|
|
161
|
+
- New regression coverage for every closure above.
|
|
162
|
+
- 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.
|
|
163
|
+
- `#87 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.
|
|
75
164
|
|
|
76
165
|
### Skill content
|
|
77
166
|
|
|
@@ -82,21 +171,11 @@ The `kernel`, `runtime`, and `hardening` playbooks now reference Fragnesia in `d
|
|
|
82
171
|
|
|
83
172
|
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.
|
|
84
173
|
|
|
85
|
-
###
|
|
86
|
-
|
|
87
|
-
A scrub across 19 shipped source files (`bin/`, `lib/`, `scripts/`) removed 101 internal-vocabulary references (`(audit X PN-N)`, `// Audit Y PN-N: ...`, `v0.12.X (audit Z PN-N):`). The remaining behavior-framing comments describe the change itself; the surrounding context (version pin, WHY) is preserved where it carries operator value.
|
|
88
|
-
|
|
89
|
-
### Operator action required
|
|
174
|
+
### Source comments
|
|
90
175
|
|
|
91
|
-
|
|
92
|
-
```
|
|
93
|
-
gh secret set NPM_TOKEN --env npm-publish --body "<paste npm automation token>"
|
|
94
|
-
gh secret list --env npm-publish # verify
|
|
95
|
-
gh secret delete NPM_TOKEN --org blamejs # AFTER verifying the env-scoped one is picked up
|
|
96
|
-
```
|
|
97
|
-
The repo-side wiring (`release.yml` declares `environment: npm-publish` on the publish job; the env has the `tag: v*.*.*` deploy filter) is already in place.
|
|
176
|
+
Cleanup pass across `bin/`, `lib/`, `scripts/` — comments now describe behavior, not work-stream.
|
|
98
177
|
|
|
99
|
-
Test count: 840 →
|
|
178
|
+
Test count: 840 → 941 (938 pass + 3 skipped). Predeploy gates: 14/14. Skills: 38/38 signed; manifest envelope signed.
|
|
100
179
|
|
|
101
180
|
## 0.12.20 — 2026-05-14
|
|
102
181
|
|
|
@@ -110,7 +189,7 @@ The v0.12.19 engine fix blocks `detection_classification: 'detected'` agent over
|
|
|
110
189
|
- `16-containers-root-user`: attest `dockerfile-curl-pipe-bash` (3 checks; `dockerfile-runs-as-root` was already attested)
|
|
111
190
|
- `19-crypto-rsa-2048-eol`: attest `openssl-pre-3-5` + `ml-dsa-slh-dsa-absent` (3 + 3)
|
|
112
191
|
|
|
113
|
-
|
|
192
|
+
v0.12.20 ships the v0.12.19 trust-chain + engine + bundle + concurrency closures plus the scenario updates.
|
|
114
193
|
|
|
115
194
|
## 0.12.19 — 2026-05-14
|
|
116
195
|
|
|
@@ -553,7 +632,7 @@ Test count: 492 → 573 (+81 across engine, sign/verify, refresh-external, prefe
|
|
|
553
632
|
|
|
554
633
|
## 0.12.11 — 2026-05-13
|
|
555
634
|
|
|
556
|
-
**Patch: OSV source hardening, indicator regex widening, CWE/framework-gap reconciliation
|
|
635
|
+
**Patch: OSV source hardening, indicator regex widening, CWE/framework-gap reconciliation.**
|
|
557
636
|
|
|
558
637
|
### OSV source hardening
|
|
559
638
|
|
|
@@ -628,7 +707,7 @@ Test count: 441 → 459 (+18: OSV source tests + matching test references for Ha
|
|
|
628
707
|
|
|
629
708
|
## 0.12.9 — 2026-05-13
|
|
630
709
|
|
|
631
|
-
**Patch:
|
|
710
|
+
**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.**
|
|
632
711
|
|
|
633
712
|
### Hard Rule #15 — diff-coverage gate is now blocking
|
|
634
713
|
|
|
@@ -680,7 +759,7 @@ Five entries reconciled against authoritative public sources as of 2026-05-13:
|
|
|
680
759
|
|
|
681
760
|
Each correction carries an inline `*_correction_note` field with the source URL and the rationale for downstream auditors. Two new CVEs surfaced by the freshness sweep (CVE-2026-42208 LiteLLM SQLi on KEV; CVE-2026-39884 mcp-server-kubernetes argument injection) are deferred to a follow-up patch — each warrants its own Hard Rule #14 primary-source IoC review.
|
|
682
761
|
|
|
683
|
-
### v0.12.8
|
|
762
|
+
### Two v0.12.8 CLI fixes recovered
|
|
684
763
|
|
|
685
764
|
Two claims in the v0.12.8 CHANGELOG were not actually on disk in the squash commit, lost during the v0.12.8 recovery flow:
|
|
686
765
|
|
|
@@ -711,7 +790,7 @@ Test count: 418 → 439. Predeploy gates: 15/15 (gate 15 now blocking). Skills:
|
|
|
711
790
|
|
|
712
791
|
## 0.12.8 — 2026-05-13
|
|
713
792
|
|
|
714
|
-
**Patch:
|
|
793
|
+
**Patch: CLI surface fixes, catalog completeness, test infrastructure hardening, AGENTS.md Hard Rule #15.**
|
|
715
794
|
|
|
716
795
|
### Hard Rule #15 — Test coverage on every diff
|
|
717
796
|
|
|
@@ -808,7 +887,7 @@ mcp playbook bumped 1.2.0 → 1.3.0. threat_currency_score stays at 98. `last_th
|
|
|
808
887
|
|
|
809
888
|
## 0.12.6 — 2026-05-13
|
|
810
889
|
|
|
811
|
-
**Patch: primary-source IoC
|
|
890
|
+
**Patch: primary-source IoC review across the catalog — five CVEs reviewed line-level against published exploit source. AGENTS.md Hard Rule #14 added.**
|
|
812
891
|
|
|
813
892
|
Five research agents dispatched in parallel to cross-reference our IoC list for each catalogued CVE against published exploit source / vendor advisories / researcher writeups. Roughly 60 IoCs added, one major CVSS correction, two CVEs gained an `iocs` block where they previously had `null`.
|
|
814
893
|
|
package/CONTEXT.md
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
# exceptd Security — AI Context
|
|
2
2
|
|
|
3
|
-
This file gives any AI assistant the context it needs to use this
|
|
3
|
+
This file gives any AI assistant the context it needs to use this repository effectively. It is AI-system-agnostic and does not assume any particular assistant runtime.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
## What This Repository Is
|
|
8
8
|
|
|
9
|
-
exceptd Security
|
|
9
|
+
exceptd Security ships two interlocking surfaces grounded in mid-2026 threat reality:
|
|
10
10
|
|
|
11
|
-
**
|
|
11
|
+
1. **Skills** — Markdown instruction files telling an AI assistant how to perform a specific security analysis (what questions to ask, what data to query, how to score risk, what output to produce).
|
|
12
|
+
2. **Playbooks** — JSON specifications of attack-class investigations executed by the CLI engine through a seven-phase contract (govern → direct → look → detect → analyze → validate → close).
|
|
13
|
+
|
|
14
|
+
**The core insight:** Every major compliance framework (NIST 800-53, ISO 27001, SOC 2, PCI-DSS) was written for environments that no longer describe how attacks happen. Both skills and playbooks explicitly map where framework coverage ends and real attacker capability begins.
|
|
12
15
|
|
|
13
16
|
---
|
|
14
17
|
|
|
@@ -33,42 +36,96 @@ attack_refs: # MITRE ATT&CK TTP IDs referenced
|
|
|
33
36
|
- T1068
|
|
34
37
|
framework_gaps: # Framework controls this skill exposes as insufficient
|
|
35
38
|
- NIST-800-53-SI-2
|
|
36
|
-
|
|
39
|
+
rfc_refs: # IETF RFC / Internet-Draft references
|
|
40
|
+
- RFC-8446
|
|
41
|
+
cwe_refs: # Root-cause weakness classes
|
|
42
|
+
- CWE-787
|
|
43
|
+
d3fend_refs: # MITRE D3FEND defensive techniques
|
|
44
|
+
- D3-EAL
|
|
45
|
+
dlp_refs: # DLP control IDs (DLP-relevant skills only)
|
|
46
|
+
- DLP-CHAN-LLM-PROMPT
|
|
47
|
+
forward_watch: # Upcoming changes to monitor for skill updates
|
|
37
48
|
- FIPS 206 finalization
|
|
38
|
-
last_threat_review:
|
|
39
|
-
"2026-05-01"
|
|
49
|
+
last_threat_review: "2026-05-01"
|
|
40
50
|
```
|
|
41
51
|
|
|
42
52
|
### Skill Body Structure
|
|
43
53
|
|
|
44
|
-
|
|
54
|
+
Required sections (every shipped skill):
|
|
45
55
|
|
|
46
|
-
1. **Threat Context** —
|
|
47
|
-
2. **Framework Lag Declaration** —
|
|
56
|
+
1. **Threat Context** — current exploitation reality, not theoretical risk
|
|
57
|
+
2. **Framework Lag Declaration** — per-framework gap statements with specific control IDs
|
|
48
58
|
3. **TTP Mapping** — ATLAS/ATT&CK IDs with framework coverage gap flags
|
|
49
|
-
4. **Exploit Availability Matrix** — PoC status, KEV listing, AI-acceleration factor
|
|
50
|
-
5. **Analysis Procedure** —
|
|
51
|
-
6. **Output Format** —
|
|
52
|
-
7. **Compliance Theater Check** —
|
|
59
|
+
4. **Exploit Availability Matrix** — PoC status, KEV listing, AI-acceleration factor, live-patchability
|
|
60
|
+
5. **Analysis Procedure** — step-by-step instructions, threading defense-in-depth, least privilege, and zero trust as foundational design principles (not optional considerations)
|
|
61
|
+
6. **Output Format** — exact structure the analysis should produce
|
|
62
|
+
7. **Compliance Theater Check** — specific test distinguishing paper compliance from real posture
|
|
63
|
+
|
|
64
|
+
Required 8th section for skills shipped on or after 2026-05-11 (pre-existing skills exempt until next minor bump):
|
|
65
|
+
|
|
66
|
+
8. **Defensive Countermeasure Mapping** — maps offensive findings to MITRE D3FEND IDs with explicit defense-in-depth layer position, least-privilege scope, zero-trust posture, and AI-pipeline applicability.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Playbooks and the Seven-Phase Contract
|
|
71
|
+
|
|
72
|
+
Playbooks live at `data/playbooks/<id>.json` and are executed by the CLI engine. Each playbook is an attack-class investigation that walks a govern → direct → look → detect → analyze → validate → close loop.
|
|
73
|
+
|
|
74
|
+
Thirteen playbooks ship today:
|
|
75
|
+
|
|
76
|
+
| Playbook | Attack class |
|
|
77
|
+
|---|---|
|
|
78
|
+
| `ai-api` | AI API as covert C2 |
|
|
79
|
+
| `containers` | Container escape |
|
|
80
|
+
| `cred-stores` | Credential-store abuse |
|
|
81
|
+
| `crypto` | PQC exposure / HNDL |
|
|
82
|
+
| `crypto-codebase` | Crypto misuse in source |
|
|
83
|
+
| `framework` | Compliance theater (pure-analyze; correlates other playbooks' findings) |
|
|
84
|
+
| `hardening` | Kernel / OS hardening posture |
|
|
85
|
+
| `kernel` | Kernel LPE |
|
|
86
|
+
| `library-author` | Upstream library supply-chain posture |
|
|
87
|
+
| `mcp` | MCP supply chain |
|
|
88
|
+
| `runtime` | Runtime tamper |
|
|
89
|
+
| `sbom` | SBOM / dependency supply chain |
|
|
90
|
+
| `secrets` | DLP exfiltration |
|
|
91
|
+
|
|
92
|
+
Phase contract:
|
|
93
|
+
|
|
94
|
+
| Phase | Purpose | CLI surface |
|
|
95
|
+
|---|---|---|
|
|
96
|
+
| 1 govern | Operator consent + jurisdiction clocks (NIS2 24h, DORA 4h, GDPR 72h, etc.) | `exceptd brief <playbook> --phase govern` |
|
|
97
|
+
| 2 direct | Threat-context briefing + skill chain + RWEP threshold | `exceptd brief <playbook> --phase direct` |
|
|
98
|
+
| 3 look | Artifacts and indicators to gather; air-gap alternates | `exceptd brief <playbook> --phase look` |
|
|
99
|
+
| 4 detect | AI applies indicators to captured evidence; runs every required false-positive check | walked inline by the assistant |
|
|
100
|
+
| 5 analyze | Correlate hits → findings | `exceptd run <playbook> --evidence -` |
|
|
101
|
+
| 6 validate | Priority-sorted remediation paths + validation tests + residual-risk statement | (part of `run`) |
|
|
102
|
+
| 7 close | CSAF-2.0 bundle + jurisdiction notification drafts + auditor-ready exception language + `feeds_into` chaining | (part of `run`) |
|
|
103
|
+
|
|
104
|
+
Preconditions encode hard refuse-to-run conditions: `threat_currency_score < 50` hard-blocks unless `--force-stale`; `_meta.mutex` refuses concurrent conflicting playbooks; `--air-gap` substitutes `air_gap_alternative` source paths.
|
|
105
|
+
|
|
106
|
+
Attestations persist at `.exceptd/attestations/<session_id>/attestation.json` and can be replayed against the stored evidence with `exceptd reattest <session-id>` (drift verdict) or inspected with `exceptd attest verify|show|list|diff`.
|
|
53
107
|
|
|
54
108
|
---
|
|
55
109
|
|
|
56
110
|
## Data Files
|
|
57
111
|
|
|
58
|
-
Skills read from `data/`.
|
|
59
|
-
|
|
60
|
-
| File | Purpose |
|
|
61
|
-
|
|
62
|
-
| `cve-catalog.json` |
|
|
63
|
-
| `atlas-ttps.json` | MITRE ATLAS v5.1.0 (November 2025) techniques
|
|
64
|
-
| `
|
|
65
|
-
| `
|
|
66
|
-
| `
|
|
67
|
-
| `
|
|
68
|
-
| `
|
|
69
|
-
| `
|
|
70
|
-
| `
|
|
71
|
-
| `
|
|
112
|
+
Skills and playbooks read from `data/`. Authoritative catalog inventory:
|
|
113
|
+
|
|
114
|
+
| File | Entries | Purpose |
|
|
115
|
+
|------|---------|---------|
|
|
116
|
+
| `cve-catalog.json` | 10 | CVEs with CVSS, RWEP score, EPSS estimates, CISA KEV flags, PoC and live-patch availability |
|
|
117
|
+
| `atlas-ttps.json` | 15 | MITRE ATLAS v5.1.0 (November 2025) techniques with framework gap flags |
|
|
118
|
+
| `attack-techniques.json` | 79 | MITRE ATT&CK techniques with framework coverage mappings |
|
|
119
|
+
| `framework-control-gaps.json` | 62 | Framework control gap entries: designed-for vs. what each control misses |
|
|
120
|
+
| `exploit-availability.json` | 10 | Per-CVE PoC locations, weaponization stage, AI-acceleration factor, live-patch status |
|
|
121
|
+
| `global-frameworks.json` | 35 jurisdictions | Patch SLAs and notification windows across global regulatory regimes |
|
|
122
|
+
| `zeroday-lessons.json` | 10 | Learning-loop entries: zero-day → attack vector → control gap → framework gap → new control |
|
|
123
|
+
| `cwe-catalog.json` | 55 | CWE v4.17 entries (Top 25 2024 plus AI- and supply-chain-relevant weaknesses) |
|
|
124
|
+
| `d3fend-catalog.json` | 28 | MITRE D3FEND v1.0.0 defensive techniques for offensive → defensive mapping |
|
|
125
|
+
| `rfc-references.json` | 31 | IETF RFC / Internet-Draft references with status, errata count, replaces / replaced-by, `last_verified` dates |
|
|
126
|
+
| `dlp-controls.json` | 22 | DLP control entries indexed by channel, classifier, surface, enforcement mode, evidence type |
|
|
127
|
+
| `playbooks/` | 13 | Playbook specifications (see above) |
|
|
128
|
+
| `_indexes/` | 17 derived files | Pre-computed indexes built by `npm run build-indexes` |
|
|
72
129
|
|
|
73
130
|
---
|
|
74
131
|
|
|
@@ -77,15 +134,16 @@ Skills read from `data/`. These are the authoritative data sources:
|
|
|
77
134
|
To use a skill, match its trigger phrases and follow its Analysis Procedure. Example invocations:
|
|
78
135
|
|
|
79
136
|
```
|
|
80
|
-
kernel-lpe-triage —
|
|
137
|
+
kernel-lpe-triage — Linux kernel LPE exposure
|
|
81
138
|
ai-attack-surface — AI/ML attack surface assessment
|
|
82
|
-
framework-gap-analysis —
|
|
83
|
-
compliance-theater —
|
|
84
|
-
global-grc NIS2 —
|
|
139
|
+
framework-gap-analysis — control ID + threat → gap statement
|
|
140
|
+
compliance-theater — detect audit-passing ≠ real-secure
|
|
141
|
+
global-grc NIS2 — map a threat to NIS2 + companion jurisdictions
|
|
85
142
|
exploit-scoring CVE-2026-31431 — RWEP score with full factor breakdown
|
|
86
|
-
security-maturity-tiers — MVP / Practical / Overkill roadmap
|
|
87
|
-
zeroday-gap-learn CVE-... —
|
|
88
|
-
pqc-first —
|
|
143
|
+
security-maturity-tiers — MVP / Practical / Overkill roadmap
|
|
144
|
+
zeroday-gap-learn CVE-... — zero-day learning loop on a new CVE
|
|
145
|
+
pqc-first — post-quantum cryptography readiness
|
|
146
|
+
researcher — front-door dispatcher for raw threat intel
|
|
89
147
|
```
|
|
90
148
|
|
|
91
149
|
---
|
|
@@ -119,39 +177,26 @@ This repository uses the term "compliance theater" for a specific, measurable co
|
|
|
119
177
|
|
|
120
178
|
Seven documented patterns:
|
|
121
179
|
1. **Patch Management Theater** — meets framework SLA, still exposed to active exploitation
|
|
122
|
-
2. **AI Access Control Theater** — service account
|
|
123
|
-
3. **Vendor Management Theater** — vendor controls pass audit;
|
|
124
|
-
4. **Malware Protection Theater** — signatures
|
|
125
|
-
5. **Supply Chain Theater** — software supply chain passes review; developer-installed AI plugins
|
|
126
|
-
6. **Encryption Theater** — classical encryption
|
|
127
|
-
7. **Detection Theater** — monitoring
|
|
180
|
+
2. **AI Access Control Theater** — service account compliant; prompt injection bypasses it entirely
|
|
181
|
+
3. **Vendor Management Theater** — vendor controls pass audit; MCP plugins are out of scope
|
|
182
|
+
4. **Malware Protection Theater** — signatures current; AI-generated novel code evades all signatures
|
|
183
|
+
5. **Supply Chain Theater** — software supply chain passes review; developer-installed AI plugins excluded
|
|
184
|
+
6. **Encryption Theater** — classical encryption compliant; HNDL exposure unaddressed
|
|
185
|
+
7. **Detection Theater** — monitoring compliant; AI C2 channels and AI-querying malware not detected
|
|
128
186
|
|
|
129
|
-
Run `lib/framework-gap.js` → `theaterCheck()`
|
|
187
|
+
Run `lib/framework-gap.js` → `theaterCheck()` for programmatic detection. The `framework` playbook surfaces these patterns across an entire estate by correlating findings from other playbooks.
|
|
130
188
|
|
|
131
189
|
---
|
|
132
190
|
|
|
133
|
-
##
|
|
134
|
-
|
|
135
|
-
The `orchestrator/` directory provides:
|
|
136
|
-
- **Scanner** — discovers kernel versions, MCP configs, crypto posture, framework claims
|
|
137
|
-
- **Dispatcher** — routes scanner findings to relevant skills via manifest triggers
|
|
138
|
-
- **Pipeline** — coordinates `threat-researcher` → `source-validator` → `skill-updater` → `report-generator`
|
|
139
|
-
- **Event bus** — triggers skill updates on CISA KEV additions, ATLAS releases, framework amendments
|
|
140
|
-
- **Scheduler** — runs weekly currency checks and annual full audits
|
|
141
|
-
|
|
142
|
-
Entry point: `node orchestrator/index.js`
|
|
191
|
+
## Agents vs. Skills vs. Playbooks
|
|
143
192
|
|
|
144
|
-
|
|
193
|
+
Three distinct artifact types:
|
|
145
194
|
|
|
146
|
-
|
|
195
|
+
- **`skills/<name>/skill.md`** — user-invoked, matched by trigger phrases, interactive front door.
|
|
196
|
+
- **`data/playbooks/<id>.json`** — engine-executed attack-class investigations, structured seven-phase output.
|
|
197
|
+
- **`agents/<name>/`** — pipeline workers (`threat-researcher`, `source-validator`, `skill-updater`, `report-generator`) that run autonomously inside the orchestrator. Not user-invokable.
|
|
147
198
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
Naming convention to keep straight:
|
|
151
|
-
- `agents/threat-researcher/` — orchestrator pipeline worker (autonomous, background)
|
|
152
|
-
- `skills/researcher/skill.md` — user-invoked triage dispatcher (interactive, front door)
|
|
153
|
-
|
|
154
|
-
They share a thematic name but are different artifacts with different runtimes.
|
|
199
|
+
The `researcher` **skill** (front-door dispatcher) and `threat-researcher` **agent** (background pipeline worker) share a thematic name but are different artifacts with different runtimes. When in doubt, the path tells you which: `skills/researcher/` vs `agents/threat-researcher/`.
|
|
155
200
|
|
|
156
201
|
---
|
|
157
202
|
|
|
@@ -159,28 +204,38 @@ They share a thematic name but are different artifacts with different runtimes.
|
|
|
159
204
|
|
|
160
205
|
### How to Load Skills
|
|
161
206
|
|
|
162
|
-
1. Read `manifest.json`
|
|
207
|
+
1. Read `manifest.json` for the full skill registry
|
|
163
208
|
2. Match user intent against `triggers` arrays
|
|
164
209
|
3. Load the matched `skill.md` into context
|
|
165
210
|
4. Follow the skill's **Analysis Procedure** step by step
|
|
166
|
-
5. Pull data from
|
|
211
|
+
5. Pull data from referenced `data_deps` files as needed
|
|
167
212
|
6. Produce output matching the skill's **Output Format**
|
|
168
213
|
|
|
214
|
+
### How to Walk a Playbook
|
|
215
|
+
|
|
216
|
+
1. `exceptd brief` (no args) lists available playbooks; `exceptd brief <id>` returns the full Phase 1+2+3 briefing in one document
|
|
217
|
+
2. Surface the Phase-1 jurisdiction obligations to the operator and wait for ack (use `exceptd brief <id> --phase govern` for just that slice)
|
|
218
|
+
3. `exceptd brief <id> --phase direct` and `--phase look` pull the threat context and indicator set
|
|
219
|
+
4. Walk Phase 4 (detect) inline using local tools; run every required false-positive check
|
|
220
|
+
5. Pipe evidence to `exceptd run <id> --evidence -` for Phases 5–7 (use `exceptd ci` for the gate-only variant in CI pipelines)
|
|
221
|
+
6. Offer to persist the attestation and draft any notification messages
|
|
222
|
+
|
|
169
223
|
### Context Budget Guidance
|
|
170
224
|
|
|
171
|
-
- `manifest.json` — load first
|
|
172
|
-
- `data/cve-catalog.json` — load on demand for
|
|
225
|
+
- `manifest.json` — load first (small, high-value index)
|
|
226
|
+
- `data/cve-catalog.json` — load on demand for CVE-specific analysis
|
|
173
227
|
- `data/framework-control-gaps.json` — load for gap analysis and theater detection
|
|
174
228
|
- `data/global-frameworks.json` — load for multi-jurisdiction questions
|
|
175
|
-
- `data/atlas-ttps.json` — load for
|
|
176
|
-
- Individual skill files — 15–
|
|
229
|
+
- `data/atlas-ttps.json`, `data/attack-techniques.json` — load for TTP-driven work
|
|
230
|
+
- Individual skill files — 15–40 KB each; load on match, not preemptively
|
|
231
|
+
- Playbook JSON — load on demand via `exceptd direct/look`; the engine handles phase orchestration
|
|
177
232
|
|
|
178
233
|
### What This Repo Does Not Contain
|
|
179
234
|
|
|
180
235
|
- No code that executes automatically in your environment
|
|
181
|
-
- No network calls
|
|
236
|
+
- No outbound network calls; all data is local and static (the watchlist surface is read-only)
|
|
182
237
|
- No credentials or keys
|
|
183
|
-
- Skills are instruction text — the AI implements them
|
|
238
|
+
- Skills are instruction text — the AI implements them; playbook execution is governed by the CLI engine
|
|
184
239
|
|
|
185
240
|
---
|
|
186
241
|
|
|
@@ -193,9 +248,11 @@ They share a thematic name but are different artifacts with different runtimes.
|
|
|
193
248
|
| ATLAS | MITRE ATLAS v5.1.0 — AI threat framework |
|
|
194
249
|
| MCP | Model Context Protocol — AI tool integration standard |
|
|
195
250
|
| HNDL | Harvest-Now-Decrypt-Later — quantum threat to current crypto |
|
|
196
|
-
| Framework lag |
|
|
251
|
+
| Framework lag | Gap between what a framework requires and what current TTPs demand |
|
|
197
252
|
| Theater | Audit-passing compliance that doesn't close the real attack path |
|
|
198
253
|
| RWEP 90+ | Priority 1: live-patch or isolate same-day |
|
|
254
|
+
| Seven-phase | govern → direct → look → detect → analyze → validate → close |
|
|
255
|
+
| CSAF-2.0 | Common Security Advisory Framework — Phase-7 output bundle format |
|
|
199
256
|
| Copy Fail | CVE-2026-31431 — RWEP 90, CISA KEV, 732-byte deterministic root |
|
|
200
257
|
| Dirty Frag | CVE-2026-43284/43500 — IPsec subsystem LPE chain |
|
|
201
258
|
| SesameOp | AI API as covert C2 channel (ATLAS AML.T0096) |
|