@blamejs/exceptd-skills 0.12.41 → 0.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +124 -0
- package/bin/exceptd.js +52 -44
- package/data/_indexes/_meta.json +49 -49
- package/data/_indexes/activity-feed.json +2 -2
- package/data/_indexes/catalog-summaries.json +2 -2
- package/data/_indexes/chains.json +1531 -575
- package/data/_indexes/jurisdiction-map.json +15 -4
- package/data/_indexes/section-offsets.json +1244 -1244
- package/data/_indexes/token-budget.json +173 -173
- package/data/atlas-ttps.json +55 -11
- package/data/attack-techniques.json +124 -19
- package/data/cve-catalog.json +194 -27
- package/data/cwe-catalog.json +15 -5
- package/data/framework-control-gaps.json +32 -10
- package/data/playbooks/ai-api.json +5 -0
- package/data/playbooks/cicd-pipeline-compromise.json +970 -0
- package/data/playbooks/cloud-iam-incident.json +4 -1
- package/data/playbooks/cred-stores.json +10 -0
- package/data/playbooks/framework.json +16 -0
- package/data/playbooks/hardening.json +4 -0
- package/data/playbooks/identity-sso-compromise.json +951 -0
- package/data/playbooks/idp-incident.json +3 -0
- package/data/playbooks/kernel.json +6 -0
- package/data/playbooks/llm-tool-use-exfil.json +963 -0
- package/data/playbooks/mcp.json +6 -0
- package/data/playbooks/runtime.json +4 -0
- package/data/playbooks/sbom.json +13 -0
- package/data/playbooks/secrets.json +6 -0
- package/data/playbooks/webhook-callback-abuse.json +916 -0
- package/data/zeroday-lessons.json +178 -0
- package/lib/cross-ref-api.js +33 -13
- package/lib/cve-curation.js +12 -1
- package/lib/exit-codes.js +29 -0
- package/lib/lint-skills.js +24 -2
- package/lib/refresh-external.js +17 -1
- package/lib/scoring.js +55 -0
- package/lib/source-advisories.js +281 -0
- package/manifest.json +83 -83
- package/orchestrator/index.js +207 -24
- package/package.json +1 -1
- package/sbom.cdx.json +134 -79
- package/scripts/predeploy.js +7 -13
- package/scripts/refresh-reverse-refs.js +86 -0
- package/scripts/refresh-sbom.js +21 -4
- package/skills/age-gates-child-safety/skill.md +1 -5
- package/skills/ai-attack-surface/skill.md +11 -4
- package/skills/ai-c2-detection/skill.md +11 -2
- package/skills/ai-risk-management/skill.md +4 -2
- package/skills/api-security/skill.md +7 -8
- package/skills/attack-surface-pentest/skill.md +2 -2
- package/skills/cloud-iam-incident/skill.md +1 -5
- package/skills/cloud-security/skill.md +0 -4
- package/skills/compliance-theater/skill.md +10 -2
- package/skills/container-runtime-security/skill.md +1 -3
- package/skills/dlp-gap-analysis/skill.md +3 -4
- package/skills/email-security-anti-phishing/skill.md +1 -8
- package/skills/exploit-scoring/skill.md +7 -2
- package/skills/framework-gap-analysis/skill.md +1 -1
- package/skills/fuzz-testing-strategy/skill.md +1 -2
- package/skills/global-grc/skill.md +3 -2
- package/skills/identity-assurance/skill.md +1 -3
- package/skills/idp-incident-response/skill.md +1 -4
- package/skills/incident-response-playbook/skill.md +1 -5
- package/skills/kernel-lpe-triage/skill.md +2 -2
- package/skills/mcp-agent-trust/skill.md +13 -3
- package/skills/mlops-security/skill.md +2 -3
- package/skills/ot-ics-security/skill.md +0 -3
- package/skills/policy-exception-gen/skill.md +11 -3
- package/skills/pqc-first/skill.md +4 -2
- package/skills/rag-pipeline-security/skill.md +2 -0
- package/skills/ransomware-response/skill.md +1 -5
- package/skills/researcher/skill.md +4 -3
- package/skills/sector-energy/skill.md +0 -4
- package/skills/sector-federal-government/skill.md +2 -3
- package/skills/sector-financial/skill.md +1 -4
- package/skills/sector-healthcare/skill.md +0 -5
- package/skills/sector-telecom/skill.md +0 -4
- package/skills/security-maturity-tiers/skill.md +1 -2
- package/skills/skill-update-loop/skill.md +4 -3
- package/skills/supply-chain-integrity/skill.md +4 -3
- package/skills/threat-model-currency/skill.md +1 -1
- package/skills/threat-modeling-methodology/skill.md +2 -1
- package/skills/webapp-security/skill.md +0 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,129 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.13.1 — 2026-05-17
|
|
4
|
+
|
|
5
|
+
Threat-intake gap closure. Driven by the post-mortem on CVE-2026-46333 (ssh-keysign-pwn) — disclosed 2026-05-14 by Qualys, missed by the toolkit at T+0 through T+3 because the existing source set (KEV, EPSS, NVD, RFC, PINS, GHSA, OSV) sits at the END of the disclosure pipeline. Adds primary-source polling, CVE-class alert surfacing, and seeds two retroactive catalog entries for the disclosures the toolkit should have caught.
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
**`refresh --check-advisories` polls 4 primary-source feeds.** New `ADVISORIES_SOURCE` in `lib/source-advisories.js` polls Qualys TRU RSS, Red Hat RHSA CSAF index, Ubuntu USN RSS, and Zero Day Initiative published-advisories RSS. Surfaces CVE IDs disclosed at T+0 to T+1 that lag NVD enrichment by 3-14 days. Report-only by design: the source emits structured `diffs[]` with `{cve_id, sources[], advisory_urls[], disclosed_at, title}` but does NOT auto-mutate the catalog. Operators route promising CVE IDs through the existing `refresh --advisory <CVE-ID>` enrichment path. Deduplicates across feeds (a CVE cited in both Qualys and USN collapses to one diff with two source attributions). Fixture-mode (`ctx.fixtures.advisories`) + cache-mode (`<cacheDir>/advisories/<feed>.xml`) for offline test reproducibility.
|
|
10
|
+
|
|
11
|
+
**`exceptd watchlist --alerts` surfaces CVE-class pattern matches.** Re-scopes `watchlist` from "skills forward_watch aggregation" to "CVE catalog pattern alerts" when `--alerts` is passed. 5 patterns ship in v0.13.1:
|
|
12
|
+
- `kernel_lpe_with_poc` (high) — Linux kernel LPE class with public PoC + `blast_radius >= 25`
|
|
13
|
+
- `supply_chain_family` (high) — `MAL-*` entries or `type: malicious-*`
|
|
14
|
+
- `ai_discovered_kev` (high) — AI-discovered AND on CISA KEV
|
|
15
|
+
- `active_exploitation_unpatched` (critical) — confirmed in-the-wild + no patch available
|
|
16
|
+
- `recent_poc_no_kev_yet` (medium) — public PoC verified within 14 days, not yet KEV-listed
|
|
17
|
+
|
|
18
|
+
Output sorts critical-severity first, then by RWEP descending. JSON envelope shape matches the v0.13.0 harmonization contract `{ok, verb, mode, generated_at, patterns_evaluated, entries_scanned, alert_count, alerts[]}`.
|
|
19
|
+
|
|
20
|
+
**Daily scheduled threat-intake routine.** A `routine: exceptd-threat-intake` (claude.ai remote agent) runs daily at 14:00 UTC (07:00 PDT). Sequence: `npm install` → `refresh --check-advisories` → `watchlist --alerts` → `refresh --apply` → `refresh --advisory <CVE-ID>` for up to 5 new CVE IDs from the primary-source feeds → re-sign + rebuild-indexes if catalog mutated → commit on `intake/<YYYY-MM-DD>` branch with full diff in the report. Closes the cadence-gap that left the toolkit dependent on operator-triggered intake. Operator-managed at https://claude.ai/code/routines.
|
|
21
|
+
|
|
22
|
+
### Bugs
|
|
23
|
+
|
|
24
|
+
**Two retroactive catalog seeds for the post-mortem disclosures.**
|
|
25
|
+
|
|
26
|
+
`CVE-2026-46333` (ssh-keysign-pwn) — Linux kernel ptrace exit-race. `exit_mm()` runs before `exit_files()` during privileged-process shutdown; the pre-fix `__ptrace_may_access()` skipped its `get_dumpable()` check when `task->mm == NULL`, leaving a microsecond window where an unprivileged attacker can race `ssh-keysign` or `chage` exit + use `pidfd_getfd(2)` to duplicate root-owned file descriptors and read `/etc/ssh/ssh_host_*_key` or `/etc/shadow`. Two public PoCs from `_SiCk` (2026-05-14). Upstream fix commit `31e62c2ebbfd` merged 2026-05-14; kernel point releases 2026-05-15. RWEP 30 (no KEV yet; +20 PoC, +25 blast_radius, -15 patch; reboot-required). 6-year dormant logic bug — originally surfaced in a 2020 Jann Horn patch proposal that was never merged. Yama `ptrace_scope` is NOT a compensating control (bypass is at the kernel access-check layer, not the LSM layer). Mitigation matrix: patch + reboot (preferred) | KernelCare livepatch when released | `sysctl kernel.user_ptrace=0` | SUID removal from `ssh-keysign` + `chage`. Matching `zeroday-lessons.json` entry adds two new control requirements: `NEW-CTRL-048` (kernel-exit-race-CVE-class audit monitoring) + `NEW-CTRL-049` (SUID minimization for kernel-LPE carrier binaries).
|
|
27
|
+
|
|
28
|
+
`MAL-2026-SHAI-HULUD-OSS` — TeamPCP open-sourced the Shai-Hulud worm framework to GitHub on 2026-05-12 under MIT license, paired with a BreachForums $1,000 USD (Monero) bounty contest for downstream supply-chain impact. The September 2025 / November 2025 / May 2026 "Mini Shai-Hulud" waves are the in-the-wild adoption signal. Modular TypeScript / Bun toolkit for credential harvesting (AWS / GCP / Azure / GitHub / AI-assistant configs) + supply-chain poisoning + encrypted exfil; targets CI/CD pipelines and developer workstations. Self-replicates via maintainer-token-pivot: stolen npm token authenticates as compromised maintainer, enumerates other packages owned, publishes malicious versions. **Explicitly targets AI-coding-assistant config files** — reads `~/.cursor/mcp.json`, `~/.codeium/windsurf/mcp_config.json`, `~/.claude/settings.json`, and installs Claude Code startup hooks for persistence. IoC pattern: GitHub repos named "A Gift From TeamPCP", commit timestamps falsified to 2099-01-01, accounts `agwagwagwa` / `headdirt` / `tmechen`. RWEP 70 (active exploitation confirmed via Mini Shai-Hulud wave; copycat modifications observed within hours of release; AI-assist factor for the framework itself). Matching `zeroday-lessons.json` entry adds three new control requirements: `NEW-CTRL-050` (AI-assistant config-file permission lockdown to 0o600) + `NEW-CTRL-051` (npm publish token workstation isolation) + `NEW-CTRL-052` (GitHub repo-pattern monitoring for exfil channels). `MAL-2026-TANSTACK-MINI` cross-referenced as a Mini-Shai-Hulud-wave incident predating the public framework release by ~24h.
|
|
29
|
+
|
|
30
|
+
### Internal
|
|
31
|
+
|
|
32
|
+
- 24 new tests in `tests/source-advisories.test.js` (18 tests covering parsers + the SOURCE contract) + `tests/watchlist-alerts.test.js` (6 tests covering envelope shape, pattern coverage, sort order, anchor surfaces).
|
|
33
|
+
- The schedule-agent setup is operational — no code change to ship; documented in this entry for operator awareness.
|
|
34
|
+
- Phase A of the post-mortem fix landed in this release; primary-source polling and alert surfacing close the "T+0-to-T+3 disclosure → catalog" gap from the 3-source-set side. The remaining cadence-gap (operator-triggered intake) is closed by the scheduled remote agent.
|
|
35
|
+
|
|
36
|
+
## 0.13.0 — 2026-05-17
|
|
37
|
+
|
|
38
|
+
Minor release. Breaking-change bundle for the v0.10.x legacy-verb removal that has been deprecation-bannered since v0.11.0; envelope harmonization across every JSON-emitting verb; 4 new playbooks expanding the canonical set to 20; engine hardening (factor-shape validation, cache invalidation, fsync-on-rename, deterministic SBOM); schema reverse fields on ATLAS, ATT&CK, and the playbook chain.
|
|
39
|
+
|
|
40
|
+
### Breaking changes — migration required
|
|
41
|
+
|
|
42
|
+
**Five v0.10.x legacy verbs hard-removed: `plan`, `govern`, `direct`, `look`, `ingest`.** They were deprecation-bannered since v0.11.0 and slated-for-removal-in-v0.13 since v0.12.0. Operators on v0.10.x → v0.13.0 now get a structured `ok:false` refusal with the v0.11+ replacement command. Each removal is a pure rename — same underlying capability is reachable via the replacement. Refusal body shape:
|
|
43
|
+
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"ok": false,
|
|
47
|
+
"error": "'plan' was removed in v0.13.0. Use `exceptd brief --all` instead.",
|
|
48
|
+
"verb": "plan",
|
|
49
|
+
"removed_in": "0.13.0",
|
|
50
|
+
"replacement": "brief --all",
|
|
51
|
+
"deprecation_history": "Deprecated in v0.11.0 ... removed in v0.13.0."
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Replacements:
|
|
56
|
+
- `exceptd plan` → `exceptd brief --all`
|
|
57
|
+
- `exceptd govern <pb>` → `exceptd brief <pb> --phase govern`
|
|
58
|
+
- `exceptd direct <pb>` → `exceptd brief <pb> --phase direct`
|
|
59
|
+
- `exceptd look <pb>` → `exceptd brief <pb> --phase look`
|
|
60
|
+
- `exceptd ingest <args>` → `exceptd run <args>`
|
|
61
|
+
|
|
62
|
+
`reattest` and `list-attestations` were also deprecation-bannered but are PRESERVED — they remain canonical short-form routings of `attest diff` / `attest list` and stay functional.
|
|
63
|
+
|
|
64
|
+
The deprecation-banner + tempdir-marker mechanism (added v0.11.0, persisted via `EXCEPTD_DEPRECATION_SHOWN` env var + `exceptd-deprecation-shown-v<X.Y.Z>` tempdir marker) is removed. Pre-v0.13 scripts that pinned the banner shape should remove those assertions.
|
|
65
|
+
|
|
66
|
+
**Orchestrator exit-code class change: usage errors exit 1 (`GENERIC_FAILURE`), not 2 (`DETECTED_ESCALATE`).** Affected verbs: `framework-gap` (missing args), `report <format>` (unknown format), `validate-cves` / `validate-rfcs` (catalog-read failure), `watchlist` (manifest-read failure), `skill <name>` (skill-not-found). Pre-v0.13 these exited 2, colliding with the canonical CI contract where exit 2 means "verb ran and detected an escalation-worthy finding." CI gates wired to branch on exit 2 will need to also accept exit 1 for these verbs, OR pre-validate inputs before invocation.
|
|
67
|
+
|
|
68
|
+
**Envelope harmonization: every JSON-emitting verb now carries top-level `ok` and (where applicable) `verb`.** Pre-v0.13 `brief --all`, `watchlist`, `ci`, `doctor`, `discover`, `attest show`, `attest export`, and `cmdRunMulti` omitted one or both fields inconsistently. `emit()` now defaults `ok: true` when not set (symmetric to the existing `ok: false → exit 1` fallback), and per-verb call sites set `verb: "..."` explicitly. Consumers that parsed bodies for the absence of these fields will break; consumers reading specific known fields are unaffected.
|
|
69
|
+
|
|
70
|
+
**Orchestrator `ok:false` bodies now land on stdout (not stderr).** Aligns with the bin/exceptd.js convention so a single consumer can parse the verb's envelope without splitting across two streams. Advisory text (`[verb] hint: ...`) still goes to stderr.
|
|
71
|
+
|
|
72
|
+
### Security
|
|
73
|
+
|
|
74
|
+
**`lib/sign.js` `generateKeypair()` ACL-hardening status surfaces in CLI output.** `restrictWindowsAcl()` now returns a boolean; the verdict line announces `Windows ACL hardened: yes|NO` rather than silently warning.
|
|
75
|
+
|
|
76
|
+
**`lib/cve-curation.js` + `lib/refresh-external.js` `writeJsonAtomic()` fsync before rename.** Pre-v0.13 a power loss between the tmp-write and the rename could leave the renamed destination zero-length / partial. The open + write + fsync + close + rename idiom closes the durability gap on both atomic-write helpers.
|
|
77
|
+
|
|
78
|
+
### Features
|
|
79
|
+
|
|
80
|
+
**4 new playbooks expand the canonical set to 20.**
|
|
81
|
+
- `webhook-callback-abuse` — OAuth callback hijack, inbound-webhook signature validation, Slack/Teams/Discord webhook leakage, the Snowflake-class long-lived-callback-token-in-CI-log pattern.
|
|
82
|
+
- `cicd-pipeline-compromise` — self-hosted runner takeover, workflow-injection (the `${{ inputs.* }}` class), third-party Action SHA-pin discipline, OIDC trust-policy abuse, runner-scoped signing keys. Distinct from `sbom` (package-registry supply chain).
|
|
83
|
+
- `identity-sso-compromise` — in-progress IdP-plane detection (Salt Typhoon / Scattered Spider / Okta-2023 / golden-SAML / PRT theft patterns). Detect-side counterpart to the existing `idp-incident` (response playbook).
|
|
84
|
+
- `llm-tool-use-exfil` — agentic-AI tool abuse via prompt injection. Auto-approve-on-high-impact-tool, instruction-coercion grammar in tool responses, unprompted tool chains, credential-shadow in tool args. Distinct from `dlp-exfiltration` (enterprise DLP) and `mcp` (install-time tool trust).
|
|
85
|
+
|
|
86
|
+
Each new playbook carries `threat_currency_score >= 90`, full air-gap alternatives on look artifacts, substantive theater_test blocks on framework gaps, and `feeds_into[]` chains into the existing playbook set.
|
|
87
|
+
|
|
88
|
+
**Schema reverse fields populated across 3 catalogs + playbooks.**
|
|
89
|
+
- ATLAS TTPs now carry `cve_refs[]` (11 entries populated with 21 back-edges from `cve.atlas_refs`).
|
|
90
|
+
- ATT&CK techniques now carry `cve_refs[]` (20 entries populated with 56 back-edges from `cve.attack_refs`).
|
|
91
|
+
- Every playbook now carries `_meta.fed_by[]` (11 playbooks populated with 54 back-edges from `_meta.feeds_into[].playbook_id`). Operators reading a playbook can see what chains INTO it without grepping every other playbook.
|
|
92
|
+
|
|
93
|
+
`scripts/refresh-reverse-refs.js` extends to 8 reverse-direction passes (4 manifest-driven, 2 CVE-driven, 2 catalog-back-edge, 1 playbook-back-edge); `npm run refresh-reverse-refs` rebuilds the full set in one pass.
|
|
94
|
+
|
|
95
|
+
**`lib/scoring.js validate()` refuses mixed Shape A / Shape B factor sets.** The catalog historically stored `rwep_factors` in two distinct shapes (raw booleans + post-weight integers). Mixing shapes inside one entry silently broke the sum invariant — a CVE with `cisa_kev: true, blast_radius: 30` reported rwep 30 instead of the operator-intended 55. The new `detectFactorShape()` helper detects mixed entries and emits a structured error pointing at the affected CVE id.
|
|
96
|
+
|
|
97
|
+
**`lib/cross-ref-api.js` cache invalidation uses (mtime, size) tier.** Pre-v0.13 cache invalidation was mtime-only; on filesystems with 1-2s mtime granularity (FAT32, HFS+ pre-APFS, NFSv3, Docker bind-mounts that proxy mtime) a rapid refresh-then-reload within the same second served stale data. Adding `size` catches every content change that affects byte count.
|
|
98
|
+
|
|
99
|
+
**`lib/lint-skills.js` enforces `last_threat_review` staleness gate.** Warn at >180 days; hard fail at >365 days. Operators with stale skills get a structured warning naming the affected file + the exact day count; year-stale skills fail the lint outright. The forcing function for Hard Rule #8 (which was policy-only pre-v0.13).
|
|
100
|
+
|
|
101
|
+
**`scripts/refresh-sbom.js` produces a deterministic bundle.** `metadata.timestamp` and `serialNumber` are derived from the content-hash seed (`<name>@<version>@<bundleSha>`) instead of wall-clock. Identical content → identical SBOM across re-runs. The SBOM-currency predeploy gate can now rely on byte-identity for the no-change case.
|
|
102
|
+
|
|
103
|
+
**`exceptd doctor --fix` second remediation branch: post-rotate stale signatures.** Continues the v0.12.41 fix. When the private key IS present but the signatures check fails (the `generate-keypair --rotate` followup state), `doctor --fix` runs `sign-all` to re-sign skills + manifest against the current keypair. Without this branch the rotation flow would converge to a broken-but-not-self-healing state.
|
|
104
|
+
|
|
105
|
+
### Bugs
|
|
106
|
+
|
|
107
|
+
**3 catalogs got `last_threat_review` fields backfilled.** `exploit-availability.json`, `global-frameworks.json`, `zeroday-lessons.json` carried `last_updated` but lacked the threat-review timestamp the other 8 catalogs use. All 11 now follow the same shape.
|
|
108
|
+
|
|
109
|
+
**`active_exploitation` field vocabulary now declared in `cve-catalog.json._meta`.** Pre-v0.13 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.
|
|
110
|
+
|
|
111
|
+
**4 CVEs flipped `_draft: false` (verified).** `CVE-2024-3094` (xz-utils backdoor), `CVE-2024-21626` (Leaky Vessels), `CVE-2026-42945` (NGINX Rift), `MAL-2026-TANSTACK-MINI`. 1 quarantined (`MAL-2026-ANTHROPIC-MCP-STDIO` — duplicate of `CVE-2026-30623`). The remaining 15 draft CVEs are now marked with a structured `_draft_reason` ("blocked on missing zeroday-lessons entry" in all 14 cases except the GTIG embargoed placeholder).
|
|
112
|
+
|
|
113
|
+
**Hard Rule #5 regional-framework backfill on 7 skills.** `policy-exception-gen`, `compliance-theater`, `exploit-scoring`, `ai-c2-detection`, `ai-attack-surface`, `mcp-agent-trust`, `api-security` previously cited NIST without one or more of EU/UK/AU/ISO equivalents. Each now carries substantive references to NIS2/DORA/EU AI Act, NCSC CAF, ASD ISM/Essential 8, and ISO 27001:2022 controls as appropriate.
|
|
114
|
+
|
|
115
|
+
**39 of 42 skills got `data_deps` arrays regenerated** from body content references. Pre-v0.13 the array drifted whenever a skill body added or removed a `data/<file>.json` reference without the frontmatter being updated. `api-security` and `email-security-anti-phishing` ended up with empty `data_deps` — their bodies reference no catalog file by name; flagged for v0.14 body-content review.
|
|
116
|
+
|
|
117
|
+
**`scripts/refresh-reverse-refs.js` orphan detection caught 8 framework-gap forward-orphan references introduced by the Hard Rule #5 backfill.** `NIST-800-53-SC-39`, `ISO-27001-2022-A.8.22`, `CIS-Kubernetes-Benchmark-5.7`, `NIST-800-218-SSDF-PW.4`, `NIST-800-53-SR-3`, `SLSA-v1.0-Source-L3`, `NIST-AI-RMF-MAP-3.4`, `OWASP-Top-10-2021-A06`. These are real framework controls cited by the new skill content but absent from the gap catalog; tracked for v0.14 gap-catalog expansion.
|
|
118
|
+
|
|
119
|
+
### Internal
|
|
120
|
+
|
|
121
|
+
- `lib/exit-codes.js` exports `safeExit(code)` — sets `process.exitCode` without calling `process.exit()`. Dispatch surface (`bin/exceptd.js`, `orchestrator/index.js`) converted from `process.exit(N)` to `safeExit(EXIT_CODES.X)` for non-zero codes; `tests/safe-exit-grep.test.js` refuses regressions.
|
|
122
|
+
- `validate-playbooks` predeploy gate flipped from informational to required. 20/20 playbooks validate cleanly.
|
|
123
|
+
- 7 new pinning tests in `tests/v0_12_41-fixes.test.js`, `tests/safe-exit-grep.test.js`, `tests/atlas-version-canonical.test.js`, `tests/operator-leak-grep.test.js`, `tests/verify-shipped-tarball-wrapper.test.js`.
|
|
124
|
+
- Test suite: 1179 total, 1173 pass, 6 skipped (POSIX-only / no-privkey gates), 0 fail.
|
|
125
|
+
- `release.yml` publish-job split (id-token:write vs contents:write separation) and `refresh.yml` split-checkout pattern remain in v0.14 backlog; they're workflow-security hardening with no operator-facing surface change.
|
|
126
|
+
|
|
3
127
|
## 0.12.41 — 2026-05-17
|
|
4
128
|
|
|
5
129
|
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.
|
package/bin/exceptd.js
CHANGED
|
@@ -207,31 +207,46 @@ function suggestVerb(cmd, known) {
|
|
|
207
207
|
// v0.11.0 introduces: brief (collapses plan/govern/direct/look), discover (scan + dispatch),
|
|
208
208
|
// doctor (currency + verify + validate-cves + validate-rfcs), ci (CI gate),
|
|
209
209
|
// ai-run (streaming JSONL), ask (plain-English routing).
|
|
210
|
+
//
|
|
211
|
+
// v0.13.0 removed the v0.10.x phase-name aliases (plan, govern, direct,
|
|
212
|
+
// look, ingest). They were deprecation-bannered since v0.11.0 and
|
|
213
|
+
// slated-for-removal-in-v0.13 since v0.12.0; v0.13 honors that contract.
|
|
214
|
+
// REMOVED_VERBS below carries the rename map for operator-facing refusal
|
|
215
|
+
// hints. `reattest` and `list-attestations` are preserved as canonical
|
|
216
|
+
// routings — they're short forms of `attest diff` / `attest list` that
|
|
217
|
+
// remain operationally useful and have substantial test coverage.
|
|
210
218
|
const PLAYBOOK_VERBS = new Set([
|
|
211
|
-
// v0.11.0 canonical surface:
|
|
212
219
|
"brief", "run", "ai-run", "attest", "discover", "doctor", "ci", "ask",
|
|
213
220
|
"verify-attestation", "run-all", "lint",
|
|
214
|
-
|
|
215
|
-
"plan", "govern", "direct", "look", "ingest", "reattest", "list-attestations",
|
|
221
|
+
"reattest", "list-attestations",
|
|
216
222
|
]);
|
|
217
223
|
|
|
218
|
-
//
|
|
219
|
-
//
|
|
220
|
-
|
|
224
|
+
// v0.13.0: hard-removed legacy verbs. The dispatcher refuses the verb
|
|
225
|
+
// with an actionable replacement hint instead of routing it. Pre-v0.13
|
|
226
|
+
// these were soft-deprecated (banner + still functional); v0.13 removes
|
|
227
|
+
// the routing entirely. Operators upgrading from v0.10.x → v0.13 see
|
|
228
|
+
// the same hint that the deprecation banner previously surfaced, but
|
|
229
|
+
// non-zero exit so scripts noticing pinned-name use fail loudly instead
|
|
230
|
+
// of silently invoking the alias.
|
|
231
|
+
const REMOVED_VERBS = {
|
|
221
232
|
plan: "brief --all",
|
|
222
233
|
govern: "brief <pb> --phase govern",
|
|
223
234
|
direct: "brief <pb> --phase direct",
|
|
224
235
|
look: "brief <pb> --phase look",
|
|
225
236
|
ingest: "run",
|
|
226
|
-
|
|
227
|
-
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
// Renamed but functionally-routed verbs (orchestrator-side dispatch still
|
|
240
|
+
// handles them as of v0.13). Distinct from REMOVED_VERBS — these aren't
|
|
241
|
+
// refused; they're just a soft hint that the rename happened. No banner
|
|
242
|
+
// is emitted post-v0.13.
|
|
243
|
+
const RENAMED_VERBS_HINT = {
|
|
228
244
|
scan: "discover --scan-only",
|
|
229
245
|
dispatch: "discover",
|
|
230
246
|
currency: "doctor --currency",
|
|
231
247
|
verify: "doctor --signatures",
|
|
232
248
|
"validate-cves": "doctor --cves",
|
|
233
249
|
"validate-rfcs": "doctor --rfcs",
|
|
234
|
-
watchlist: "watch",
|
|
235
250
|
prefetch: "refresh --no-network",
|
|
236
251
|
"build-indexes": "refresh --indexes-only",
|
|
237
252
|
};
|
|
@@ -498,40 +513,23 @@ function main() {
|
|
|
498
513
|
process.exit(0);
|
|
499
514
|
}
|
|
500
515
|
|
|
501
|
-
// v0.
|
|
502
|
-
//
|
|
503
|
-
//
|
|
504
|
-
//
|
|
505
|
-
//
|
|
506
|
-
//
|
|
507
|
-
if (
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
const markerFile = path.join(markerDir, `exceptd-deprecation-shown-v${ver}`);
|
|
519
|
-
let alreadyShown = false;
|
|
520
|
-
try { alreadyShown = fs.existsSync(markerFile); } catch { /* tmpdir unwritable; degrade to per-process */ }
|
|
521
|
-
if (!alreadyShown) {
|
|
522
|
-
const haveBrief = ver !== "unknown" && ver.match(/^(\d+)\.(\d+)/) && (parseInt(RegExp.$1, 10) > 0 || parseInt(RegExp.$2, 10) >= 11);
|
|
523
|
-
process.stderr.write(
|
|
524
|
-
`[exceptd] DEPRECATION: \`${cmd}\` is a v0.10.x verb. ` +
|
|
525
|
-
(haveBrief
|
|
526
|
-
? `Prefer \`${LEGACY_VERB_REPLACEMENTS[cmd]}\` (available in this install, v${ver}). `
|
|
527
|
-
: `Upgrade to v0.11.0+ then use \`${LEGACY_VERB_REPLACEMENTS[cmd]}\` (currently installed: v${ver}). `) +
|
|
528
|
-
`Legacy verbs remain functional through this release; they will be removed in v0.13. ` +
|
|
529
|
-
`This banner shows once per exceptd version per host (re-shown on upgrade). Permanent suppress: export EXCEPTD_DEPRECATION_SHOWN=1.\n`
|
|
530
|
-
);
|
|
531
|
-
try { fs.writeFileSync(markerFile, `shown_at=${new Date().toISOString()}\nversion=${ver}\n`, { mode: 0o600 }); }
|
|
532
|
-
catch { /* tmpdir unwritable; the env-var guard below keeps the per-process suppression intact */ }
|
|
533
|
-
}
|
|
534
|
-
process.env.EXCEPTD_DEPRECATION_SHOWN = "1";
|
|
516
|
+
// v0.13.0: hard-refuse the v0.10.x legacy verbs that were
|
|
517
|
+
// deprecation-bannered since v0.11.0. Pre-v0.13 these silently routed
|
|
518
|
+
// to their v0.11+ replacements with a soft banner; v0.13 honors the
|
|
519
|
+
// long-advertised removal. Operators upgrading from v0.10.x get a
|
|
520
|
+
// structured error with the replacement command, suitable for
|
|
521
|
+
// grep / scripted handling.
|
|
522
|
+
if (REMOVED_VERBS[cmd]) {
|
|
523
|
+
emitError(
|
|
524
|
+
`'${cmd}' was removed in v0.13.0. Use \`exceptd ${REMOVED_VERBS[cmd]}\` instead.`,
|
|
525
|
+
{
|
|
526
|
+
verb: cmd,
|
|
527
|
+
removed_in: "0.13.0",
|
|
528
|
+
replacement: REMOVED_VERBS[cmd],
|
|
529
|
+
deprecation_history: "Deprecated in v0.11.0 with a soft banner; slated-for-removal-in-v0.13 announced in v0.12.0; removed in v0.13.0.",
|
|
530
|
+
}
|
|
531
|
+
);
|
|
532
|
+
return;
|
|
535
533
|
}
|
|
536
534
|
|
|
537
535
|
// Seven-phase playbook verbs run in-process — they emit JSON to stdout
|
|
@@ -714,6 +712,16 @@ function emit(obj, pretty, humanRenderer) {
|
|
|
714
712
|
if (obj && obj.ok === false && !process.exitCode) {
|
|
715
713
|
process.exitCode = EXIT_CODES.GENERIC_FAILURE;
|
|
716
714
|
}
|
|
715
|
+
// v0.13.0 envelope harmonization: every emitted body has a top-level
|
|
716
|
+
// `ok` field — defaults to true when not set, matching the symmetric
|
|
717
|
+
// ok:false → exitCode=1 fallback above. Consumers that parse stdout
|
|
718
|
+
// can now assume the envelope shape regardless of which verb produced
|
|
719
|
+
// the body. Per-site `verb: "<name>"` is set at the call site; this
|
|
720
|
+
// helper guarantees the `ok` field's presence but does not synthesize
|
|
721
|
+
// verb (the caller knows its own name).
|
|
722
|
+
if (obj && typeof obj === 'object' && !('ok' in obj)) {
|
|
723
|
+
obj = { ok: true, ...obj };
|
|
724
|
+
}
|
|
717
725
|
const wantJson = !!global.__exceptdWantJson || !!process.env.EXCEPTD_RAW_JSON;
|
|
718
726
|
if (humanRenderer && !wantJson && !pretty) {
|
|
719
727
|
process.stdout.write(humanRenderer(obj) + "\n");
|
|
@@ -4544,7 +4552,7 @@ function cmdAttest(runner, args, runOpts, pretty) {
|
|
|
4544
4552
|
}
|
|
4545
4553
|
|
|
4546
4554
|
if (subverb === "show") {
|
|
4547
|
-
emit({ session_id: sessionId, attestations, attestation_replays: replays }, pretty);
|
|
4555
|
+
emit({ verb: "attest show", session_id: sessionId, attestations, attestation_replays: replays }, pretty);
|
|
4548
4556
|
return;
|
|
4549
4557
|
}
|
|
4550
4558
|
|
package/data/_indexes/_meta.json
CHANGED
|
@@ -1,63 +1,63 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema_version": "1.1.0",
|
|
3
|
-
"generated_at": "2026-05-
|
|
3
|
+
"generated_at": "2026-05-18T01:04:18.854Z",
|
|
4
4
|
"generator": "scripts/build-indexes.js",
|
|
5
5
|
"source_count": 54,
|
|
6
6
|
"source_hashes": {
|
|
7
|
-
"manifest.json": "
|
|
8
|
-
"data/atlas-ttps.json": "
|
|
9
|
-
"data/attack-techniques.json": "
|
|
10
|
-
"data/cve-catalog.json": "
|
|
11
|
-
"data/cwe-catalog.json": "
|
|
7
|
+
"manifest.json": "500446c009c4da12a8e33794fefaffea287d10ee6f3b4d1e5298fb87447ed09e",
|
|
8
|
+
"data/atlas-ttps.json": "0ec427652a9e613f04675beb26dc4c08934ba291e47427972b2a008c151cca78",
|
|
9
|
+
"data/attack-techniques.json": "0ca33f8b0cf55a43de1290e310096020c4e0d16305bd01bcbe6cb46e0278caa8",
|
|
10
|
+
"data/cve-catalog.json": "7fae34cf0abbd09abbbbd6a61ea06e487ddbd57060d3af6a58528c684156cf60",
|
|
11
|
+
"data/cwe-catalog.json": "832d096bd52081fe43c082fd6958f9054d6b6e136df5b3d4cef7efd0ea49a843",
|
|
12
12
|
"data/d3fend-catalog.json": "a1fc2827ceb344669e148d55197dbf1b0e5b20bcc618e90517639c17d67ee82d",
|
|
13
13
|
"data/dlp-controls.json": "d2406c482dddd30e49203879999dc4b3a7fd4d0494d6a61d86b91ee76415df19",
|
|
14
14
|
"data/exploit-availability.json": "003a400f5ae5b15527589571679ccdb9b3a62e60073627b5fbdeb2a9fe330a7a",
|
|
15
|
-
"data/framework-control-gaps.json": "
|
|
15
|
+
"data/framework-control-gaps.json": "5e2baf1e435c5b61b183e3f603636eae4fab34ee800488919c679665882c4f62",
|
|
16
16
|
"data/global-frameworks.json": "9ba563a85f7f8d6c3c957de64945e20925a89d0ed6ea6fc561cf093811acf558",
|
|
17
17
|
"data/rfc-references.json": "e253a548c8a829d178d5aea601e268724b85c936ccbfa51c2e5d80c5f8efe2b0",
|
|
18
|
-
"data/zeroday-lessons.json": "
|
|
19
|
-
"skills/kernel-lpe-triage/skill.md": "
|
|
20
|
-
"skills/ai-attack-surface/skill.md": "
|
|
21
|
-
"skills/mcp-agent-trust/skill.md": "
|
|
22
|
-
"skills/framework-gap-analysis/skill.md": "
|
|
23
|
-
"skills/compliance-theater/skill.md": "
|
|
24
|
-
"skills/exploit-scoring/skill.md": "
|
|
25
|
-
"skills/rag-pipeline-security/skill.md": "
|
|
26
|
-
"skills/ai-c2-detection/skill.md": "
|
|
27
|
-
"skills/policy-exception-gen/skill.md": "
|
|
28
|
-
"skills/threat-model-currency/skill.md": "
|
|
29
|
-
"skills/global-grc/skill.md": "
|
|
18
|
+
"data/zeroday-lessons.json": "40d666d0932da24b425b01ced0f9c9e5f2e6cfd2082f53861d982919dde56a4a",
|
|
19
|
+
"skills/kernel-lpe-triage/skill.md": "ae4a0af924d0078ffc6cd051a3ef9fce75a6a3f9c0c15d1c07900ae5faf80502",
|
|
20
|
+
"skills/ai-attack-surface/skill.md": "dcca7d92a1ab4d1e4c46356b614a138b1c1f79b65a6a290eccf2095d8d443993",
|
|
21
|
+
"skills/mcp-agent-trust/skill.md": "6821f6d38f6e23bbed953f8f86a279597b0b95a2d0548b5383e851bca7442531",
|
|
22
|
+
"skills/framework-gap-analysis/skill.md": "3b139eaefbedd36b2379cfe22dceef71e97d0e34404b0009b7afbfe0a8dc39e6",
|
|
23
|
+
"skills/compliance-theater/skill.md": "a1387c523f7aa2481a199f6288e0152b94aa5a6644600eb39dbb3ea9ee9af6bd",
|
|
24
|
+
"skills/exploit-scoring/skill.md": "fba9e27722d361cc6ed5992d9aaeaa397598b417fc5a0d6fe0bee2993942e7e8",
|
|
25
|
+
"skills/rag-pipeline-security/skill.md": "ff07e48918090247aef71def4150b0df372a24bcdaa34eb6e11d246b9e71e1ee",
|
|
26
|
+
"skills/ai-c2-detection/skill.md": "3da9f549f5c62e6163cddd70c8edccbef7be622d5a45fa89c90c6550e68c6b2e",
|
|
27
|
+
"skills/policy-exception-gen/skill.md": "a7d886f7fa99a150b040f158b09045ba45e107439315389aea785311b0013395",
|
|
28
|
+
"skills/threat-model-currency/skill.md": "ecc6441cb47ef2bc24547e47be018098228c956a41d61ddb50de7e7b37114a37",
|
|
29
|
+
"skills/global-grc/skill.md": "1dca534cce7612c1d26a7b1bfd088a811081555ecfa25b1f68cff2ca2ba28c98",
|
|
30
30
|
"skills/zeroday-gap-learn/skill.md": "59a0d7cd85b923b3f5633bdc15c1a88eef7dea6332480d93b0bb0ae93a4cd0fe",
|
|
31
|
-
"skills/pqc-first/skill.md": "
|
|
32
|
-
"skills/skill-update-loop/skill.md": "
|
|
33
|
-
"skills/security-maturity-tiers/skill.md": "
|
|
34
|
-
"skills/researcher/skill.md": "
|
|
35
|
-
"skills/attack-surface-pentest/skill.md": "
|
|
36
|
-
"skills/fuzz-testing-strategy/skill.md": "
|
|
37
|
-
"skills/dlp-gap-analysis/skill.md": "
|
|
38
|
-
"skills/supply-chain-integrity/skill.md": "
|
|
31
|
+
"skills/pqc-first/skill.md": "a7131b65d0ceee47887b16679ee4e4b065d32d8751fe59921762388703662913",
|
|
32
|
+
"skills/skill-update-loop/skill.md": "cf2b996cb18a5146614c06e3a50f4734a07d02b5be36bbdf492583f9cdcfed4d",
|
|
33
|
+
"skills/security-maturity-tiers/skill.md": "ed962937c45f3d95f325f231b787d272fe45c4cb91d4c5a2d982493d722c2acf",
|
|
34
|
+
"skills/researcher/skill.md": "b47daaa26fdac07aa23e7becaa18487c5302e65c654f99fecab3689f23ec1bd2",
|
|
35
|
+
"skills/attack-surface-pentest/skill.md": "0d301beb9fb8e247ec80256a7e647804b5f9a41c7156e5724555ca9f93ccb986",
|
|
36
|
+
"skills/fuzz-testing-strategy/skill.md": "51acb746cd63366ca62567588c700a9eb3f37c43250bd9ae4e1477ccb71c5b6d",
|
|
37
|
+
"skills/dlp-gap-analysis/skill.md": "1c4e1d7da2421b82f202eaf2c9e21876af34ab5c76ce1359166842ee473f02dd",
|
|
38
|
+
"skills/supply-chain-integrity/skill.md": "ad69b72f5c5df095f8618b977fbc8f0fbff396eebd4a8448b44c3f93309f63f9",
|
|
39
39
|
"skills/defensive-countermeasure-mapping/skill.md": "e62c71ba3be2b4d0f7dfa529fec007cba6bee3013f76b93756e3e6310f2d22ab",
|
|
40
|
-
"skills/identity-assurance/skill.md": "
|
|
41
|
-
"skills/ot-ics-security/skill.md": "
|
|
40
|
+
"skills/identity-assurance/skill.md": "4ee7096fd82997c66b0f9e825ea3c04c3aa84768b74e6f668c1a9104104138cf",
|
|
41
|
+
"skills/ot-ics-security/skill.md": "9ece7b1fb7f24e37dbdd8618b94b2a4434e182e3426e15f17e26464c0a1fdfd1",
|
|
42
42
|
"skills/coordinated-vuln-disclosure/skill.md": "0e875953bb8a38a89c8ec5d2a9ef967b12e9a9f166dc9356723f10304fd0535e",
|
|
43
|
-
"skills/threat-modeling-methodology/skill.md": "
|
|
44
|
-
"skills/webapp-security/skill.md": "
|
|
45
|
-
"skills/ai-risk-management/skill.md": "
|
|
46
|
-
"skills/sector-healthcare/skill.md": "
|
|
47
|
-
"skills/sector-financial/skill.md": "
|
|
48
|
-
"skills/sector-federal-government/skill.md": "
|
|
49
|
-
"skills/sector-energy/skill.md": "
|
|
50
|
-
"skills/sector-telecom/skill.md": "
|
|
51
|
-
"skills/api-security/skill.md": "
|
|
52
|
-
"skills/cloud-security/skill.md": "
|
|
53
|
-
"skills/container-runtime-security/skill.md": "
|
|
54
|
-
"skills/mlops-security/skill.md": "
|
|
55
|
-
"skills/incident-response-playbook/skill.md": "
|
|
56
|
-
"skills/ransomware-response/skill.md": "
|
|
57
|
-
"skills/email-security-anti-phishing/skill.md": "
|
|
58
|
-
"skills/age-gates-child-safety/skill.md": "
|
|
59
|
-
"skills/cloud-iam-incident/skill.md": "
|
|
60
|
-
"skills/idp-incident-response/skill.md": "
|
|
43
|
+
"skills/threat-modeling-methodology/skill.md": "ac623f61585de66c9ef5ed63e9c6059faef77e525abc672ac6d435c616a7268f",
|
|
44
|
+
"skills/webapp-security/skill.md": "fdb07324b69a3a724e3eaba17bf687d72d4bd9d5c4f440be816bc9b08b8aef04",
|
|
45
|
+
"skills/ai-risk-management/skill.md": "67e62791f60231f2ff53408922fa7137a9060de72097769c630f838a1c227c45",
|
|
46
|
+
"skills/sector-healthcare/skill.md": "a18e11d25524cdbf40df3798f4c2aa3cb51a4db1b088242ea53fa2885e86b64c",
|
|
47
|
+
"skills/sector-financial/skill.md": "023b5440d614e6b83ba7294219bcac3cdbffd28fdfdd5f0ec23abbeea71b8230",
|
|
48
|
+
"skills/sector-federal-government/skill.md": "c63cf1c7c98e920f968cfe60f14e718ea71b120c1b01616af22f64a796963bbe",
|
|
49
|
+
"skills/sector-energy/skill.md": "643fd951359c2602d9b029a244fe66c1e23f726e711141a06c09cc760a479534",
|
|
50
|
+
"skills/sector-telecom/skill.md": "862f9482af88e5409e011a6981a5d719863deeb646e41cd4df63e5d6597c50b1",
|
|
51
|
+
"skills/api-security/skill.md": "2bdfa3dbe534efa3df245e0da37998ad7ab2da4a3171d5000d3346513c10bceb",
|
|
52
|
+
"skills/cloud-security/skill.md": "c9fad9ed3663cf2faec74ad8f06d62eb86e6636f79933560d8c8d50e0e82d1da",
|
|
53
|
+
"skills/container-runtime-security/skill.md": "605a8e8eb1af09835b967ec7179456015ec116c6b9051af3a8d225866cc2f7af",
|
|
54
|
+
"skills/mlops-security/skill.md": "ca3fd922b43fc57aeb5e65c2d5a2823e6bc438167d6afa3a767cee83e4af1f96",
|
|
55
|
+
"skills/incident-response-playbook/skill.md": "2017515d899c1b2bcb878bc6731e4059623ac52345b2cebbd92204583657bf60",
|
|
56
|
+
"skills/ransomware-response/skill.md": "2e4fc488f86ed1ba7791ab0e7021160d8ca5ad33a02cdf92a5b916c8afecaa54",
|
|
57
|
+
"skills/email-security-anti-phishing/skill.md": "e4e9e5a820c0ed3fde9483282e7a0ecaf79284cd2e9923ce66f2b0fb1fc44626",
|
|
58
|
+
"skills/age-gates-child-safety/skill.md": "66e7773d29c179ab62f409007c05e05993e04a19273225a1e520f2481fd9a90d",
|
|
59
|
+
"skills/cloud-iam-incident/skill.md": "6494ee3856edeb212e65fe5cdb208357c1a832eb8ac374b26055586bfc71f629",
|
|
60
|
+
"skills/idp-incident-response/skill.md": "e67a2576e7f1c3bf89f499f5c977bc470ef29e8b3e3e45f4cb5bd45a82674282"
|
|
61
61
|
},
|
|
62
62
|
"skill_count": 42,
|
|
63
63
|
"catalog_count": 11,
|
|
@@ -72,13 +72,13 @@
|
|
|
72
72
|
"dlp_refs": 0
|
|
73
73
|
},
|
|
74
74
|
"trigger_table_entries": 538,
|
|
75
|
-
"chains_cve_entries":
|
|
75
|
+
"chains_cve_entries": 34,
|
|
76
76
|
"chains_cwe_entries": 55,
|
|
77
77
|
"jurisdictions_indexed": 29,
|
|
78
78
|
"handoff_dag_nodes": 42,
|
|
79
79
|
"summary_cards": 42,
|
|
80
80
|
"section_offsets_skills": 42,
|
|
81
|
-
"token_budget_total_approx":
|
|
81
|
+
"token_budget_total_approx": 402643,
|
|
82
82
|
"recipes": 8,
|
|
83
83
|
"jurisdiction_clocks": 29,
|
|
84
84
|
"did_ladders": 8,
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
"artifact": "data/zeroday-lessons.json",
|
|
88
88
|
"path": "data/zeroday-lessons.json",
|
|
89
89
|
"schema_version": "1.1.0",
|
|
90
|
-
"entry_count":
|
|
90
|
+
"entry_count": 24
|
|
91
91
|
},
|
|
92
92
|
{
|
|
93
93
|
"date": "2026-05-15",
|
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
"artifact": "data/cve-catalog.json",
|
|
103
103
|
"path": "data/cve-catalog.json",
|
|
104
104
|
"schema_version": "1.0.0",
|
|
105
|
-
"entry_count":
|
|
105
|
+
"entry_count": 39
|
|
106
106
|
},
|
|
107
107
|
{
|
|
108
108
|
"date": "2026-05-13",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"rebuild_after_days": 365,
|
|
63
63
|
"note": "Per-entry last_verified governs decay. Skills depending on this catalog must check entry freshness before high-stakes use."
|
|
64
64
|
},
|
|
65
|
-
"entry_count":
|
|
65
|
+
"entry_count": 39,
|
|
66
66
|
"sample_keys": [
|
|
67
67
|
"CVE-2025-53773",
|
|
68
68
|
"CVE-2026-30615",
|
|
@@ -238,7 +238,7 @@
|
|
|
238
238
|
"rebuild_after_days": 365,
|
|
239
239
|
"note": "Per-entry last_verified governs decay. Skills depending on this catalog must check entry freshness before high-stakes use."
|
|
240
240
|
},
|
|
241
|
-
"entry_count":
|
|
241
|
+
"entry_count": 24,
|
|
242
242
|
"sample_keys": [
|
|
243
243
|
"CVE-2026-31431",
|
|
244
244
|
"CVE-2025-53773",
|