@blamejs/exceptd-skills 0.19.32 → 0.19.34
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 +22 -0
- package/bin/exceptd.js +896 -2824
- package/data/_indexes/_meta.json +8 -8
- package/data/_indexes/activity-feed.json +2 -2
- package/data/_indexes/catalog-summaries.json +7 -7
- package/data/_indexes/chains.json +60118 -0
- package/data/attack-techniques.json +267 -7
- package/data/cve-catalog.json +9991 -3
- package/data/cwe-catalog.json +109 -2
- package/data/framework-control-gaps.json +578 -3
- package/data/zeroday-lessons.json +8330 -1
- package/lib/auto-discovery.js +56 -286
- package/lib/canonical-eq.js +7 -40
- package/lib/citation-resolve.js +22 -70
- package/lib/collectors/ai-api.js +20 -54
- package/lib/collectors/cicd-pipeline-compromise.js +40 -108
- package/lib/collectors/citation-hygiene.js +72 -210
- package/lib/collectors/containers.js +41 -130
- package/lib/collectors/cred-stores.js +31 -115
- package/lib/collectors/crypto-codebase.js +55 -138
- package/lib/collectors/crypto.js +24 -54
- package/lib/collectors/hardening.js +20 -78
- package/lib/collectors/kernel.js +16 -46
- package/lib/collectors/library-author.js +57 -206
- package/lib/collectors/mcp.js +24 -70
- package/lib/collectors/runtime.js +24 -86
- package/lib/collectors/sbom.js +34 -106
- package/lib/collectors/scan-excludes.js +31 -138
- package/lib/collectors/secrets.js +62 -178
- package/lib/cross-ref-api.js +39 -123
- package/lib/currency-severity.js +8 -27
- package/lib/cve-batch.js +13 -21
- package/lib/cve-cli.js +13 -20
- package/lib/cve-curation.js +72 -239
- package/lib/cve-regression-watcher.js +29 -152
- package/lib/cvss.js +13 -54
- package/lib/doctor-bucketing.js +3 -19
- package/lib/exit-codes.js +10 -42
- package/lib/flag-suggest.js +7 -25
- package/lib/framework-gap.js +35 -114
- package/lib/gap-detectors.js +37 -159
- package/lib/id-validation.js +9 -30
- package/lib/job-queue.js +13 -36
- package/lib/lint-skills.js +64 -232
- package/lib/playbook-runner.js +693 -2095
- package/lib/prefetch.js +100 -376
- package/lib/refresh-external.js +199 -627
- package/lib/refresh-network.js +75 -307
- package/lib/rfc-cli.js +23 -68
- package/lib/scoring.js +77 -145
- package/lib/sign.js +43 -229
- package/lib/source-advisories.js +43 -194
- package/lib/source-ghsa.js +37 -120
- package/lib/source-osv.js +94 -266
- package/lib/ttp-mapper.js +14 -24
- package/lib/upstream-check-cli.js +10 -28
- package/lib/upstream-check.js +19 -44
- package/lib/validate-catalog-meta.js +17 -61
- package/lib/validate-cve-catalog.js +43 -119
- package/lib/validate-indexes.js +25 -76
- package/lib/validate-package.js +16 -62
- package/lib/validate-playbooks.js +69 -275
- package/lib/validate-vendor.js +16 -49
- package/lib/verify.js +56 -286
- package/lib/version-pins.js +5 -34
- package/lib/worker-pool.js +11 -30
- package/lib/xml-tokenizer.js +47 -152
- package/manifest.json +53 -53
- package/orchestrator/dispatcher.js +17 -68
- package/orchestrator/event-bus.js +11 -74
- package/orchestrator/index.js +138 -412
- package/orchestrator/pipeline.js +28 -85
- package/orchestrator/scanner.js +34 -138
- package/orchestrator/scheduler.js +20 -84
- package/package.json +2 -2
- package/sbom.cdx.json +253 -253
- package/scripts/audit-catalog-gaps.js +9 -62
- package/scripts/audit-cross-skill.js +5 -31
- package/scripts/audit-perf.js +6 -16
- package/scripts/backfill-theater-test.js +7 -64
- package/scripts/bootstrap.js +12 -44
- package/scripts/build-indexes.js +40 -154
- package/scripts/builders/activity-feed.js +4 -14
- package/scripts/builders/catalog-summaries.js +3 -10
- package/scripts/builders/currency.js +7 -20
- package/scripts/builders/cwe-chains.js +7 -30
- package/scripts/builders/did-ladders.js +6 -13
- package/scripts/builders/frequency.js +5 -19
- package/scripts/builders/jurisdiction-clocks.js +6 -25
- package/scripts/builders/recipes.js +6 -14
- package/scripts/builders/section-offsets.js +13 -51
- package/scripts/builders/stale-content.js +7 -28
- package/scripts/builders/summary-cards.js +8 -29
- package/scripts/builders/theater-fingerprints.js +12 -27
- package/scripts/builders/token-budget.js +4 -31
- package/scripts/check-agents-md-collectors.js +11 -54
- package/scripts/check-catalog-gap-budget.js +15 -32
- package/scripts/check-changelog-extract.js +18 -48
- package/scripts/check-codebase-patterns-currency.js +6 -22
- package/scripts/check-codebase-patterns.js +50 -143
- package/scripts/check-epss-consistency.js +9 -64
- package/scripts/check-framework-gap-coverage.js +13 -31
- package/scripts/check-manifest-snapshot.js +13 -73
- package/scripts/check-sbom-currency.js +44 -142
- package/scripts/check-test-count.js +15 -52
- package/scripts/check-test-coverage.js +66 -197
- package/scripts/check-test-subjects.js +21 -62
- package/scripts/check-ttp-references.js +14 -38
- package/scripts/check-ttp-upstream.js +8 -40
- package/scripts/check-version-bump.js +9 -61
- package/scripts/check-version-tags.js +20 -121
- package/scripts/predeploy.js +38 -184
- package/scripts/refresh-manifest-snapshot.js +16 -38
- package/scripts/refresh-mitre-atlas.js +3 -8
- package/scripts/refresh-mitre-attack.js +1 -8
- package/scripts/refresh-mitre-d3fend.js +3 -9
- package/scripts/refresh-mitre-ics-attack.js +3 -8
- package/scripts/refresh-reverse-refs.js +27 -94
- package/scripts/refresh-rfc-index.js +2 -10
- package/scripts/refresh-sbom.js +31 -161
- package/scripts/refresh-upstream-catalogs.js +40 -137
- package/scripts/release.js +69 -232
- package/scripts/run-e2e-scenarios.js +24 -71
- package/scripts/sync-manifest-metadata.js +10 -34
- package/scripts/sync-package-description.js +8 -17
- package/scripts/validate-vendor-online.js +13 -44
- package/scripts/verify-shipped-tarball.js +35 -140
|
@@ -1,31 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* full audit reminder. Emits events via event-bus.js when currency thresholds
|
|
8
|
-
* are breached.
|
|
9
|
-
*
|
|
10
|
-
* This is a simple interval-based scheduler. For production use, swap for a
|
|
11
|
-
* proper cron daemon or cloud scheduler without changing the task definitions.
|
|
12
|
-
*
|
|
13
|
-
* Bootstrap-fire policy. Long-cadence tasks (monthly, annual) are also
|
|
14
|
-
* evaluated on `start()` so a freshly-restarted watcher does not silently
|
|
15
|
-
* skip a due interval. Whether a task fires on bootstrap is gated by a
|
|
16
|
-
* persisted "last fired" timestamp store at
|
|
17
|
-
* `~/.exceptd/scheduler-last-fired.json` — the task fires only when the
|
|
18
|
-
* elapsed time since the persisted timestamp exceeds the interval. The
|
|
19
|
-
* weekly currency check always fires on bootstrap (legacy behavior).
|
|
20
|
-
*
|
|
21
|
-
* Implementation note — INT32 overflow guard. `setInterval` / `setTimeout`
|
|
22
|
-
* delay values are coerced to a signed 32-bit integer; any value above
|
|
23
|
-
* 2^31 - 1 ms (~24.8 days) is silently clamped to 1 ms by Node, which
|
|
24
|
-
* causes the handler to fire ~1000×/sec. The MONTHLY_CVE_VALIDATION and
|
|
25
|
-
* ANNUAL_AUDIT intervals both exceed that limit. `scheduleEvery` wraps the
|
|
26
|
-
* underlying timer with a short tick interval (capped at SAFE_MAX_MS) and
|
|
27
|
-
* compares wall-clock elapsed time against the requested interval, so any
|
|
28
|
-
* delay — including multi-year intervals — fires exactly when due.
|
|
4
|
+
* Interval-based coordinator for skill currency maintenance: weekly currency
|
|
5
|
+
* check, monthly CVE validation reminder, annual full audit. Breached currency
|
|
6
|
+
* thresholds are emitted on event-bus.js.
|
|
29
7
|
*/
|
|
30
8
|
|
|
31
9
|
const fs = require('fs');
|
|
@@ -36,7 +14,7 @@ const { bus, EVENT_TYPES } = require('./event-bus');
|
|
|
36
14
|
const { currencyCheck } = require('./pipeline');
|
|
37
15
|
|
|
38
16
|
const SAFE_MAX_MS = 2_147_483_647; // INT32 max — Node's setTimeout/setInterval ceiling.
|
|
39
|
-
const TICK_MS = Math.min(SAFE_MAX_MS, 24 * 60 * 60 * 1000);
|
|
17
|
+
const TICK_MS = Math.min(SAFE_MAX_MS, 24 * 60 * 60 * 1000);
|
|
40
18
|
|
|
41
19
|
const INTERVALS = {
|
|
42
20
|
WEEKLY_CURRENCY: 7 * 24 * 60 * 60 * 1000,
|
|
@@ -58,13 +36,7 @@ const LAST_FIRED_KEYS = {
|
|
|
58
36
|
let unschedulers = [];
|
|
59
37
|
let running = false;
|
|
60
38
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Resolve the path of the last-fired persistence file. Defaults to
|
|
65
|
-
* `~/.exceptd/scheduler-last-fired.json`. Honors EXCEPTD_HOME for the test
|
|
66
|
-
* suite so unit tests stay isolated from the maintainer's real home dir.
|
|
67
|
-
*/
|
|
39
|
+
/** EXCEPTD_HOME overrides the root so tests stay off the real home dir. */
|
|
68
40
|
function _lastFiredStorePath() {
|
|
69
41
|
const root = process.env.EXCEPTD_HOME || path.join(os.homedir(), '.exceptd');
|
|
70
42
|
return path.join(root, 'scheduler-last-fired.json');
|
|
@@ -85,9 +57,7 @@ function _saveLastFired(store) {
|
|
|
85
57
|
fs.mkdirSync(path.dirname(p), { recursive: true });
|
|
86
58
|
fs.writeFileSync(p, JSON.stringify(store, null, 2));
|
|
87
59
|
} catch (err) {
|
|
88
|
-
//
|
|
89
|
-
// can't tell whether the task fired; it does not break the running
|
|
90
|
-
// scheduler.
|
|
60
|
+
// Best-effort: a failed write only costs the next start its last-fired knowledge.
|
|
91
61
|
console.error('[scheduler] could not persist last-fired:', err.message);
|
|
92
62
|
}
|
|
93
63
|
}
|
|
@@ -107,24 +77,16 @@ function _shouldBootstrapFire(key, intervalMs) {
|
|
|
107
77
|
return (Date.now() - last) >= intervalMs;
|
|
108
78
|
}
|
|
109
79
|
|
|
110
|
-
// --- scheduling primitive ---
|
|
111
|
-
|
|
112
80
|
/**
|
|
113
|
-
* Schedule `handler`
|
|
114
|
-
*
|
|
81
|
+
* Schedule `handler` every `intervalMs` ms, returning an unschedule function.
|
|
82
|
+
* Throws RangeError unless intervalMs is a positive finite number.
|
|
115
83
|
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
84
|
+
* setInterval coerces its delay to signed 32-bit — above 2^31-1 ms it clamps to
|
|
85
|
+
* 1 ms and fires ~1000x/sec, which the monthly and annual intervals would hit.
|
|
86
|
+
* So the timer ticks at TICK_MS or less and compares wall-clock elapsed.
|
|
119
87
|
*/
|
|
120
88
|
function scheduleEvery(intervalMs, handler) {
|
|
121
|
-
//
|
|
122
|
-
// (upper bound) but never asserted intervalMs > 0. `scheduleEvery(0, fn)`
|
|
123
|
-
// would set a 0ms interval that fires ~10k times per second; negatives
|
|
124
|
-
// (-100) coerce the same way and NaN drives setInterval into a 1ms tick.
|
|
125
|
-
// All three exhaust the event loop. Refuse the call rather than silently
|
|
126
|
-
// floor — the scheduler is a long-lived primitive and a footgun here
|
|
127
|
-
// poisons every periodic task in the watcher.
|
|
89
|
+
// Zero, negative and NaN drive a ~1 ms tick, so refuse rather than floor.
|
|
128
90
|
if (!Number.isFinite(intervalMs) || intervalMs <= 0) {
|
|
129
91
|
throw new RangeError(`scheduleEvery: intervalMs must be a positive finite number, got ${intervalMs}`);
|
|
130
92
|
}
|
|
@@ -138,23 +100,15 @@ function scheduleEvery(intervalMs, handler) {
|
|
|
138
100
|
}
|
|
139
101
|
};
|
|
140
102
|
const id = setInterval(tick, Math.min(intervalMs, TICK_MS));
|
|
141
|
-
//
|
|
142
|
-
//
|
|
143
|
-
// loop alive (the event bus has no I/O of its own). Callers that don't
|
|
144
|
-
// want the timer to hold the loop open should call the returned
|
|
145
|
-
// unschedule function in their teardown path.
|
|
103
|
+
// No id.unref(): `watch` is long-running and relies on these timers to hold the
|
|
104
|
+
// event loop open — the event bus has no I/O of its own.
|
|
146
105
|
return () => clearInterval(id);
|
|
147
106
|
}
|
|
148
107
|
|
|
149
|
-
// --- public API ---
|
|
150
|
-
|
|
151
108
|
/**
|
|
152
|
-
* Start the scheduler
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
* interval (or absent), so a restarted watcher does not silently skip a due
|
|
156
|
-
* window. Bootstrap-fire happens inside the same try/catch the periodic
|
|
157
|
-
* wrapper uses so a single thrown task cannot crash the watcher.
|
|
109
|
+
* Start the scheduler: the weekly task runs immediately, then all three run on
|
|
110
|
+
* their intervals. Monthly and annual also bootstrap-fire when the persisted
|
|
111
|
+
* last-fired timestamp is absent or older than the interval.
|
|
158
112
|
*/
|
|
159
113
|
function start() {
|
|
160
114
|
if (running) return;
|
|
@@ -165,15 +119,12 @@ function start() {
|
|
|
165
119
|
catch (e) { console.error('[scheduler] ' + label + ' failed:', e); }
|
|
166
120
|
};
|
|
167
121
|
|
|
168
|
-
// Weekly always fires on bootstrap
|
|
122
|
+
// Weekly always fires on bootstrap — ungated, unlike the two below.
|
|
169
123
|
safeRun('weekly currency bootstrap', () => {
|
|
170
124
|
runWeeklyCurrencyCheck();
|
|
171
125
|
_markFired(LAST_FIRED_KEYS.WEEKLY_CURRENCY);
|
|
172
126
|
});
|
|
173
127
|
|
|
174
|
-
// Monthly + annual bootstrap-fire only when the persisted timestamp is
|
|
175
|
-
// older than the interval. This closes the "freshly-restarted watcher
|
|
176
|
-
// never fires the long-cadence task" gap.
|
|
177
128
|
if (_shouldBootstrapFire(LAST_FIRED_KEYS.MONTHLY_CVE_VALIDATION, INTERVALS.MONTHLY_CVE_VALIDATION)) {
|
|
178
129
|
safeRun('monthly CVE bootstrap', () => {
|
|
179
130
|
runMonthlyCveValidation();
|
|
@@ -203,9 +154,6 @@ function start() {
|
|
|
203
154
|
console.log('[scheduler] Started. Weekly currency check, monthly CVE validation, annual audit scheduled.');
|
|
204
155
|
}
|
|
205
156
|
|
|
206
|
-
/**
|
|
207
|
-
* Stop the scheduler and clear all timers.
|
|
208
|
-
*/
|
|
209
157
|
function stop() {
|
|
210
158
|
for (const off of unschedulers) {
|
|
211
159
|
try { off(); } catch { /* ignore */ }
|
|
@@ -215,30 +163,18 @@ function stop() {
|
|
|
215
163
|
console.log('[scheduler] Stopped.');
|
|
216
164
|
}
|
|
217
165
|
|
|
218
|
-
/**
|
|
219
|
-
* Run just the currency check immediately (for CLI use).
|
|
220
|
-
* @returns {object} Currency report
|
|
221
|
-
*/
|
|
222
166
|
function runCurrencyNow() {
|
|
223
167
|
return runWeeklyCurrencyCheck();
|
|
224
168
|
}
|
|
225
169
|
|
|
226
|
-
// --- task implementations ---
|
|
227
|
-
|
|
228
170
|
function runWeeklyCurrencyCheck() {
|
|
229
171
|
const timestamp = new Date().toISOString();
|
|
230
172
|
console.log(`[scheduler] Running weekly currency check — ${timestamp}`);
|
|
231
173
|
|
|
232
174
|
const { currency_report, action_required, critical_count } = currencyCheck();
|
|
233
175
|
|
|
234
|
-
//
|
|
235
|
-
//
|
|
236
|
-
// (`watch`, dashboards, alerting webhooks) from receiving an event storm
|
|
237
|
-
// when N skills are simultaneously stale — common after a long pause
|
|
238
|
-
// between runs or on first bootstrap. The aggregate payload carries
|
|
239
|
-
// critical_count + the full array of stale skills so consumers can still
|
|
240
|
-
// drill in. The legacy per-skill SKILL_CURRENCY_LOW signature is preserved
|
|
241
|
-
// for callers (and tests) that consume bus.skillCurrencyLow() directly.
|
|
176
|
+
// ONE aggregate event per run, not N per-skill: per-skill events storm every
|
|
177
|
+
// consumer. The payload carries the full stale list so a consumer can drill in.
|
|
242
178
|
const critical = currency_report.filter(s => s.currency_score < CURRENCY_THRESHOLDS.critical);
|
|
243
179
|
if (critical.length > 0) {
|
|
244
180
|
bus.emit(EVENT_TYPES.SKILL_CURRENCY_LOW_AGGREGATE, {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blamejs/exceptd-skills",
|
|
3
|
-
"version": "0.19.
|
|
4
|
-
"description": "AI security skills grounded in mid-2026 threat reality, not stale framework documentation. 51 skills, 11 catalogs (
|
|
3
|
+
"version": "0.19.34",
|
|
4
|
+
"description": "AI security skills grounded in mid-2026 threat reality, not stale framework documentation. 51 skills, 11 catalogs (1417 CVEs / 236 CWEs / 794 ATT&CK + ICS / 174 ATLAS / 468 D3FEND / 8889 RFCs), 35 jurisdictions, 10-class catalog gap detector + budget gate, real XML parser + canonical-form diff + content-pattern regression detection, Ed25519-signed.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai-security",
|
|
7
7
|
"ai-skills",
|