@blamejs/exceptd-skills 0.16.25 → 0.16.29
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 +5 -5
- package/ARCHITECTURE.md +3 -3
- package/CHANGELOG.md +28 -0
- package/CONTEXT.md +2 -2
- package/README.md +6 -6
- package/agents/threat-researcher.md +2 -2
- package/bin/exceptd.js +41 -8
- package/data/_indexes/_meta.json +41 -40
- package/data/_indexes/activity-feed.json +240 -240
- package/data/_indexes/catalog-summaries.json +3 -3
- package/data/_indexes/currency.json +64 -64
- package/data/_indexes/jurisdiction-map.json +31 -158
- package/data/_indexes/recipes.json +1 -1
- package/data/_indexes/section-offsets.json +510 -510
- package/data/_indexes/summary-cards.json +33 -33
- package/data/_indexes/token-budget.json +200 -200
- package/data/atlas-ttps.json +7 -7
- package/data/attack-techniques.json +5 -5
- package/data/framework-control-gaps.json +3 -3
- package/lib/auto-discovery.js +15 -9
- package/lib/collectors/library-author.js +26 -9
- package/lib/collectors/secrets.js +8 -1
- package/lib/cvss.js +108 -0
- package/lib/lint-skills.js +6 -1
- package/lib/playbook-runner.js +17 -4
- package/lib/prefetch.js +97 -5
- package/lib/refresh-external.js +25 -13
- package/lib/schemas/manifest.schema.json +1 -1
- package/lib/schemas/skill-frontmatter.schema.json +1 -1
- package/lib/validate-indexes.js +5 -0
- package/lib/version-pins.js +3 -3
- package/manifest-snapshot.json +2 -2
- package/manifest-snapshot.sha256 +1 -1
- package/manifest.json +124 -124
- package/orchestrator/pipeline.js +16 -4
- package/package.json +1 -1
- package/sbom.cdx.json +170 -140
- package/scripts/build-indexes.js +12 -1
- package/scripts/builders/catalog-summaries.js +1 -1
- package/scripts/builders/recipes.js +1 -1
- package/scripts/check-sbom-currency.js +76 -14
- package/scripts/refresh-sbom.js +1 -1
- package/scripts/run-e2e-scenarios.js +48 -17
- package/scripts/sync-package-description.js +74 -0
- package/scripts/verify-shipped-tarball.js +18 -7
- package/skills/age-gates-child-safety/skill.md +3 -3
- package/skills/ai-attack-surface/skill.md +4 -4
- package/skills/ai-c2-detection/skill.md +5 -5
- package/skills/api-security/skill.md +2 -2
- package/skills/attack-surface-pentest/skill.md +4 -4
- package/skills/cloud-security/skill.md +3 -3
- package/skills/compliance-theater/skill.md +3 -3
- package/skills/container-runtime-security/skill.md +3 -3
- package/skills/coordinated-vuln-disclosure/skill.md +2 -2
- package/skills/defensive-countermeasure-mapping/skill.md +3 -3
- package/skills/dlp-gap-analysis/skill.md +5 -5
- package/skills/exploit-scoring/skill.md +2 -2
- package/skills/framework-gap-analysis/skill.md +4 -4
- package/skills/fuzz-testing-strategy/skill.md +2 -2
- package/skills/incident-response-playbook/skill.md +3 -3
- package/skills/mcp-agent-trust/skill.md +2 -2
- package/skills/mlops-security/skill.md +3 -3
- package/skills/ot-ics-security/skill.md +3 -3
- package/skills/policy-exception-gen/skill.md +3 -3
- package/skills/pqc-first/skill.md +2 -2
- package/skills/rag-pipeline-security/skill.md +4 -4
- package/skills/ransomware-response/skill.md +2 -2
- package/skills/sector-energy/skill.md +2 -2
- package/skills/sector-federal-government/skill.md +2 -2
- package/skills/sector-financial/skill.md +4 -4
- package/skills/sector-healthcare/skill.md +3 -3
- package/skills/security-maturity-tiers/skill.md +1 -1
- package/skills/skill-update-loop/skill.md +6 -6
- package/skills/supply-chain-integrity/skill.md +2 -2
- package/skills/threat-model-currency/skill.md +8 -8
- package/skills/threat-modeling-methodology/skill.md +2 -2
- package/skills/webapp-security/skill.md +2 -2
- package/skills/zeroday-gap-learn/skill.md +3 -3
- package/sources/validators/cve-validator.js +27 -18
package/AGENTS.md
CHANGED
|
@@ -44,9 +44,9 @@ Each rule below carries a **Forcing function** annotation declaring whether it i
|
|
|
44
44
|
12. **External data version pinning** — Every reference to external data (MITRE ATLAS, MITRE ATT&CK, NIST frameworks, CISA KEV, IETF RFCs and Internet-Drafts) must pin to a specific version. When a new version is released: (a) audit for breaking changes (renamed TTPs, tactic-split moves, replaced RFCs, deprecated controls), (b) bump `last_threat_review` in all affected skills, (c) update `_meta` version fields in the relevant `data/*.json` file, (d) update `last_verified` on affected `data/rfc-references.json` entries, (e) never silently inherit version changes. Frameworks lag RFCs; RFCs lag attacker innovation — skills must track lag at every layer.
|
|
45
45
|
*Forcing function:* `_meta` version fields are schema-required; reviewer-checked for cross-file version consistency.
|
|
46
46
|
|
|
47
|
-
**Pinned ATLAS version:
|
|
47
|
+
**Pinned ATLAS version: v2026.05 (May 2026), Secure AI v2 layer (May 2026). Audit cadence: monthly** (ATLAS now ships monthly per CTID; the Secure AI v2 layered set and per-technique maturity classification are tracked separately in `data/atlas-ttps.json` via the `secure_ai_v2_layer` and `maturity` fields).
|
|
48
48
|
|
|
49
|
-
**Pinned ATT&CK version: v19.
|
|
49
|
+
**Pinned ATT&CK version: v19.1 (May 2026). Audit cadence: semi-annual** (April and October releases). v19 split Defense Evasion (TA0005) into Stealth (TA0005) and Defense Impairment (TA0112) — affected entries in `data/attack-techniques.json` carry `tactic_moved_from` for traceability. v18 introduced Detection Strategies (DSxxxx) as first-class objects; record applicable strategy IDs on entries where canonical strategies exist.
|
|
50
50
|
|
|
51
51
|
The IETF RFC / Internet-Draft catalog lives at `data/rfc-references.json`; each entry tracks status, errata count, replaces / replaced-by, and `last_verified`.
|
|
52
52
|
|
|
@@ -206,7 +206,7 @@ Wrong: adding a new CVE to `data/cve-catalog.json` without completing all requir
|
|
|
206
206
|
Right: every new entry requires all fields defined in the CVE catalog schema. Partial entries fail the schema validation in `lib/scoring.js`.
|
|
207
207
|
|
|
208
208
|
**DR-7: Stale ATLAS / ATT&CK version**
|
|
209
|
-
Current pinned ATLAS version: **
|
|
209
|
+
Current pinned ATLAS version: **v2026.05 (May 2026)** with the **CTID Secure AI v2 layer (May 2026)**. ATLAS audit cadence is **monthly** (CTID now ships monthly). Current pinned ATT&CK version: **v19.1 (May 2026)**, semi-annual cadence (April + October). When either source updates: audit all TTP IDs for changes (including v19's Defense Evasion → Stealth / Defense Impairment split), bump `last_threat_review` in affected skills, update `_meta` version fields in `data/atlas-ttps.json` and `data/attack-techniques.json`. Never silently upgrade.
|
|
210
210
|
|
|
211
211
|
**DR-8: Missing zero-day learning loop**
|
|
212
212
|
Wrong: adding a new entry to `data/cve-catalog.json` without running the learning loop.
|
|
@@ -407,8 +407,8 @@ When in doubt, ship the playbook without a collector and open the gap as a follo
|
|
|
407
407
|
- [ ] All new CVEs have complete `data/cve-catalog.json` entries
|
|
408
408
|
- [ ] All new CVEs have `data/zeroday-lessons.json` entries
|
|
409
409
|
- [ ] All skill `data_deps` resolve to existing files
|
|
410
|
-
- [ ] All ATLAS refs are valid
|
|
411
|
-
- [ ] All ATT&CK refs are valid v19.
|
|
410
|
+
- [ ] All ATLAS refs are valid v2026.05 IDs (current pinned version); Secure AI v2 layer flags + maturity present on AI-pipeline entries
|
|
411
|
+
- [ ] All ATT&CK refs are valid v19.1 IDs (current pinned version); post-split tactics (Stealth / Defense Impairment) used where applicable
|
|
412
412
|
- [ ] All framework control IDs resolve in `data/framework-control-gaps.json`
|
|
413
413
|
- [ ] No skill body contains placeholder language (TODO, TBD, coming soon, placeholder)
|
|
414
414
|
- [ ] No skill uses CVSS as sole risk metric
|
package/ARCHITECTURE.md
CHANGED
|
@@ -36,7 +36,7 @@ data_deps:
|
|
|
36
36
|
- cve-catalog.json # files in data/ this skill reads
|
|
37
37
|
- atlas-ttps.json
|
|
38
38
|
atlas_refs:
|
|
39
|
-
- AML.T0043 # MITRE ATLAS
|
|
39
|
+
- AML.T0043 # MITRE ATLAS v2026.05 TTP IDs
|
|
40
40
|
- AML.T0054
|
|
41
41
|
attack_refs:
|
|
42
42
|
- T1068 # MITRE ATT&CK TTP IDs
|
|
@@ -124,7 +124,7 @@ Schema per entry:
|
|
|
124
124
|
"AML.T0043": {
|
|
125
125
|
"name": "Craft Adversarial Data",
|
|
126
126
|
"tactic": "ML Attack Staging",
|
|
127
|
-
"atlas_version": "
|
|
127
|
+
"atlas_version": "2026.05",
|
|
128
128
|
"description": "...",
|
|
129
129
|
"framework_coverage": {
|
|
130
130
|
"NIST-800-53": {"covered": false, "nearest_control": null, "gap_description": "..."},
|
|
@@ -204,7 +204,7 @@ RWEP (Real-World Exploit Priority) scoring engine.
|
|
|
204
204
|
|
|
205
205
|
- `score(cveId)` — Return RWEP score for a CVE in the catalog
|
|
206
206
|
- `scoreCustom(factors)` — Score a custom factor set (for CVEs not yet in catalog)
|
|
207
|
-
- `validate()` — Schema validation: check all skill data_deps resolve, all CVE entries are complete, all ATLAS refs are valid
|
|
207
|
+
- `validate()` — Schema validation: check all skill data_deps resolve, all CVE entries are complete, all ATLAS refs are valid v2026.05 IDs
|
|
208
208
|
- `compare(cveId)` — Return CVSS vs. RWEP comparison with explanation of the delta
|
|
209
209
|
|
|
210
210
|
RWEP factor weights:
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.16.29 — 2026-06-12
|
|
4
|
+
|
|
5
|
+
A correctness pass across the refresh pipeline, scoring, attestation, the collectors, and offline mode.
|
|
6
|
+
|
|
7
|
+
`refresh --apply` over the network no longer downgrades a curated CVSS 3.1 score and vector to NVD's legacy v2 metric on older CVEs — the offline cache path already guarded this in 0.16.27, and the live path now applies the same cross-version guard. New-RFC discovery now honors `--air-gap` (it previously queried IETF Datatracker live regardless), and an intrinsically air-gapped playbook — secrets, cred-stores, containers — refuses the `--upstream-check` npm-registry probe without the explicit flag. The `--from-cache` help no longer implies new-RFC discovery is offline; it stays live unless `--air-gap` is also passed.
|
|
8
|
+
|
|
9
|
+
A CVE that a VEX statement marks fixed no longer inflates a finding's adjusted RWEP through its exploitation, KEV, and proof-of-concept multipliers, and a patched CVE's exploitation status no longer drives the notification draft. Jurisdiction coverage no longer attributes a skill to a jurisdiction from a bare two-letter ISO code that appears only in prose or inside a control identifier; coverage is driven by the regulation-name mapping. The skill-currency staleness check can now reach the warn and critical tiers it gates on — they were unreachable, so the scheduled currency workflow could never flag a skill past its review window; a genuinely abandoned skill now scores into them while a maintained one does not.
|
|
10
|
+
|
|
11
|
+
`attest diff --against` now verifies the comparison attestation's Ed25519 signature, not only the local side, and refuses a tampered `--against` attestation (exit 6; `--force-replay` overrides). Both sides' verification is recorded in the output.
|
|
12
|
+
|
|
13
|
+
The collectors no longer raise false findings from `#`-commented YAML — a commented `npm install`, `runs-on: self-hosted`, or `secrets.NPM_TOKEN` is no longer read as the real thing — and a commented `npm publish --provenance` no longer suppresses the missing-build-provenance finding. A documentation or redaction-pattern snippet of a service-account private key no longer registers as an embedded secret. A skill.md with CRLF line endings no longer produces a misleading frontmatter-parse error, and the `run --format` reference now lists `json`, which the runtime already accepts.
|
|
14
|
+
|
|
15
|
+
The scheduled external-data refresh keeps the package description's entry counts in sync with the data it applies, so an auto-refresh that changes a count no longer fails the SBOM currency check on its pull request.
|
|
16
|
+
|
|
17
|
+
## 0.16.28 — 2026-06-10
|
|
18
|
+
|
|
19
|
+
Refreshes the pinned MITRE threat-framework versions. MITRE ATLAS is now pinned to v2026.05: its content moved to a YYYY.MM calendar-versioning scheme, and the release adds platform tags (Predictive AI, Generative AI, Agentic AI, Enterprise) to every technique. MITRE ATT&CK is pinned to v19.1, a point release of typo and data corrections over v19.0. Both bumps were audited against every ATLAS and ATT&CK technique ID the catalog cites: none was removed, renamed, or revoked, so all existing references remain valid.
|
|
20
|
+
|
|
21
|
+
## 0.16.27 — 2026-06-08
|
|
22
|
+
|
|
23
|
+
The automated external-data refresh runs to completion again, and the NVD score sync no longer regresses curated severities.
|
|
24
|
+
|
|
25
|
+
Warming the upstream cache fans out hundreds (daily) to thousands (weekly) of rate-limited per-CVE and per-RFC requests, and a single transient fetch error — a timeout or a rate-limit response, counted only after its retries are exhausted — previously aborted the entire refresh before any data was applied. The cache warm now tolerates a bounded number of transient per-entry errors, but still fails when the error count signals a systemic upstream outage or when any single feed is entirely unreachable (so a dead KEV feed can no longer be silently skipped). The affected sources are named in the summary, and on the error channel under `--quiet`, so a recurring dead source is visible in the run log.
|
|
26
|
+
|
|
27
|
+
The NVD synchronization no longer downgrades a curated CVSS 3.1 entry to NVD's legacy CVSS 2.0 score. NVD marks the v2 metric as the primary score on many pre-2016 CVEs even when a 3.1 re-score is present, and emits that v2 vector without its `CVSS:2.0/` prefix; the refresh selected the v2 metric and overwrote the catalog's curated 3.1 score and vector, producing an unprefixed vector the catalog validator rejects and silently regressing the score. The refresh now selects the newest CVSS version a CVE carries (4.0, then 3.1, then 3.0, then 2.0), normalizes a bare v2 vector to its canonical prefixed form, and never replaces a curated score or vector with an older CVSS version — a genuine same-version or newer re-score still flows through. The same selection applies on the live network refresh path and to auto-imported draft entries.
|
|
28
|
+
|
|
29
|
+
The end-to-end scenario runner no longer passes a scenario that did not actually exercise the CLI. A run killed by the 60-second timeout, or one that failed to launch, was read only through its exit status — so it surfaced as a confusing JSON-parse failure (or, with no assertions, as a pass); the runner now reports the spawn error and the terminating signal directly. A scenario that declares neither an expected exit code nor any output assertion is now a configuration error rather than a silent pass, so an empty expectation can no longer green-light any CLI behavior, including a crash.
|
|
30
|
+
|
|
3
31
|
## 0.16.25 — 2026-06-05
|
|
4
32
|
|
|
5
33
|
The `refresh` air-gap guidance now consistently names `--prefetch` as the cache-populate command. The `refresh --help` synopsis and the `--from-cache` missing-path error hint previously presented `--no-network` as a populate alias — but `--no-network` is the report-only dry run that writes nothing, so an operator following that guidance produced an empty cache and then hit a confusing "path does not exist" on the offline host. `--no-network` is now documented as the report-only mode it actually is, and the air-gap hint points at `--prefetch`.
|
package/CONTEXT.md
CHANGED
|
@@ -114,7 +114,7 @@ Skills and playbooks read from `data/`. Authoritative catalog inventory:
|
|
|
114
114
|
| File | Entries | Purpose |
|
|
115
115
|
|------|---------|---------|
|
|
116
116
|
| `cve-catalog.json` | 439 | CVEs with CVSS, RWEP score, EPSS estimates, CISA KEV flags, PoC and live-patch availability |
|
|
117
|
-
| `atlas-ttps.json` | 170 | MITRE ATLAS
|
|
117
|
+
| `atlas-ttps.json` | 170 | MITRE ATLAS v2026.05 (May 2026) techniques with framework gap flags |
|
|
118
118
|
| `attack-techniques.json` | 805 | MITRE ATT&CK techniques with framework coverage mappings |
|
|
119
119
|
| `framework-control-gaps.json` | 194 | Framework control gap entries: designed-for vs. what each control misses |
|
|
120
120
|
| `exploit-availability.json` | 28 | Per-CVE PoC locations, weaponization stage, AI-acceleration factor, live-patch status |
|
|
@@ -245,7 +245,7 @@ The `researcher` **skill** (front-door dispatcher) and `threat-researcher` **age
|
|
|
245
245
|
|------|------------|
|
|
246
246
|
| RWEP | Real-World Exploit Priority — risk score beyond CVSS |
|
|
247
247
|
| KEV | CISA Known Exploited Vulnerabilities catalog |
|
|
248
|
-
| ATLAS | MITRE ATLAS
|
|
248
|
+
| ATLAS | MITRE ATLAS v2026.05 — AI threat framework |
|
|
249
249
|
| MCP | Model Context Protocol — AI tool integration standard |
|
|
250
250
|
| HNDL | Harvest-Now-Decrypt-Later — quantum threat to current crypto |
|
|
251
251
|
| Framework lag | Gap between what a framework requires and what current TTPs demand |
|
package/README.md
CHANGED
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
[](https://scorecard.dev/viewer/?uri=github.com/blamejs/exceptd-skills)
|
|
16
16
|
[](https://www.apache.org/licenses/LICENSE-2.0)
|
|
17
17
|
[](#skill-inventory)
|
|
18
|
-
[](https://atlas.mitre.org)
|
|
19
|
+
[](https://attack.mitre.org)
|
|
20
20
|
[](AGENTS.md)
|
|
21
21
|
[](data/global-frameworks.json)
|
|
22
22
|
|
|
@@ -49,7 +49,7 @@ Assess Linux kernel local privilege escalation exposure. Covers Copy Fail (CVE-2
|
|
|
49
49
|
### AI-Specific Attack Surface
|
|
50
50
|
|
|
51
51
|
**[ai-attack-surface](skills/ai-attack-surface/skill.md)**
|
|
52
|
-
Comprehensive AI/ML attack surface assessment mapped to MITRE ATLAS
|
|
52
|
+
Comprehensive AI/ML attack surface assessment mapped to MITRE ATLAS v2026.05 with explicit gap flags. Covers prompt injection as enterprise RCE (CVE-2025-53773 CVSS 7.8, 85%+ bypass rate against SOTA defenses), MCP supply chain RCE (CVE-2026-30615, zero user interaction, 150M+ downloads), RAG exfiltration, model poisoning, AI-assisted exploit development (41% of 2025 zero-days), credential theft acceleration (160% increase).
|
|
53
53
|
|
|
54
54
|
**[mcp-agent-trust](skills/mcp-agent-trust/skill.md)**
|
|
55
55
|
Enumerate MCP (Model Context Protocol) trust boundary failures. Covers tool allowlisting gaps, unsigned server manifests, prompt injection via tool responses, supply chain compromise. CVE-2026-30615 (Windsurf, zero-interaction RCE). Generates: tool allowlist policy, server signing requirements, bearer auth config, output sanitization requirements.
|
|
@@ -228,7 +228,7 @@ exceptd run [playbook] Phases 4-7. Auto-detects cwd context when
|
|
|
228
228
|
--evidence-dir <dir> Per-playbook submission files (cron-friendly).
|
|
229
229
|
--scope <type> | --all Multi-playbook run.
|
|
230
230
|
--vex <file> CycloneDX / OpenVEX filter (drop not_affected).
|
|
231
|
-
--format <fmt> ... csaf-2.0 | sarif | openvex | markdown | summary.
|
|
231
|
+
--format <fmt> ... csaf-2.0 | sarif | openvex | markdown | summary | json.
|
|
232
232
|
Repeatable. CSAF is primary; extras go to
|
|
233
233
|
close.evidence_package.bundles_by_format.
|
|
234
234
|
--diff-from-latest Drift vs prior attestation for same playbook.
|
|
@@ -622,7 +622,7 @@ All skills pull from `data/`. Cross-validated against canonical upstream sources
|
|
|
622
622
|
To resolve a single citation rather than refresh the whole catalog, `exceptd cve <CVE-ID>` and `exceptd rfc <number>` return a status verdict for one id (catalog → resolved cache → one NVD / datatracker lookup, offline-capable). The lookup caches, so a fan-out of agents shares the answer instead of each independently re-researching the same citation.
|
|
623
623
|
|
|
624
624
|
- `cve-catalog.json` — CVE metadata with RWEP scores, CISA KEV status, PoC availability, live-patch info
|
|
625
|
-
- `atlas-ttps.json` — MITRE ATLAS
|
|
625
|
+
- `atlas-ttps.json` — MITRE ATLAS v2026.05 TTPs with gap flags and exploitation examples. Each TTP now carries a `cve_refs[]` back-edge — operators reading an ATLAS entry see the catalogued CVEs that cite it without grepping `cve-catalog.json`. The same back-edge is populated on `attack-techniques.json`, and each playbook carries a `_meta.fed_by[]` reverse field naming the upstream playbooks that chain into it.
|
|
626
626
|
- `framework-control-gaps.json` — Per-framework, per-control: what it was designed for vs. what it misses
|
|
627
627
|
- `exploit-availability.json` — PoC locations, weaponization status, AI-assist factor
|
|
628
628
|
- `global-frameworks.json` — All major global compliance frameworks (35 jurisdictions) with control inventories and lag scores
|
|
@@ -638,7 +638,7 @@ To resolve a single citation rather than refresh the whole catalog, `exceptd cve
|
|
|
638
638
|
|
|
639
639
|
**Compliance is not security.** A SOC 2 Type II report confirms that controls existed and operated effectively during the audit period. It says nothing about whether those controls are adequate for current attack patterns. When NIST 800-53 SI-2 says "apply security patches in a timely manner" and Copy Fail is a 732-byte deterministic root with a public PoC and no race condition, "timely" is the wrong frame entirely.
|
|
640
640
|
|
|
641
|
-
**Framework lag is measured in months.** MITRE ATLAS
|
|
641
|
+
**Framework lag is measured in months.** MITRE ATLAS v2026.05 (May 2026) is the most current AI threat framework available. It still lags real exploitation by 3-6 months. NIST AI RMF lags by years. ISO 27001:2022 has no AI-specific controls. These skills explicitly flag every place where framework coverage ends and real attacker capability begins.
|
|
642
642
|
|
|
643
643
|
**AI changed the exploit development timeline.** Copy Fail was discovered by an AI system in approximately one hour. 41% of 2025 zero-days involved AI-assisted reverse engineering on the attacker side. The time between vulnerability introduction and reliable exploitation is compressing faster than patch management processes can adapt. Risk scoring must reflect this.
|
|
644
644
|
|
|
@@ -52,9 +52,9 @@ Research and validate new threat intelligence — CVEs, attack campaigns, new AT
|
|
|
52
52
|
- Distinguish: "CISA KEV confirmed" vs. "suspected" vs. "no evidence"
|
|
53
53
|
|
|
54
54
|
6. **Map to ATLAS/ATT&CK**
|
|
55
|
-
- Identify which ATLAS
|
|
55
|
+
- Identify which ATLAS v2026.05 TTPs are relevant to this CVE's attack vector
|
|
56
56
|
- Identify which ATT&CK techniques are relevant
|
|
57
|
-
- Flag any ATLAS gaps (attack pattern not in ATLAS
|
|
57
|
+
- Flag any ATLAS gaps (attack pattern not in ATLAS v2026.05)
|
|
58
58
|
|
|
59
59
|
7. **Identify affected skills**
|
|
60
60
|
- Which skills cover the CVE's technology domain?
|
package/bin/exceptd.js
CHANGED
|
@@ -3406,8 +3406,10 @@ function cmdRun(runner, args, runOpts, pretty) {
|
|
|
3406
3406
|
// Audit 3 A.6: --air-gap must refuse the registry probe. The
|
|
3407
3407
|
// upstream-check helper has no air-gap awareness of its own; the
|
|
3408
3408
|
// central refusal lives here so any future caller of --upstream-check
|
|
3409
|
-
// inherits it.
|
|
3410
|
-
|
|
3409
|
+
// inherits it. Mirror the line-3444 hoist: an intrinsically air-gapped
|
|
3410
|
+
// playbook (_meta.air_gap_mode — secrets / cred-stores / containers) must
|
|
3411
|
+
// refuse the egress too, even without the explicit --air-gap flag.
|
|
3412
|
+
if (runOpts.airGap || process.env.EXCEPTD_AIR_GAP === "1" || pb._meta?.air_gap_mode) {
|
|
3411
3413
|
upstreamCheck = {
|
|
3412
3414
|
ok: false,
|
|
3413
3415
|
source: "air-gap",
|
|
@@ -5641,24 +5643,26 @@ function cmdAttest(runner, args, runOpts, pretty) {
|
|
|
5641
5643
|
// attestation.json cannot shadow the real attestation in the
|
|
5642
5644
|
// diff.
|
|
5643
5645
|
let other = null;
|
|
5646
|
+
let otherPath = null;
|
|
5644
5647
|
const otherAttestationPath = path.join(otherDir, "attestation.json");
|
|
5645
5648
|
if (fs.existsSync(otherAttestationPath)) {
|
|
5646
5649
|
try {
|
|
5647
5650
|
const parsed = JSON.parse(fs.readFileSync(otherAttestationPath, "utf8"));
|
|
5648
|
-
if (parsed && parsed.kind !== "replay") other = parsed;
|
|
5651
|
+
if (parsed && parsed.kind !== "replay") { other = parsed; otherPath = otherAttestationPath; }
|
|
5649
5652
|
} catch { /* fall through to scan */ }
|
|
5650
5653
|
}
|
|
5651
5654
|
if (!other) {
|
|
5652
5655
|
const candidates = [];
|
|
5653
5656
|
for (const f of otherFiles) {
|
|
5654
5657
|
try {
|
|
5655
|
-
const
|
|
5658
|
+
const fp = path.join(otherDir, f);
|
|
5659
|
+
const parsed = JSON.parse(fs.readFileSync(fp, "utf8"));
|
|
5656
5660
|
if (!parsed || parsed.kind === "replay") continue;
|
|
5657
|
-
candidates.push(parsed);
|
|
5661
|
+
candidates.push({ parsed, file: fp });
|
|
5658
5662
|
} catch { /* skip malformed */ }
|
|
5659
5663
|
}
|
|
5660
|
-
candidates.sort((a, b) => (b.captured_at || "").localeCompare(a.captured_at || ""));
|
|
5661
|
-
other = candidates[0]
|
|
5664
|
+
candidates.sort((a, b) => (b.parsed.captured_at || "").localeCompare(a.parsed.captured_at || ""));
|
|
5665
|
+
if (candidates[0]) { other = candidates[0].parsed; otherPath = candidates[0].file; }
|
|
5662
5666
|
}
|
|
5663
5667
|
if (!other) {
|
|
5664
5668
|
return emitError(`attest diff --against ${args.against}: no attestations under that session id.`, null, pretty);
|
|
@@ -5673,6 +5677,33 @@ function cmdAttest(runner, args, runOpts, pretty) {
|
|
|
5673
5677
|
pretty
|
|
5674
5678
|
);
|
|
5675
5679
|
}
|
|
5680
|
+
// Verify BOTH attestations' sidecars — the --against (B-side) drives the
|
|
5681
|
+
// drift verdict as much as the A-side, so a forged comparison attestation
|
|
5682
|
+
// must be refused too, not silently diffed under an A-only green sidecar
|
|
5683
|
+
// line. Mirrors reattest's tamper-refusal contract (exit TAMPERED unless
|
|
5684
|
+
// --force-replay); surfaces a_/b_sidecar_verify either way.
|
|
5685
|
+
const aSidecarVerify = verifyAttestationSidecar(path.join(dir, "attestation.json"));
|
|
5686
|
+
const bSidecarVerify = otherPath
|
|
5687
|
+
? verifyAttestationSidecar(otherPath)
|
|
5688
|
+
: { file: null, signed: false, verified: false, reason: "no B-side attestation file resolved" };
|
|
5689
|
+
const aTampered = isTamperedSidecarVerify(aSidecarVerify);
|
|
5690
|
+
const bTampered = isTamperedSidecarVerify(bSidecarVerify);
|
|
5691
|
+
if ((aTampered || bTampered) && !args["force-replay"]) {
|
|
5692
|
+
const sides = [aTampered && "A-side", bTampered && "--against (B-side)"].filter(Boolean).join(" + ");
|
|
5693
|
+
process.stderr.write(`[exceptd attest diff] TAMPERED: ${sides} attestation failed Ed25519 verification. Refusing to diff against forged input. Pass --force-replay to override (the output records a_sidecar_verify + b_sidecar_verify).\n`);
|
|
5694
|
+
emit({
|
|
5695
|
+
ok: false,
|
|
5696
|
+
error: `attest diff: ${sides} attestation failed signature verification — refusing to diff`,
|
|
5697
|
+
verb: "attest diff",
|
|
5698
|
+
a_session: sessionId,
|
|
5699
|
+
b_session: args.against,
|
|
5700
|
+
a_sidecar_verify: aSidecarVerify,
|
|
5701
|
+
b_sidecar_verify: bSidecarVerify,
|
|
5702
|
+
hint: "If a sidecar was intentionally removed/rotated and you have inspected the attestation, pass --force-replay.",
|
|
5703
|
+
}, pretty);
|
|
5704
|
+
process.exitCode = EXIT_CODES.TAMPERED;
|
|
5705
|
+
return;
|
|
5706
|
+
}
|
|
5676
5707
|
emit({
|
|
5677
5708
|
verb: "attest diff",
|
|
5678
5709
|
a_session: sessionId,
|
|
@@ -5683,7 +5714,9 @@ function cmdAttest(runner, args, runOpts, pretty) {
|
|
|
5683
5714
|
a_evidence_hash: self.evidence_hash,
|
|
5684
5715
|
b_evidence_hash: other.evidence_hash,
|
|
5685
5716
|
status: self.evidence_hash === other.evidence_hash ? "unchanged" : "drifted",
|
|
5686
|
-
sidecar_verify:
|
|
5717
|
+
sidecar_verify: aSidecarVerify,
|
|
5718
|
+
a_sidecar_verify: aSidecarVerify,
|
|
5719
|
+
b_sidecar_verify: bSidecarVerify,
|
|
5687
5720
|
// v0.11.8 (#102): normalize submissions before diffing so flat-shape
|
|
5688
5721
|
// (observations + verdict) submissions emit meaningful artifact_diff
|
|
5689
5722
|
// counts. Pre-0.11.8 (self.submission||{}).artifacts was undefined
|
package/data/_indexes/_meta.json
CHANGED
|
@@ -1,61 +1,62 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema_version": "1.1.0",
|
|
3
|
-
"generated_at": "2026-06-
|
|
3
|
+
"generated_at": "2026-06-12T07:53:17.256Z",
|
|
4
4
|
"generator": "scripts/build-indexes.js",
|
|
5
|
-
"source_count":
|
|
5
|
+
"source_count": 64,
|
|
6
6
|
"source_hashes": {
|
|
7
|
-
"manifest.json": "
|
|
8
|
-
"
|
|
9
|
-
"data/
|
|
7
|
+
"manifest.json": "7cdbf86213bc03cc55f8cd1ec5516f7c492177f0968c27216beabf68fdd68ef1",
|
|
8
|
+
"README.md": "e7b854e7db9a364a1b368b5084b4f0c2a8282f0459ce39800ac1d1dabdc06074",
|
|
9
|
+
"data/atlas-ttps.json": "29f3447ac5c45f42f50b3ed8a46010c2b8ecbcc8094bb19b5db57ba4707b396c",
|
|
10
|
+
"data/attack-techniques.json": "6506db66fdd69bb3564e12aef8f727edddc55d0e6e99f60833a200a57e8ee65e",
|
|
10
11
|
"data/cve-catalog.json": "51d8425a49e5cc0375d0a154a83a16816e99c3141a5bbafe6383607ca11be240",
|
|
11
12
|
"data/cwe-catalog.json": "b398003b68b0d9539d13a5536e933005149fd05f3d33978297c870987542cd86",
|
|
12
13
|
"data/d3fend-catalog.json": "9a54bccb9f24f84b32024216cc3f53819a053721ac8ab43c326859e68fc0ffaf",
|
|
13
14
|
"data/dlp-controls.json": "d2406c482dddd30e49203879999dc4b3a7fd4d0494d6a61d86b91ee76415df19",
|
|
14
15
|
"data/exploit-availability.json": "ec2656f0d9a893610e27b43eb6035fe9b18e057c9f6dfaac7e7d4959bbcbb795",
|
|
15
|
-
"data/framework-control-gaps.json": "
|
|
16
|
+
"data/framework-control-gaps.json": "b0ad6a39648322df7f5c596238acdc791631eb1d047171be53576808c64b03ce",
|
|
16
17
|
"data/global-frameworks.json": "9ba563a85f7f8d6c3c957de64945e20925a89d0ed6ea6fc561cf093811acf558",
|
|
17
18
|
"data/rfc-references.json": "b21d03b948c41bc8a854e2f057948ecf844bd8c105848aeb141d1eadf8192c31",
|
|
18
19
|
"data/zeroday-lessons.json": "b6403d31f06e8f081217c338d2d5c515f8352295fbf58395f3c571cd95a05de0",
|
|
19
20
|
"skills/kernel-lpe-triage/skill.md": "0f79c641cef6e5f4a942eb94f43c460562bf83dfb67ae112d146c39c6b320fb0",
|
|
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": "
|
|
21
|
+
"skills/ai-attack-surface/skill.md": "6eefa7772f1faf9c8ed971f2a827cd48398a12ab3b691b258c7c8364a5deb39c",
|
|
22
|
+
"skills/mcp-agent-trust/skill.md": "bda6842bfa3b8bfd5edb3ef37751c493ff32a3ca80f771c3d988ede4176f0803",
|
|
23
|
+
"skills/framework-gap-analysis/skill.md": "fdc5a60f63af6050a2a89d123bc99b63196b1dbd64b3d22259a423b5b560d125",
|
|
24
|
+
"skills/compliance-theater/skill.md": "72f97f85ff93894ce3d514d5c6ebb8d843be4c0eb5f5f5dce079eaa90738309a",
|
|
25
|
+
"skills/exploit-scoring/skill.md": "b59a24c70e79c0fc5a389f095a07a07c9a96e266fa37f507d886daa4df535abc",
|
|
26
|
+
"skills/rag-pipeline-security/skill.md": "c839de2fe1efc23c4c89745cea953f8e81de43c55117a4192e80b7e487670078",
|
|
27
|
+
"skills/ai-c2-detection/skill.md": "ac555b9c9a59a26655bfa79cbccd8aa1bd2773c1314abf33546353e852939ff9",
|
|
28
|
+
"skills/policy-exception-gen/skill.md": "1a2dbb8e836277cddba0e24c86e57088b36a9a766bf907adb21d7ce4a487277f",
|
|
29
|
+
"skills/threat-model-currency/skill.md": "a784c2b9f00aa259c1612eb9983cc8a53a91331a800831d2cda5301ea951a914",
|
|
29
30
|
"skills/global-grc/skill.md": "8d1dfbae79153d403d543b3481f463260a89a35d068db0fa9eeda21c01c78e09",
|
|
30
|
-
"skills/zeroday-gap-learn/skill.md": "
|
|
31
|
-
"skills/pqc-first/skill.md": "
|
|
32
|
-
"skills/skill-update-loop/skill.md": "
|
|
33
|
-
"skills/security-maturity-tiers/skill.md": "
|
|
31
|
+
"skills/zeroday-gap-learn/skill.md": "b0d81f110d4aac3dbcf605c638b9cb4b5b377a2589ac98de60a72445368ed903",
|
|
32
|
+
"skills/pqc-first/skill.md": "803b3dc39eba4caa4f08980806b5fd02fb20b3655625cf014adccd85e4320e16",
|
|
33
|
+
"skills/skill-update-loop/skill.md": "d3514386d1fa04d21998991a0681c8dc154867f3ebe24a85131d526264ecd68c",
|
|
34
|
+
"skills/security-maturity-tiers/skill.md": "376e104f8a3f8aa2951825aa90de1acc2282ccc87a87615610277bffd1239db1",
|
|
34
35
|
"skills/researcher/skill.md": "9f1211d177c64e4c465407a45ad9e2901c5c6c0af410a0d0a51cc8fb780420d4",
|
|
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": "
|
|
39
|
-
"skills/defensive-countermeasure-mapping/skill.md": "
|
|
36
|
+
"skills/attack-surface-pentest/skill.md": "014863752eee05b8538aa8401511295c37df94fdb2936828ef37b66ed5388b11",
|
|
37
|
+
"skills/fuzz-testing-strategy/skill.md": "636a2d1d5846ecad3d75c48425d85b8a463fa68eca98858d5d96aca205905c4f",
|
|
38
|
+
"skills/dlp-gap-analysis/skill.md": "85f4025b41ab0ad6560155842b04a400c0f1a34bf89164f2d2bf4df05753c2dc",
|
|
39
|
+
"skills/supply-chain-integrity/skill.md": "b1fa90145a886e2943d89fc588fae6dccac2fec21a5068fd5b009a0e8b0efe8c",
|
|
40
|
+
"skills/defensive-countermeasure-mapping/skill.md": "48f140a265a96cd8c2d065f63a351ad02bbcbca5f75a686f3e8094e93f2d0383",
|
|
40
41
|
"skills/identity-assurance/skill.md": "86649aa573bde5b2ef2456a77d2fbfa9d1b623a4ef1326dd7a7ab384d0419307",
|
|
41
|
-
"skills/ot-ics-security/skill.md": "
|
|
42
|
-
"skills/coordinated-vuln-disclosure/skill.md": "
|
|
43
|
-
"skills/threat-modeling-methodology/skill.md": "
|
|
44
|
-
"skills/webapp-security/skill.md": "
|
|
42
|
+
"skills/ot-ics-security/skill.md": "80aa5a27ba31e57a80eb6d6fb8c8319a17e036ab341fc203515619b334449ab4",
|
|
43
|
+
"skills/coordinated-vuln-disclosure/skill.md": "8b752a1c7cafcb414ed32ef573ec62542e1e55872aa51157e86289deb0acb3f9",
|
|
44
|
+
"skills/threat-modeling-methodology/skill.md": "b67ce043e018df5079a7d7d5708687a63af177ea915aff52baaee1aa7b19e606",
|
|
45
|
+
"skills/webapp-security/skill.md": "d9817acfc1b52025857303d2839e2d9b4e87ee963c7ab9ffdc356d938eed0c72",
|
|
45
46
|
"skills/ai-risk-management/skill.md": "3e116dc6f03f31e32f1ee885516d72d9c11d3ff67d2184108b13dcbdf5f417bf",
|
|
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": "
|
|
47
|
+
"skills/sector-healthcare/skill.md": "c8fecc8d7e0d3d88c3134bf9be3e4a9bf3e192b8307d393894bf1dee577ace25",
|
|
48
|
+
"skills/sector-financial/skill.md": "364839b2ed70e09bbce1db387633c6235422959758f73150d58e5ae728adf21c",
|
|
49
|
+
"skills/sector-federal-government/skill.md": "35ac67e9c67802b71576b723538704222426781f1feab48e08126c5f71db061a",
|
|
50
|
+
"skills/sector-energy/skill.md": "8c20e93e687fb41b5880d6f270a26915ecc8efa4b65797f728363dd59d7374fc",
|
|
50
51
|
"skills/sector-telecom/skill.md": "4b80771e78a474e3f43227ecc730ddda1684bff98d7e6e53f5ec373e1e886f34",
|
|
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": "
|
|
52
|
+
"skills/api-security/skill.md": "9cd5bc4b6ae46afade496b0772d013a302a4a6858414dd757f317c1f9c84942d",
|
|
53
|
+
"skills/cloud-security/skill.md": "128323a2bae6a70e9e8fc31f7bf207688542da7d7f0355fbe72bd6db7dc73768",
|
|
54
|
+
"skills/container-runtime-security/skill.md": "6d9f3c04e4ae7323d41f66d563d96bbdef2c301459b2bf9d4828a5dbae9ef021",
|
|
55
|
+
"skills/mlops-security/skill.md": "af4e563f7da7b98c75d56556ec7d1f9bba8f204c586ebd981562c5e3526dbed8",
|
|
56
|
+
"skills/incident-response-playbook/skill.md": "20e4f0463aea6b1968f1cafb5b682ecdab3b7f38c16c9e051ce9514f50c42faf",
|
|
57
|
+
"skills/ransomware-response/skill.md": "d2f84694fdfa5fc21a5e959dcc8b4458d595715cb240642f30638ceb3d00c100",
|
|
57
58
|
"skills/email-security-anti-phishing/skill.md": "0965eca982e8fc633b85e70c0ba6becb8c0f5ee7bdd0be96ad73a9a222bb8816",
|
|
58
|
-
"skills/age-gates-child-safety/skill.md": "
|
|
59
|
+
"skills/age-gates-child-safety/skill.md": "2cae96ba7cfde40b98016b8a9bc5450d79c6218cabb7165625cfaf3f5fd06f2e",
|
|
59
60
|
"skills/cloud-iam-incident/skill.md": "6aab2e400d1e87df7ac2b6f0a17dac6aa99723b217258c4a7b446703d1521775",
|
|
60
61
|
"skills/idp-incident-response/skill.md": "cb2f2c5b90de4592bfd66dcd55f9bf2004f370746d519cad577fcbaf36125878",
|
|
61
62
|
"skills/vc-wallet-trust/skill.md": "802dada75d934c9ab322246f650eb2eac9e2f72c1f094b0cebcfa605b56108a5",
|
|
@@ -87,7 +88,7 @@
|
|
|
87
88
|
"handoff_dag_nodes": 51,
|
|
88
89
|
"summary_cards": 51,
|
|
89
90
|
"section_offsets_skills": 51,
|
|
90
|
-
"token_budget_total_approx":
|
|
91
|
+
"token_budget_total_approx": 435989,
|
|
91
92
|
"recipes": 8,
|
|
92
93
|
"jurisdiction_clocks": 29,
|
|
93
94
|
"did_ladders": 8,
|