@blamejs/exceptd-skills 0.19.30 → 0.19.32
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/ARCHITECTURE.md +32 -23
- package/CHANGELOG.md +28 -0
- package/CONTEXT.md +19 -11
- package/README.md +99 -18
- package/SECURITY.md +65 -45
- package/data/_indexes/_meta.json +9 -9
- package/data/_indexes/activity-feed.json +12 -12
- package/data/_indexes/catalog-summaries.json +12 -12
- package/data/_indexes/chains.json +65405 -16
- package/data/attack-techniques.json +289 -10
- package/data/cve-catalog.json +11817 -473
- package/data/cwe-catalog.json +114 -3
- package/data/framework-control-gaps.json +622 -3
- package/data/zeroday-lessons.json +8753 -3
- package/lib/collectors/citation-hygiene.js +7 -1
- package/lib/cve-batch.js +27 -57
- package/lib/cve-curation.js +26 -1
- package/lib/cve-enrich.js +18 -43
- package/lib/refresh-external.js +100 -1
- package/lib/scoring.js +158 -372
- package/lib/validate-cve-catalog.js +11 -0
- package/lib/validate-package.js +5 -2
- package/manifest.json +53 -53
- package/package.json +2 -2
- package/sbom.cdx.json +51 -51
- package/sources/validators/cve-validator.js +40 -15
package/ARCHITECTURE.md
CHANGED
|
@@ -6,7 +6,7 @@ exceptd Security is a skills repository. Each skill is a `.md` file with YAML fr
|
|
|
6
6
|
|
|
7
7
|
The repository has three layers:
|
|
8
8
|
|
|
9
|
-
```
|
|
9
|
+
```text
|
|
10
10
|
skills/ Instruction layer — tells the AI what to analyze, how to score, what to output
|
|
11
11
|
data/ Intelligence layer — CVE metadata, ATLAS TTPs, framework gap mappings
|
|
12
12
|
lib/ Logic layer — scoring algorithms, TTP mapper, framework gap analyzer
|
|
@@ -16,7 +16,7 @@ lib/ Logic layer — scoring algorithms, TTP mapper, framework gap a
|
|
|
16
16
|
|
|
17
17
|
## Skill File Anatomy
|
|
18
18
|
|
|
19
|
-
```
|
|
19
|
+
```text
|
|
20
20
|
skills/
|
|
21
21
|
└── <skill-name>/
|
|
22
22
|
└── skill.md Single file per skill. Frontmatter + body.
|
|
@@ -42,7 +42,7 @@ attack_refs:
|
|
|
42
42
|
- T1068 # MITRE ATT&CK TTP IDs
|
|
43
43
|
framework_gaps:
|
|
44
44
|
- NIST-800-53-SI-2 # control IDs documented as insufficient in this skill
|
|
45
|
-
- ISO-27001-A.
|
|
45
|
+
- ISO-27001-2022-A.8.8 # must resolve against data/framework-control-gaps.json
|
|
46
46
|
last_threat_review: "2026-05-01"
|
|
47
47
|
---
|
|
48
48
|
```
|
|
@@ -84,7 +84,7 @@ Schema per entry:
|
|
|
84
84
|
"poc_description": "Public PoC description — no direct exploit links",
|
|
85
85
|
"ai_discovered": false,
|
|
86
86
|
"ai_assisted_weaponization": false,
|
|
87
|
-
"active_exploitation":
|
|
87
|
+
"active_exploitation": "confirmed | suspected | theoretical | none | unknown",
|
|
88
88
|
"affected": "Human-readable scope description",
|
|
89
89
|
"affected_versions": ["kernel >= 4.14", "kernel < 6.8.10"],
|
|
90
90
|
"vector": "Attack vector description",
|
|
@@ -95,26 +95,33 @@ Schema per entry:
|
|
|
95
95
|
"live_patch_tools": ["kpatch", "livepatch", "kGraft"],
|
|
96
96
|
"framework_control_gaps": {
|
|
97
97
|
"NIST-800-53-SI-2": "Why this control is insufficient for this CVE",
|
|
98
|
-
"ISO-27001-A.
|
|
98
|
+
"ISO-27001-2022-A.8.8": "Why this control is insufficient"
|
|
99
99
|
},
|
|
100
100
|
"atlas_refs": ["AML.T0043"],
|
|
101
101
|
"attack_refs": ["T1068"],
|
|
102
|
-
"rwep_score":
|
|
102
|
+
"rwep_score": 85,
|
|
103
103
|
"rwep_factors": {
|
|
104
104
|
"cisa_kev": 25,
|
|
105
105
|
"poc_available": 20,
|
|
106
|
-
"
|
|
106
|
+
"ai_factor": 0,
|
|
107
107
|
"active_exploitation": 20,
|
|
108
|
-
"blast_radius":
|
|
109
|
-
"patch_available":
|
|
110
|
-
"
|
|
111
|
-
"reboot_required":
|
|
108
|
+
"blast_radius": 20,
|
|
109
|
+
"patch_available": 0,
|
|
110
|
+
"live_patch_available": 0,
|
|
111
|
+
"reboot_required": 0
|
|
112
112
|
},
|
|
113
113
|
"last_updated": "YYYY-MM-DD"
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
116
|
```
|
|
117
117
|
|
|
118
|
+
Two invariants the schema cannot express and the validator enforces:
|
|
119
|
+
`rwep_factors` must sum to `rwep_score`, and every key must match the weight
|
|
120
|
+
names in `lib/scoring.js` — `ai_factor` and `live_patch_available`, not
|
|
121
|
+
`ai_assisted` and `live_patch`. The weights are `cisa_kev` 25, `poc_available`
|
|
122
|
+
20, `ai_factor` 15, `active_exploitation` 20, `blast_radius` 0–30,
|
|
123
|
+
`patch_available` −15, `live_patch_available` −10, `reboot_required` +5.
|
|
124
|
+
|
|
118
125
|
### `data/atlas-ttps.json`
|
|
119
126
|
|
|
120
127
|
Schema per entry:
|
|
@@ -176,7 +183,7 @@ Tracks PoC status, weaponization stage, and AI-assist factor per CVE. Updated wh
|
|
|
176
183
|
|
|
177
184
|
### `data/cwe-catalog.json`
|
|
178
185
|
|
|
179
|
-
|
|
186
|
+
236 CWE entries pinned to **CWE v4.20**. 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.
|
|
180
187
|
|
|
181
188
|
`_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`.
|
|
182
189
|
|
|
@@ -207,16 +214,18 @@ RWEP (Real-World Exploit Priority) scoring engine.
|
|
|
207
214
|
- `validate()` — Schema validation: check all skill data_deps resolve, all CVE entries are complete, all ATLAS refs are valid v2026.07 IDs
|
|
208
215
|
- `compare(cveId)` — Return CVSS vs. RWEP comparison with explanation of the delta
|
|
209
216
|
|
|
210
|
-
RWEP factor weights
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
217
|
+
RWEP factor weights. The key names here are the ones a catalog entry's
|
|
218
|
+
`rwep_factors` must use, and the factors must sum to `rwep_score`:
|
|
219
|
+
|
|
220
|
+
```text
|
|
221
|
+
cisa_kev +25 binary
|
|
222
|
+
poc_available +20 binary
|
|
223
|
+
ai_factor +15 binary — ai_discovered OR ai_assisted_weaponization
|
|
224
|
+
active_exploitation +20 graded — confirmed 20, suspected 10, unknown 5, none 0
|
|
225
|
+
blast_radius 0-30 scaled
|
|
226
|
+
patch_available -15 binary
|
|
227
|
+
live_patch_available -10 binary
|
|
228
|
+
reboot_required +5 binary — the patch exists but needs a reboot
|
|
220
229
|
```
|
|
221
230
|
|
|
222
231
|
### `lib/ttp-mapper.js`
|
|
@@ -277,7 +286,7 @@ Skills can be composed. `framework-gap-analysis` calls out to `threat-model-curr
|
|
|
277
286
|
|
|
278
287
|
Composition is explicit: skills declare which other skills they depend on in their frontmatter `skill_deps` field. Circular dependencies are not permitted.
|
|
279
288
|
|
|
280
|
-
```
|
|
289
|
+
```text
|
|
281
290
|
zeroday-gap-learn → framework-control-gaps.json (writes)
|
|
282
291
|
framework-gap-analysis → framework-control-gaps.json (reads)
|
|
283
292
|
compliance-theater → exploit-scoring (depends on RWEP)
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.19.32 — 2026-08-21
|
|
4
|
+
|
|
5
|
+
A KEV entry stores four fields from CISA's record and the refresh compared two of them. The listing flag and its date tracked upstream; the remediation deadline and the ransomware designation were written once, at curation, and never looked at again. Both now reconcile on every refresh, on the live path and the cached one alike, which closes a gap that had been widening since the fields were first stored.
|
|
6
|
+
|
|
7
|
+
The catalog is corrected accordingly. Fifty-one entries carried no ransomware designation where CISA now records one, and forty-three of those had no such field at all — which every consumer reads as a denial rather than as an absence. All 1,167 KEV-listed entries now carry the boolean explicitly, and the catalog validator refuses one that does not, so the field cannot go back to being sometimes-absent. Four entries stated a remediation deadline of twenty-one days after listing where CISA required three or fourteen; that date is rendered into remediation output and regulator notification drafts, so it was telling operators they had time the directive does not give them. Eleven more had no deadline stored at all.
|
|
8
|
+
|
|
9
|
+
Six entries said in prose that CISA recorded no ransomware association while their own corrected flag said otherwise. An entry that contradicts itself is worse than one that is simply wrong, because the reader cannot tell which half to believe; those sentences now state what the record states.
|
|
10
|
+
|
|
11
|
+
A designation no longer outlives the listing it came from. When CISA removes a CVE, the refresh already cleared the listing dates but left the ransomware flag standing on a record that no longer exists; it is cleared to unknown rather than to false, since false would assert something upstream is no longer there to say.
|
|
12
|
+
|
|
13
|
+
`refresh --drift-only` reconciles the entries the catalog already holds and skips discovery of new ones. Discovery imports drafts that still need curation, so correcting stale fields on shipped entries previously meant either taking that work in the same change or leaving the fields stale.
|
|
14
|
+
|
|
15
|
+
The repository documentation describes the repository again. `ARCHITECTURE.md` carried a CVE schema example — the block a contributor copies — whose `active_exploitation` was a boolean where the schema defines a five-value string, whose factor keys were `ai_assisted` and `live_patch` where the scorer reads `ai_factor` and `live_patch_available`, and whose patch weights were −7 and −5 against the real −15 and −10. It also cited an ISO control under its superseded 2013 numbering, which resolves against nothing. `CONTEXT.md` wrote the RWEP formula with a minus in front of two already-negative weights, turning both mitigating factors into penalties. `MAINTAINERS.md` told a maintainer to commit and push to `main`, which requires a pull request and rejects the push, and restated upstream version pins that had drifted from the catalogs that own them. `SECURITY.md` told reporters not to open a public issue without naming the private advisory channel that is enabled. Counts across all six files now match the data they describe.
|
|
16
|
+
|
|
17
|
+
Comment volume is down across the scoring engine and the curation modules, with every surviving comment either a contract the signature cannot state or a trap worth naming. No behavior changed.
|
|
18
|
+
|
|
19
|
+
## 0.19.31 — 2026-08-19
|
|
20
|
+
|
|
21
|
+
The catalog reaches 1,323 CVEs with 98 additions from CISA KEV, spanning 2005 to 2025 with the weight in the middle years: 15 from 2019, 11 from 2016, 10 each from 2018 and 2020. Microsoft accounts for 29, with Adobe, Cisco, D-Link, Oracle, Apache, Citrix, NETGEAR and VMware behind it. Twenty-four carry CISA's ransomware designation and 76 have an obtainable public exploit.
|
|
22
|
+
|
|
23
|
+
Fifty-one need a restart before the fix is running, and the entries keep that separate from the update being installed. A browser engine, a kernel extension or a service DLL keeps serving the vulnerable code until the process or the host restarts, so a remediation record keyed to the deployed version reports hosts as done while the pre-patch code executes. For nine of the additions CISA's required action is removal rather than patching, and five have no vendor fix at all; those entries name removal as the remediation instead of describing an upgrade path that does not exist.
|
|
24
|
+
|
|
25
|
+
Where sources disagree, the entries carry the disagreement. A Metasploit module frames CVE-2013-2551 as an integer overflow while NVD and Microsoft classify it as a use-after-free, and the entry leads with the vendor classification while describing the path the public tooling drives. Where a vendor publishes an unspecified-vulnerability row and nothing more, as Oracle does for CVE-2012-0518, the entry says the mechanism is not on the public record rather than inventing one.
|
|
26
|
+
|
|
27
|
+
Public-exploit availability is recorded as a finding in both directions, and a negative names the check that produced it: which index was searched, and a public CVE whose entries that same search returns, so a reader can tell a real absence from a broken query. Several entries record a near miss explicitly — a Metasploit module belonging to an adjacent CVE, a write-up with no code, an exploit whose author withheld it.
|
|
28
|
+
|
|
29
|
+
Framework-gap statements now rest on each CVE's own dates, versions, KB numbers and vendor wording. Claims about what organisations typically do — which patches get deferred, which assets sit outside an inventory, what a monitoring programme usually collects — are gone, because none of them could be sourced and each was load-bearing for the conclusion it supported.
|
|
30
|
+
|
|
3
31
|
## 0.19.30 — 2026-08-18
|
|
4
32
|
|
|
5
33
|
Three CISA KEV entries join the catalog, taking it to 1,225. Each of them turns on a question its sources answer differently, which is why they landed a release later than the rest of their set.
|
package/CONTEXT.md
CHANGED
|
@@ -115,14 +115,14 @@ Skills and playbooks read from `data/`. Authoritative catalog inventory:
|
|
|
115
115
|
|
|
116
116
|
| File | Entries | Purpose |
|
|
117
117
|
|------|---------|---------|
|
|
118
|
-
| `cve-catalog.json` |
|
|
118
|
+
| `cve-catalog.json` | 1323 | CVEs with CVSS, RWEP score, EPSS estimates, CISA KEV flags, PoC and live-patch availability |
|
|
119
119
|
| `atlas-ttps.json` | 174 | MITRE ATLAS v2026.07 (August 2026) techniques with framework gap flags |
|
|
120
120
|
| `attack-techniques.json` | 794 | MITRE ATT&CK techniques with framework coverage mappings |
|
|
121
121
|
| `framework-control-gaps.json` | 194 | Framework control gap entries: designed-for vs. what each control misses |
|
|
122
122
|
| `exploit-availability.json` | 28 | Per-CVE PoC locations, weaponization stage, AI-acceleration factor, live-patch status |
|
|
123
123
|
| `global-frameworks.json` | 35 jurisdictions | Patch SLAs and notification windows across global regulatory regimes |
|
|
124
|
-
| `zeroday-lessons.json` |
|
|
125
|
-
| `cwe-catalog.json` |
|
|
124
|
+
| `zeroday-lessons.json` | 1323 | Learning-loop entries: zero-day → attack vector → control gap → framework gap → new control |
|
|
125
|
+
| `cwe-catalog.json` | 236 | CWE v4.20 entries (Top 25 2024 plus AI- and supply-chain-relevant weaknesses) |
|
|
126
126
|
| `d3fend-catalog.json` | 468 | MITRE D3FEND v1.3.0 defensive techniques for offensive → defensive mapping |
|
|
127
127
|
| `rfc-references.json` | 8889 | IETF RFC / Internet-Draft references with status, errata count, replaces / replaced-by, `last_verified` dates |
|
|
128
128
|
| `dlp-controls.json` | 22 | DLP control entries indexed by channel, classifier, surface, enforcement mode, evidence type |
|
|
@@ -154,16 +154,24 @@ researcher — front-door dispatcher for raw threat intel
|
|
|
154
154
|
|
|
155
155
|
The repository uses Real-World Exploit Priority (RWEP) scoring, not CVSS alone. CVSS is reported alongside RWEP but never as the sole score.
|
|
156
156
|
|
|
157
|
-
RWEP
|
|
158
|
-
|
|
159
|
-
base = cisa_kev(+25) + poc_public(+20) + ai_factor(+15)
|
|
160
|
-
+ active_exploitation(+20) + blast_radius(0-30)
|
|
161
|
-
- patch_available(-15) - live_patch(-10) + reboot_required(+5)
|
|
157
|
+
RWEP is the sum of eight weighted factors, clamped to 0–100. The two mitigating
|
|
158
|
+
factors carry negative weights, so every term is added:
|
|
162
159
|
|
|
163
|
-
ai_factor = ai_discovered OR ai_assisted_weaponization
|
|
164
|
-
blast_radius = 0-30 scale (30 = all-Linux or 150M+ installations)
|
|
165
|
-
reboot_required = +5 always when patch requires reboot
|
|
166
160
|
```
|
|
161
|
+
rwep_score = cisa_kev(+25) + poc_available(+20) + ai_factor(+15)
|
|
162
|
+
+ active_exploitation(+20) + blast_radius(0..+30)
|
|
163
|
+
+ patch_available(-15) + live_patch_available(-10)
|
|
164
|
+
+ reboot_required(+5)
|
|
165
|
+
|
|
166
|
+
ai_factor = ai_discovered OR ai_assisted_weaponization
|
|
167
|
+
blast_radius = 0-30 (30 = all-Linux, or an install base in the 150M range)
|
|
168
|
+
active_exploitation = +20 confirmed, +10 suspected, +5 unknown
|
|
169
|
+
reboot_required = +5 whenever the patch needs a reboot
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
The stored `rwep_factors` must sum to the stored `rwep_score`; the catalog
|
|
173
|
+
validator fails the entry when they disagree. `lib/scoring.js` holds the weights,
|
|
174
|
+
and its key names are the ones the catalog must use.
|
|
167
175
|
|
|
168
176
|
Example: CVE-2026-31431 (Copy Fail) — CVSS 7.8 / **RWEP 90**
|
|
169
177
|
- CVSS 7.8 suggests "high, patch within 30 days"
|
package/README.md
CHANGED
|
@@ -28,9 +28,27 @@
|
|
|
28
28
|
|
|
29
29
|
Every skill explicitly flags where a compliance framework's control is insufficient for current attack patterns. The framework is often the problem, not the org.
|
|
30
30
|
|
|
31
|
-
##
|
|
31
|
+
## What ships
|
|
32
32
|
|
|
33
|
-
Pre-1.0.
|
|
33
|
+
Pre-1.0. Released on [GitHub](https://github.com/blamejs/exceptd-skills/releases)
|
|
34
|
+
and on npm as [`@blamejs/exceptd-skills`](https://www.npmjs.com/package/@blamejs/exceptd-skills),
|
|
35
|
+
with npm provenance attestation and an Ed25519 signature on every skill body.
|
|
36
|
+
|
|
37
|
+
51 skills across kernel LPE, MCP supply chain, AI-as-C2, prompt injection,
|
|
38
|
+
post-quantum crypto, SBOM integrity, identity incident response and 35 further
|
|
39
|
+
domains.
|
|
40
|
+
|
|
41
|
+
| | |
|
|
42
|
+
|---|---|
|
|
43
|
+
| **11 catalogs** | CVE, ATLAS, ATT&CK, CWE, D3FEND, DLP, RFC, framework gaps, global frameworks, zero-day lessons, exploit availability — across 35 jurisdictions |
|
|
44
|
+
| **1,323 CVEs** | Each with behavioral indicators, an ATT&CK technique mapping, and a defense-chain zero-day lesson |
|
|
45
|
+
| **33 playbooks** | Seven-phase investigations: `kernel`, `mcp`, `ai-api`, `sbom`, `containers`, `crypto`, `secrets` and the rest, through `webhook-callback-abuse`, `cicd-pipeline-compromise`, `identity-sso-compromise`, `llm-tool-use-exfil` and `post-quantum-migration`. `exceptd brief --all` is the live list |
|
|
46
|
+
| **A CLI** | `discover → brief → run → attest`, where each run executes the playbook's seven-phase contract |
|
|
47
|
+
|
|
48
|
+
A nightly job pulls KEV, NVD, EPSS, GHSA, OSV and IETF deltas alongside 15
|
|
49
|
+
advisory, vendor-research and tech-press feeds, and opens a pull request for
|
|
50
|
+
editorial review rather than merging. A companion watcher flags historical CVEs
|
|
51
|
+
re-broken without a new identifier being assigned.
|
|
34
52
|
|
|
35
53
|
---
|
|
36
54
|
|
|
@@ -159,20 +177,6 @@ Verify on npm: `npm view @blamejs/exceptd-skills@<version> dist.signatures` show
|
|
|
159
177
|
|
|
160
178
|
Air-gapped operation: run `exceptd refresh --prefetch` on a connected host, copy the resulting `.cache/upstream/` to the airgap, run `exceptd refresh --from-cache <path> --apply` over there. The vendored upstream snapshots replace every network call.
|
|
161
179
|
|
|
162
|
-
Fresh-disclosure workflow (v0.12.0): the nightly auto-PR job pulls KEV / NVD / EPSS / IETF / **GHSA** (added in v0.12.0) / **OSV** (added in v0.12.10). KEV typically takes days; NVD ~10 days; GHSA fires within hours of disclosure and covers npm + PyPI + Maven + Go + NuGet + …; OSV aggregates the OSSF Malicious Packages dataset (`MAL-*` keys) + Snyk + RustSec + Mageia + Ubuntu USN + Go Vuln DB + PYSEC + UVI on top of GHSA — useful for malicious-package compromises that don't have CVEs yet (`exceptd refresh --advisory MAL-2026-3083`). New IDs land as drafts (`_auto_imported: true`, `_draft: true`) that the catalog validator treats as warnings, not errors — operators get the fresh entry immediately, editorial review (framework gaps, IoCs, ATLAS/ATT&CK refs) follows via `exceptd refresh --curate <ID>`. To pull one advisory immediately: `exceptd refresh --advisory <CVE-or-GHSA-or-MAL-or-SNYK-or-RUSTSEC-ID> --apply`.
|
|
163
|
-
|
|
164
|
-
Primary-source advisory polling: `exceptd refresh --check-advisories` polls 15 vendor and coordinated-disclosure feeds — 8 advisory/coordinated-disclosure venues (Qualys TRU, Red Hat RHSA, Ubuntu USN, Zero Day Initiative, kernel.org commits, oss-security mailing list, JFrog SecOps, CISA current advisories), 4 vendor security research blogs (Microsoft Security Blog, Sysdig, Trail of Bits, Embrace the Red), and 3 more (BleepingComputer security, The Hacker News, and a researcher activity-feed tracker). Combined coverage publishes CVE IDs at T+0 to T+1 — typically 3–14 days ahead of NVD enrichment. The command is report-only: it returns a structured `diffs[]` listing each newly-seen CVE ID with its source attributions and advisory URLs, but does not mutate the catalog. A complementary silent-regression watcher (`lib/cve-regression-watcher.js`) cross-checks poller diffs for historical-CVE references (year ≤ currentYear − 2) and surfaces candidate silent-regression cases — historical CVEs re-broken by a new proof-of-concept without a new ID being assigned. Operators triage the output and route promising IDs through `exceptd refresh --advisory <CVE-ID> --apply`. Pairs with the daily scheduled remote agent below.
|
|
165
|
-
|
|
166
|
-
CVE-class alert surfacing: `exceptd watchlist --alerts` matches the live `cve-catalog.json` against five operational patterns (`kernel_lpe_with_poc`, `supply_chain_family`, `ai_discovered_kev`, `active_exploitation_unpatched`, `recent_poc_no_kev_yet`) and returns the matches sorted critical-severity-first, then by RWEP. Use it to triage a refreshed catalog without scanning every entry by hand.
|
|
167
|
-
|
|
168
|
-
GitHub repo-pattern monitoring: `exceptd watchlist --org-scan --org <login>` probes GitHub Search for repositories matching known threat-actor naming patterns ("A Gift From TeamPCP", "Shai-Hulud", "TeamPCP") scoped to one org. Custom patterns via repeatable `--pattern <s>`. Implements the canonical detection for the Shai-Hulud / TeamPCP supply-chain framework class — the attacker uses GitHub itself as the exfil channel. Set `GITHUB_TOKEN` for private-repo coverage and rate-limit headroom; public-repo search works without auth.
|
|
169
|
-
|
|
170
|
-
AI-assistant config-file audit: `exceptd doctor --ai-config` walks `~/.claude`, `~/.cursor`, `~/.codeium`, `~/.aider`, and `~/.continue`, flagging sensitive files (`settings.json`, `mcp.json`, `*.mcp_config.json`, `api_key*`, `*.token`, `*.credentials`) not at mode 0600 on POSIX. On Windows the mode bits aren't load-bearing; each finding is surfaced with an info-level "manual ACL review" note. Catches the AI-config-credential-exfil class that the Shai-Hulud framework targets. Opt-in — does not run as part of the default no-flag `doctor` pass.
|
|
171
|
-
|
|
172
|
-
Evidence-collection layer: `exceptd collect <playbook>` invokes a companion script under `lib/collectors/<playbook>.js` that walks cwd, applies the catalogued regex set, stats permissions, and emits the submission JSON in the same shape `exceptd run --evidence -` accepts. 14 of 33 playbooks have collectors today (`ai-api`, `cicd-pipeline-compromise`, `citation-hygiene`, `containers`, `cred-stores`, `crypto`, `crypto-codebase`, `hardening`, `kernel`, `library-author`, `mcp`, `runtime`, `sbom`, `secrets`); the remaining 19 are policy-skipped per AGENTS.md (judgement-shaped incident / governance / pure-analyze playbooks where AI-driven evidence collection is the design). Canonical operator pipe: `exceptd collect <pb> | exceptd run <pb> --evidence -`. `exceptd doctor --collectors` enumerates the layer; `exceptd discover` tags applicable playbooks with `[collector]` when one ships. `cicd-pipeline-compromise` requires `--attest-ownership` on the collect call (the playbook's `operator-owns-ci-fleet` precondition is opt-in to prevent unauthorized CI assessments).
|
|
173
|
-
|
|
174
|
-
Daily scheduled threat intake: a `routine: exceptd-threat-intake` (claude.ai remote agent) runs daily at 14:00 UTC. 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 the catalog mutated → commit on `intake/<YYYY-MM-DD>` branch with the full diff in the report. Fresh disclosures no longer wait for an operator to trigger an intake run. Operator-managed at <https://claude.ai/code/routines>.
|
|
175
|
-
|
|
176
180
|
Optional env vars for higher rate budgets:
|
|
177
181
|
|
|
178
182
|
| Variable | Purpose |
|
|
@@ -202,11 +206,83 @@ npm run predeploy # full predeploy gate sequence locally
|
|
|
202
206
|
|
|
203
207
|
Direct invocations also available: `npm run verify`, `node lib/sign.js sign-all`.
|
|
204
208
|
|
|
209
|
+
## Keeping the catalog current
|
|
210
|
+
|
|
211
|
+
A CVE reaches the catalog through one of three paths, at different speeds.
|
|
212
|
+
|
|
213
|
+
**The nightly job** pulls KEV, NVD, EPSS, IETF, GHSA and OSV. They arrive at
|
|
214
|
+
different times: KEV takes days and NVD around ten, while GHSA fires within hours
|
|
215
|
+
of disclosure across npm, PyPI, Maven, Go and NuGet. OSV layers Snyk, RustSec,
|
|
216
|
+
Mageia, Ubuntu USN, the Go vulnerability database, PYSEC and UVI on top, plus the
|
|
217
|
+
OSSF Malicious Packages dataset — which is where a compromised package with no
|
|
218
|
+
CVE shows up at all. New IDs land as drafts flagged `_auto_imported`, which the
|
|
219
|
+
catalog validator reports as warnings rather than errors: the entry is available
|
|
220
|
+
immediately and the editorial work follows.
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
exceptd refresh --advisory CVE-2026-45321 --apply # pull one ID now
|
|
224
|
+
exceptd refresh --curate CVE-2026-45321 # editorial questions for a draft
|
|
225
|
+
exceptd refresh --drift-only --apply # reconcile what is already held
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
**Primary-source polling** runs ahead of all of them. `exceptd refresh
|
|
229
|
+
--check-advisories` reads 15 feeds — eight advisory and coordinated-disclosure
|
|
230
|
+
venues (Qualys TRU, Red Hat RHSA, Ubuntu USN, ZDI, kernel.org commits,
|
|
231
|
+
oss-security, JFrog SecOps, CISA), four vendor research blogs (Microsoft
|
|
232
|
+
Security, Sysdig, Trail of Bits, Embrace the Red), and three press and researcher
|
|
233
|
+
trackers. Between them they publish CVE IDs three to fourteen days ahead of NVD
|
|
234
|
+
enrichment. The command is report-only: it returns each newly-seen ID with its
|
|
235
|
+
sources and advisory URLs and changes nothing. `lib/cve-regression-watcher.js`
|
|
236
|
+
reads the same diffs for references to CVEs two or more years old, which is what
|
|
237
|
+
a silently re-broken historical flaw looks like before anyone assigns it a new
|
|
238
|
+
identifier.
|
|
239
|
+
|
|
240
|
+
**A daily agent** (`routine: exceptd-threat-intake`, 14:00 UTC) chains those
|
|
241
|
+
steps — poll, alert, refresh, enrich up to five new IDs, re-sign and rebuild if
|
|
242
|
+
the catalog moved — and commits to an `intake/<date>` branch. Managed at
|
|
243
|
+
<https://claude.ai/code/routines>.
|
|
244
|
+
|
|
245
|
+
Once a refresh lands, `exceptd watchlist --alerts` matches the catalog against
|
|
246
|
+
five operational patterns — `kernel_lpe_with_poc`, `supply_chain_family`,
|
|
247
|
+
`ai_discovered_kev`, `active_exploitation_unpatched`, `recent_poc_no_kev_yet` —
|
|
248
|
+
sorted critical-first, then by RWEP, so a refreshed catalog can be triaged
|
|
249
|
+
without reading every entry.
|
|
250
|
+
|
|
251
|
+
## Evidence collection
|
|
252
|
+
|
|
253
|
+
`exceptd collect <playbook>` walks the working directory, applies the playbook's
|
|
254
|
+
catalogued patterns, stats permissions, and emits submission JSON in the shape
|
|
255
|
+
`exceptd run --evidence -` accepts:
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
exceptd collect <playbook> | exceptd run <playbook> --evidence -
|
|
259
|
+
exceptd doctor --collectors # which playbooks ship one, and which do not
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
14 of the 33 playbooks ship a collector. The other 19 are deliberately without
|
|
263
|
+
one: they are judgement-shaped incident, governance and pure-analyze playbooks
|
|
264
|
+
where the evidence is an assessment rather than a file on disk.
|
|
265
|
+
`cicd-pipeline-compromise` additionally requires `--attest-ownership`, because
|
|
266
|
+
its `operator-owns-ci-fleet` precondition is what stops it being pointed at
|
|
267
|
+
someone else's CI.
|
|
268
|
+
|
|
269
|
+
Two scans sit outside the playbook contract:
|
|
270
|
+
|
|
271
|
+
- `exceptd watchlist --org-scan --org <login>` searches one GitHub org for
|
|
272
|
+
repositories matching known threat-actor naming patterns. This is the
|
|
273
|
+
detection for the supply-chain class that uses GitHub itself as the exfil
|
|
274
|
+
channel. Set `GITHUB_TOKEN` for private repositories and rate-limit headroom.
|
|
275
|
+
- `exceptd doctor --ai-config` checks `~/.claude`, `~/.cursor`, `~/.codeium`,
|
|
276
|
+
`~/.aider` and `~/.continue` for credential-bearing files — `settings.json`,
|
|
277
|
+
`mcp.json`, `api_key*`, `*.token`, `*.credentials` — left readable beyond mode
|
|
278
|
+
0600. Windows has no equivalent bit, so findings there are raised for manual
|
|
279
|
+
ACL review. Opt-in; the bare `doctor` pass does not run it.
|
|
280
|
+
|
|
205
281
|
## CLI command reference
|
|
206
282
|
|
|
207
283
|
Every command works the same via `npx @blamejs/exceptd-skills`, a global install (`exceptd`), or a local `node bin/exceptd.js`.
|
|
208
284
|
|
|
209
|
-
###
|
|
285
|
+
### Canonical verbs
|
|
210
286
|
|
|
211
287
|
```
|
|
212
288
|
exceptd First-run welcome — two ways to start
|
|
@@ -415,6 +491,11 @@ exceptd refresh Refresh upstream catalogs + indexes.
|
|
|
415
491
|
upstream artifact now (network required).
|
|
416
492
|
Run on a connected host, then point
|
|
417
493
|
--from-cache at the result on the air-gap.
|
|
494
|
+
--drift-only Reconcile the entries the catalog already
|
|
495
|
+
holds; skip discovery of new ones. Use it
|
|
496
|
+
to correct stale fields on shipped entries
|
|
497
|
+
without pulling in drafts that still need
|
|
498
|
+
curation.
|
|
418
499
|
--no-network Report-only dry-run: list what would be
|
|
419
500
|
fetched without touching the network.
|
|
420
501
|
--network (v0.11.14) Fetch latest signed catalog
|
|
@@ -506,7 +587,7 @@ exceptd <verb> --help Most verbs print per-verb usage with flag
|
|
|
506
587
|
descriptions.
|
|
507
588
|
```
|
|
508
589
|
|
|
509
|
-
###
|
|
590
|
+
### Deprecated and removed verbs
|
|
510
591
|
|
|
511
592
|
Five verbs removed in v0.13.0 after deprecation since v0.11.0. Invoking any of these now returns a structured `ok:false` refusal pointing at the replacement; pre-v0.13 scripts must migrate.
|
|
512
593
|
|
package/SECURITY.md
CHANGED
|
@@ -1,73 +1,93 @@
|
|
|
1
1
|
# Security Policy
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## Reporting a vulnerability
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Two private channels, either is fine:
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- **GitHub** — open a draft advisory from the repository's Security tab
|
|
8
|
+
([Report a vulnerability](https://github.com/blamejs/exceptd-skills/security/advisories/new)).
|
|
9
|
+
Private vulnerability reporting is enabled, so the report stays between you and
|
|
10
|
+
the maintainers until an advisory is published.
|
|
11
|
+
- **Email** — security@exceptd.com
|
|
8
12
|
|
|
9
|
-
|
|
13
|
+
**Do not open a public GitHub issue.** A public issue is the one channel that
|
|
14
|
+
tells everyone else before the fix exists.
|
|
10
15
|
|
|
11
|
-
Include:
|
|
12
|
-
- Description of the issue
|
|
13
|
-
- Steps to reproduce
|
|
14
|
-
- Impact assessment
|
|
15
|
-
- Whether you believe this is being actively exploited
|
|
16
|
+
Include what you have:
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
- What the issue is
|
|
19
|
+
- How to reproduce it
|
|
20
|
+
- What an attacker gets
|
|
21
|
+
- Whether you believe it is being exploited now
|
|
18
22
|
|
|
19
|
-
##
|
|
23
|
+
## What to expect
|
|
20
24
|
|
|
21
|
-
| Severity | First
|
|
25
|
+
| Severity | First response | Triage | Fix |
|
|
22
26
|
|---|---|---|---|
|
|
23
|
-
| Critical
|
|
24
|
-
| High
|
|
25
|
-
| Medium
|
|
26
|
-
| Low
|
|
27
|
-
|
|
28
|
-
## Supported Versions
|
|
29
|
-
|
|
30
|
-
Pre-1.0: Latest patch on the most recent minor receives data updates (CVE catalog, framework gap updates, new ATLAS TTPs). All versions receive critical accuracy corrections.
|
|
27
|
+
| Critical — data-integrity attack on the CVE catalog, RWEP score manipulation | 24h | 72h | 7d |
|
|
28
|
+
| High — a skill that produces incorrect remediation for a CISA KEV entry | 72h | 7d | 14d |
|
|
29
|
+
| Medium — an incorrect framework gap mapping or wrong control ID | 7d | 14d | 30d |
|
|
30
|
+
| Low — missing data, incomplete entries | 14d | 30d | next minor |
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
## Supported versions
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
Pre-1.0, the latest patch on the most recent minor receives data updates: CVE
|
|
35
|
+
catalog, framework gap changes, new ATLAS TTPs. Every version receives critical
|
|
36
|
+
accuracy corrections.
|
|
35
37
|
|
|
36
|
-
|
|
38
|
+
From 1.0, each major version receives data updates for 18 months.
|
|
37
39
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
**Accuracy of framework gap declarations.** If a gap is incorrectly declared as "closed" when it remains open, organizations may believe they are protected when they are not. Gap status changes require evidence (framework update reference + control text analysis) not assertions.
|
|
40
|
+
## Scope
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
This policy covers the repository itself — the skill files, the data catalogs,
|
|
43
|
+
and the library code. It does not cover applications built on top of them.
|
|
43
44
|
|
|
44
|
-
|
|
45
|
+
The repository has no npm runtime dependencies; `lib/` is self-contained and the
|
|
46
|
+
skills and catalogs are plain text and JSON. Loaded through an AI assistant, the
|
|
47
|
+
skills are instruction text: nothing here executes in your environment unless
|
|
48
|
+
your assistant chooses to run it.
|
|
45
49
|
|
|
46
|
-
|
|
50
|
+
Out of scope:
|
|
47
51
|
|
|
48
|
-
- Runtime security of applications that
|
|
49
|
-
-
|
|
50
|
-
|
|
52
|
+
- Runtime security of applications that consume these skills
|
|
53
|
+
- Accuracy of the upstream frameworks themselves — NIST, ISO and MITRE lag is
|
|
54
|
+
tracked here, not controlled here
|
|
55
|
+
- Physical access to the machine this runs on
|
|
51
56
|
|
|
52
|
-
##
|
|
57
|
+
## What the repository defends
|
|
53
58
|
|
|
54
|
-
CVE catalog
|
|
59
|
+
**The CVE catalog and its RWEP scores.** Tampered scores deprioritize
|
|
60
|
+
vulnerabilities that are genuinely critical. Every RWEP score is reproducible
|
|
61
|
+
from the inputs in `data/cve-catalog.json` and the formula in `lib/scoring.js`;
|
|
62
|
+
recompute it yourself when the decision is a large one.
|
|
55
63
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
64
|
+
**Framework gap declarations.** A gap recorded as closed while it remains open
|
|
65
|
+
tells an organization it is covered when it is not. Changing a gap's status
|
|
66
|
+
requires evidence — a framework update reference and the control text it turns
|
|
67
|
+
on — not an assertion.
|
|
60
68
|
|
|
61
|
-
|
|
69
|
+
**Exploit-availability freshness.** An exploit marked not-public when it is
|
|
70
|
+
public understates RWEP by a fifth of the scale. `data/exploit-availability.json`
|
|
71
|
+
is versioned and every entry carries `last_verified`.
|
|
62
72
|
|
|
63
|
-
|
|
73
|
+
**Skill instruction correctness.** A skill that recommends a patch which does not
|
|
74
|
+
exist for a given kernel version, or cites the wrong ATLAS technique, does direct
|
|
75
|
+
harm. Skills carry a `last_threat_review` date and are re-reviewed when the CVEs
|
|
76
|
+
or techniques they cite change.
|
|
64
77
|
|
|
65
|
-
|
|
78
|
+
## Using the data
|
|
66
79
|
|
|
67
|
-
|
|
80
|
+
Catalog entries and RWEP scores are analytical summaries for operational use, not
|
|
81
|
+
authoritative sources. Cross-reference before acting:
|
|
68
82
|
|
|
69
|
-
|
|
83
|
+
- CISA KEV — https://www.cisa.gov/known-exploited-vulnerabilities-catalog
|
|
84
|
+
- NVD — https://nvd.nist.gov/
|
|
85
|
+
- MITRE ATLAS — https://atlas.mitre.org/
|
|
86
|
+
- MITRE ATT&CK — https://attack.mitre.org/
|
|
70
87
|
|
|
71
|
-
|
|
88
|
+
Verify KEV status against CISA directly for critical decisions. RWEP is a
|
|
89
|
+
prioritization heuristic, not a compliance instrument.
|
|
72
90
|
|
|
73
|
-
|
|
91
|
+
Threat intelligence has a short shelf life. What this repository asserts reflects
|
|
92
|
+
the state of knowledge at each skill's `last_threat_review` date. Check the
|
|
93
|
+
primary source before a production decision rests on it.
|
package/data/_indexes/_meta.json
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema_version": "1.1.0",
|
|
3
|
-
"generated_at": "2026-08-
|
|
3
|
+
"generated_at": "2026-08-22T06:16:21.493Z",
|
|
4
4
|
"generator": "scripts/build-indexes.js",
|
|
5
5
|
"source_count": 64,
|
|
6
6
|
"source_hashes": {
|
|
7
|
-
"manifest.json": "
|
|
8
|
-
"README.md": "
|
|
7
|
+
"manifest.json": "0b5994038838da7f7685f50c81eb5dc9c552c3865617162bab778279ed9bacbe",
|
|
8
|
+
"README.md": "bc575c178c21e3d07f1491710e24b26cad3a3cee012c43641b6ea7e83468e64e",
|
|
9
9
|
"data/atlas-ttps.json": "a14089671efcb4f06dd0f82d688fe49276c1370e167e4483d76e9c0a40ef41eb",
|
|
10
|
-
"data/attack-techniques.json": "
|
|
11
|
-
"data/cve-catalog.json": "
|
|
12
|
-
"data/cwe-catalog.json": "
|
|
10
|
+
"data/attack-techniques.json": "cf192b45621ce697d3b86789db58c840312c1fc13601beb58df7c747b065d08b",
|
|
11
|
+
"data/cve-catalog.json": "8293de3334f8c134c26b13269126c62ed80fc88663a4e45d456beb031b8893e4",
|
|
12
|
+
"data/cwe-catalog.json": "7db3e297a7401c99e1bf9019e9b2eaf88e5cda97f6799e01667acab13362a746",
|
|
13
13
|
"data/d3fend-catalog.json": "9a4a356a1446d7db8be8b6684fa789802405a96cdaf769f06db4136bd07db6ac",
|
|
14
14
|
"data/dlp-controls.json": "791f6a46b19b0c0fa2f46630ac8b398afb7ec9c2f2019056828c8820fe255f19",
|
|
15
15
|
"data/exploit-availability.json": "7139702266a8d5ba8b235ab76518b8a84deaa31fdb912e81cb124121cf3e9930",
|
|
16
|
-
"data/framework-control-gaps.json": "
|
|
16
|
+
"data/framework-control-gaps.json": "79cd66ea9ca6eb1e63c6647d52a28a205747d64c4cb96e61fb2bb0c057023834",
|
|
17
17
|
"data/global-frameworks.json": "20b18a851b3ab82e57cd159b49476d69fe544f02523398b2015189ab81c7c3f8",
|
|
18
18
|
"data/rfc-references.json": "6e9017eca910ab7e4bee85ad7c23927fd6ec766f34be7fce49ebf020cec3381a",
|
|
19
|
-
"data/zeroday-lessons.json": "
|
|
19
|
+
"data/zeroday-lessons.json": "3ee0c1aa27701a0eda2479f0d10fb4f095d8d542152595a04b15373eddf69d1e",
|
|
20
20
|
"skills/kernel-lpe-triage/skill.md": "0f79c641cef6e5f4a942eb94f43c460562bf83dfb67ae112d146c39c6b320fb0",
|
|
21
21
|
"skills/ai-attack-surface/skill.md": "c97335e14cd34bd1cd3c9d2cbd397f33569a07292b2f2f7721483575eb4459f7",
|
|
22
22
|
"skills/mcp-agent-trust/skill.md": "6195c93a6cadb213051214742890fa2bf4e39bae377a654d4195f0c90bd8b896",
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
"dlp_refs": 0
|
|
102
102
|
},
|
|
103
103
|
"trigger_table_entries": 688,
|
|
104
|
-
"chains_cve_entries":
|
|
104
|
+
"chains_cve_entries": 1310,
|
|
105
105
|
"chains_cwe_entries": 236,
|
|
106
106
|
"jurisdictions_indexed": 34,
|
|
107
107
|
"handoff_dag_nodes": 51,
|
|
@@ -6,23 +6,23 @@
|
|
|
6
6
|
},
|
|
7
7
|
"events": [
|
|
8
8
|
{
|
|
9
|
-
"date": "2026-08-
|
|
9
|
+
"date": "2026-08-22",
|
|
10
10
|
"type": "catalog_update",
|
|
11
|
-
"artifact": "data/
|
|
12
|
-
"path": "data/
|
|
11
|
+
"artifact": "data/cve-catalog.json",
|
|
12
|
+
"path": "data/cve-catalog.json",
|
|
13
13
|
"schema_version": "1.0.0",
|
|
14
|
-
"entry_count":
|
|
14
|
+
"entry_count": 1323
|
|
15
15
|
},
|
|
16
16
|
{
|
|
17
|
-
"date": "2026-08-
|
|
17
|
+
"date": "2026-08-19",
|
|
18
18
|
"type": "catalog_update",
|
|
19
|
-
"artifact": "data/
|
|
20
|
-
"path": "data/
|
|
19
|
+
"artifact": "data/attack-techniques.json",
|
|
20
|
+
"path": "data/attack-techniques.json",
|
|
21
21
|
"schema_version": "1.0.0",
|
|
22
|
-
"entry_count":
|
|
22
|
+
"entry_count": 794
|
|
23
23
|
},
|
|
24
24
|
{
|
|
25
|
-
"date": "2026-08-
|
|
25
|
+
"date": "2026-08-19",
|
|
26
26
|
"type": "catalog_update",
|
|
27
27
|
"artifact": "data/cwe-catalog.json",
|
|
28
28
|
"path": "data/cwe-catalog.json",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"entry_count": 236
|
|
31
31
|
},
|
|
32
32
|
{
|
|
33
|
-
"date": "2026-08-
|
|
33
|
+
"date": "2026-08-19",
|
|
34
34
|
"type": "catalog_update",
|
|
35
35
|
"artifact": "data/framework-control-gaps.json",
|
|
36
36
|
"path": "data/framework-control-gaps.json",
|
|
@@ -38,12 +38,12 @@
|
|
|
38
38
|
"entry_count": 194
|
|
39
39
|
},
|
|
40
40
|
{
|
|
41
|
-
"date": "2026-08-
|
|
41
|
+
"date": "2026-08-19",
|
|
42
42
|
"type": "catalog_update",
|
|
43
43
|
"artifact": "data/zeroday-lessons.json",
|
|
44
44
|
"path": "data/zeroday-lessons.json",
|
|
45
45
|
"schema_version": "1.1.0",
|
|
46
|
-
"entry_count":
|
|
46
|
+
"entry_count": 1323
|
|
47
47
|
},
|
|
48
48
|
{
|
|
49
49
|
"date": "2026-08-08",
|