@blamejs/exceptd-skills 0.12.13 → 0.12.15
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 +150 -0
- package/bin/exceptd.js +147 -9
- package/data/_indexes/_meta.json +45 -45
- package/data/_indexes/activity-feed.json +4 -4
- package/data/_indexes/catalog-summaries.json +29 -29
- package/data/_indexes/chains.json +3238 -3210
- package/data/_indexes/frequency.json +3 -0
- package/data/_indexes/jurisdiction-map.json +5 -3
- package/data/_indexes/section-offsets.json +712 -685
- package/data/_indexes/theater-fingerprints.json +1 -1
- package/data/_indexes/token-budget.json +355 -340
- package/data/atlas-ttps.json +144 -129
- package/data/attack-techniques.json +319 -76
- package/data/cve-catalog.json +515 -475
- package/data/cwe-catalog.json +1081 -759
- package/data/exploit-availability.json +63 -15
- package/data/framework-control-gaps.json +867 -843
- package/data/rfc-references.json +276 -276
- package/keys/EXPECTED_FINGERPRINT +1 -0
- package/lib/auto-discovery.js +21 -4
- package/lib/cross-ref-api.js +39 -6
- package/lib/cve-curation.js +18 -5
- package/lib/lint-skills.js +6 -1
- package/lib/playbook-runner.js +742 -78
- package/lib/refresh-external.js +40 -22
- package/lib/refresh-network.js +193 -17
- package/lib/scoring.js +20 -7
- package/lib/source-ghsa.js +219 -37
- package/lib/source-osv.js +381 -122
- package/lib/validate-catalog-meta.js +64 -9
- package/lib/validate-cve-catalog.js +56 -18
- package/lib/validate-indexes.js +88 -37
- package/lib/verify.js +72 -0
- package/manifest-snapshot.json +1 -1
- package/manifest-snapshot.sha256 +1 -0
- package/manifest.json +73 -73
- package/orchestrator/dispatcher.js +21 -1
- package/orchestrator/event-bus.js +52 -8
- package/orchestrator/index.js +279 -20
- package/orchestrator/pipeline.js +63 -2
- package/orchestrator/scanner.js +32 -10
- package/orchestrator/scheduler.js +150 -17
- package/package.json +3 -1
- package/sbom.cdx.json +7 -7
- package/scripts/check-manifest-snapshot.js +32 -0
- package/scripts/check-sbom-currency.js +65 -3
- package/scripts/check-test-coverage.js +142 -19
- package/scripts/predeploy.js +83 -39
- package/scripts/refresh-manifest-snapshot.js +55 -4
- package/scripts/validate-vendor-online.js +169 -0
- package/scripts/verify-shipped-tarball.js +106 -3
- package/skills/ai-attack-surface/skill.md +18 -10
- package/skills/ai-c2-detection/skill.md +7 -2
- package/skills/ai-risk-management/skill.md +5 -4
- package/skills/api-security/skill.md +3 -3
- package/skills/attack-surface-pentest/skill.md +5 -5
- package/skills/cloud-security/skill.md +1 -1
- package/skills/compliance-theater/skill.md +8 -8
- package/skills/container-runtime-security/skill.md +1 -1
- package/skills/dlp-gap-analysis/skill.md +5 -1
- package/skills/email-security-anti-phishing/skill.md +1 -1
- package/skills/exploit-scoring/skill.md +18 -18
- package/skills/framework-gap-analysis/skill.md +6 -6
- package/skills/global-grc/skill.md +3 -2
- package/skills/identity-assurance/skill.md +2 -2
- package/skills/incident-response-playbook/skill.md +4 -4
- package/skills/kernel-lpe-triage/skill.md +21 -2
- package/skills/mcp-agent-trust/skill.md +17 -10
- package/skills/mlops-security/skill.md +2 -1
- package/skills/ot-ics-security/skill.md +1 -1
- package/skills/policy-exception-gen/skill.md +3 -3
- package/skills/pqc-first/skill.md +1 -1
- package/skills/rag-pipeline-security/skill.md +7 -3
- package/skills/researcher/skill.md +20 -3
- package/skills/sector-energy/skill.md +1 -1
- package/skills/sector-federal-government/skill.md +1 -1
- package/skills/sector-financial/skill.md +3 -3
- package/skills/sector-healthcare/skill.md +2 -2
- package/skills/security-maturity-tiers/skill.md +7 -7
- package/skills/skill-update-loop/skill.md +19 -3
- package/skills/supply-chain-integrity/skill.md +1 -1
- package/skills/threat-model-currency/skill.md +11 -11
- package/skills/threat-modeling-methodology/skill.md +3 -3
- package/skills/webapp-security/skill.md +1 -1
- package/skills/zeroday-gap-learn/skill.md +51 -7
- package/vendor/blamejs/_PROVENANCE.json +4 -1
- package/vendor/blamejs/worker-pool.js +38 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
SHA256:JX04VjFprM7+3gHJdO0Wi4tTCf1RKI9Roza3XOzAe0Y=
|
package/lib/auto-discovery.js
CHANGED
|
@@ -184,10 +184,21 @@ function buildKevDraftEntry(kevEntry, nvdPayload, epssPayload) {
|
|
|
184
184
|
"https://www.cisa.gov/known-exploited-vulnerabilities-catalog",
|
|
185
185
|
kevEntry.notes ? String(kevEntry.notes) : null,
|
|
186
186
|
].filter(Boolean),
|
|
187
|
-
|
|
187
|
+
// v0.12.15 (audit M P1-B): schema requires source_verified to be a
|
|
188
|
+
// YYYY-MM-DD string OR null; the prior `false` boolean produced an
|
|
189
|
+
// entry that failed strict catalog validation. Use null to mean
|
|
190
|
+
// "not yet verified" — operators populate the date during curation.
|
|
191
|
+
source_verified: null,
|
|
188
192
|
last_updated: TODAY,
|
|
189
193
|
last_verified: TODAY,
|
|
190
|
-
|
|
194
|
+
// v0.12.15 (audit M P1-D): `_auto_imported` must be the boolean `true`
|
|
195
|
+
// for lib/validate-cve-catalog.js's draft-recognition check (strict
|
|
196
|
+
// `=== true` comparison). The prior object-shape was non-recognizable
|
|
197
|
+
// and the strict validator treated KEV-discovered drafts as
|
|
198
|
+
// hard-error entries instead of warning-tier drafts. The provenance
|
|
199
|
+
// metadata that used to be inline now lives in `_auto_imported_meta`.
|
|
200
|
+
_auto_imported: true,
|
|
201
|
+
_auto_imported_meta: {
|
|
191
202
|
source: "KEV discovery",
|
|
192
203
|
imported_at: TODAY,
|
|
193
204
|
curation_needed: [
|
|
@@ -476,14 +487,20 @@ async function discoverNewRfcs(ctx, opts = {}) {
|
|
|
476
487
|
skills_referencing: [],
|
|
477
488
|
errata_count: null,
|
|
478
489
|
last_verified: TODAY,
|
|
479
|
-
_auto_imported:
|
|
490
|
+
// v0.12.15 (audit M P1-D, P3-T): boolean `_auto_imported: true` for
|
|
491
|
+
// strict-validator recognition; provenance moved to sibling
|
|
492
|
+
// `_auto_imported_meta`. Errata-URL hint converted to a real template
|
|
493
|
+
// literal so the rfc number actually interpolates (the previous double-
|
|
494
|
+
// quoted string left `${number}` as literal text in operator output).
|
|
495
|
+
_auto_imported: true,
|
|
496
|
+
_auto_imported_meta: {
|
|
480
497
|
source: `RFC discovery (IETF ${wg} working group)`,
|
|
481
498
|
imported_at: TODAY,
|
|
482
499
|
curation_needed: [
|
|
483
500
|
"relevance — project-specific framing of how this RFC matters for mid-2026 threats",
|
|
484
501
|
"lag_notes — what gaps remain or where the RFC falls short",
|
|
485
502
|
"skills_referencing — list of skills that should cite this RFC",
|
|
486
|
-
|
|
503
|
+
`errata_count — populate from <rfc-editor.org/errata/rfc${number}>`,
|
|
487
504
|
],
|
|
488
505
|
},
|
|
489
506
|
};
|
package/lib/cross-ref-api.js
CHANGED
|
@@ -21,6 +21,15 @@ const INDEX_DIR = path.join(DATA_DIR, '_indexes');
|
|
|
21
21
|
|
|
22
22
|
const _cache = new Map();
|
|
23
23
|
|
|
24
|
+
// v0.12.14 (audit C-F7): catalog corruption no longer crashes the runner
|
|
25
|
+
// uncaught. A malformed JSON file in data/ used to produce a SyntaxError
|
|
26
|
+
// at require-time of any consumer (lib/playbook-runner.js), which threw
|
|
27
|
+
// out of the run() entrypoint without honoring AGENTS.md's "non-zero
|
|
28
|
+
// exit + {ok:false, error} to stderr" contract. Now: caught + degraded
|
|
29
|
+
// to an empty catalog with a recorded _loadError that downstream code
|
|
30
|
+
// can inspect.
|
|
31
|
+
const _loadErrors = [];
|
|
32
|
+
|
|
24
33
|
function loadCatalog(filename) {
|
|
25
34
|
if (_cache.has(filename)) return _cache.get(filename);
|
|
26
35
|
const full = path.join(DATA_DIR, filename);
|
|
@@ -28,9 +37,17 @@ function loadCatalog(filename) {
|
|
|
28
37
|
_cache.set(filename, {});
|
|
29
38
|
return {};
|
|
30
39
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
40
|
+
try {
|
|
41
|
+
const parsed = JSON.parse(fs.readFileSync(full, 'utf8'));
|
|
42
|
+
_cache.set(filename, parsed);
|
|
43
|
+
return parsed;
|
|
44
|
+
} catch (e) {
|
|
45
|
+
_loadErrors.push({ kind: 'catalog', file: filename, error: e.message });
|
|
46
|
+
const stub = {};
|
|
47
|
+
Object.defineProperty(stub, '_loadError', { value: e.message, enumerable: false });
|
|
48
|
+
_cache.set(filename, stub);
|
|
49
|
+
return stub;
|
|
50
|
+
}
|
|
34
51
|
}
|
|
35
52
|
|
|
36
53
|
function loadIndex(filename) {
|
|
@@ -40,9 +57,21 @@ function loadIndex(filename) {
|
|
|
40
57
|
_cache.set('idx:' + filename, {});
|
|
41
58
|
return {};
|
|
42
59
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
60
|
+
try {
|
|
61
|
+
const parsed = JSON.parse(fs.readFileSync(full, 'utf8'));
|
|
62
|
+
_cache.set('idx:' + filename, parsed);
|
|
63
|
+
return parsed;
|
|
64
|
+
} catch (e) {
|
|
65
|
+
_loadErrors.push({ kind: 'index', file: filename, error: e.message });
|
|
66
|
+
const stub = {};
|
|
67
|
+
Object.defineProperty(stub, '_loadError', { value: e.message, enumerable: false });
|
|
68
|
+
_cache.set('idx:' + filename, stub);
|
|
69
|
+
return stub;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function getLoadErrors() {
|
|
74
|
+
return _loadErrors.slice();
|
|
46
75
|
}
|
|
47
76
|
|
|
48
77
|
function entries(catalog) {
|
|
@@ -221,4 +250,8 @@ module.exports = {
|
|
|
221
250
|
// Lower-level access (engine uses these directly)
|
|
222
251
|
_loadCatalog: loadCatalog,
|
|
223
252
|
_loadIndex: loadIndex,
|
|
253
|
+
// v0.12.14: surface accumulated catalog/index load errors. Returns
|
|
254
|
+
// [{kind, file, error}, ...] for every catalog/index whose JSON
|
|
255
|
+
// parse failed. Empty array on a healthy install.
|
|
256
|
+
getLoadErrors,
|
|
224
257
|
};
|
package/lib/cve-curation.js
CHANGED
|
@@ -50,11 +50,18 @@ let _cveSchemaCache = null;
|
|
|
50
50
|
function loadCveEntrySchema() {
|
|
51
51
|
if (_cveSchemaCache) return _cveSchemaCache;
|
|
52
52
|
try {
|
|
53
|
+
// v0.12.15 (audit M P1-A): the prior version of this function looked for
|
|
54
|
+
// either `root.patternProperties["^CVE-\\d{4}-\\d+$"]` or an object
|
|
55
|
+
// `root.additionalProperties`. The actual schema at lib/schemas/cve-
|
|
56
|
+
// catalog.schema.json has NEITHER — its top level IS the entry shape
|
|
57
|
+
// (`{type:'object', required:[...], properties: {...}}`) because
|
|
58
|
+
// validate-cve-catalog.js iterates each CVE id key manually and runs
|
|
59
|
+
// the schema validator over each value. Result: loadCveEntrySchema()
|
|
60
|
+
// always returned null, the v0.12.12 codex P1 #1 fix (strict-schema
|
|
61
|
+
// gating of promotion) was silently disabled, and schema-violating
|
|
62
|
+
// entries promoted anyway. Use the root schema directly.
|
|
53
63
|
const root = JSON.parse(fs.readFileSync(CVE_SCHEMA_PATH, "utf8"));
|
|
54
|
-
|
|
55
|
-
(root.patternProperties && root.patternProperties["^CVE-\\d{4}-\\d+$"]) ||
|
|
56
|
-
(root.additionalProperties && typeof root.additionalProperties === "object" ? root.additionalProperties : null);
|
|
57
|
-
_cveSchemaCache = entrySchema || null;
|
|
64
|
+
_cveSchemaCache = root || null;
|
|
58
65
|
return _cveSchemaCache;
|
|
59
66
|
} catch {
|
|
60
67
|
return null;
|
|
@@ -264,7 +271,13 @@ function buildQuestionnaire(cveId, draft) {
|
|
|
264
271
|
// Pull candidate catalogs. Each is optional — missing catalogs are skipped
|
|
265
272
|
// gracefully. J7 makes these one-shot loads per process.
|
|
266
273
|
const atlas = loadJson("data/atlas-ttps.json");
|
|
267
|
-
|
|
274
|
+
// v0.12.15 (audit M P1-E): the catalog ships as data/attack-techniques.json
|
|
275
|
+
// (renamed from data/attack-ttps.json before the v0.12.12 release; the
|
|
276
|
+
// canonical file path is also what lib/validate-cve-catalog.js consumes).
|
|
277
|
+
// The prior `data/attack-ttps.json` lookup silently fell back to an empty
|
|
278
|
+
// object via loadJsonRaw's ENOENT handling, so the ATT&CK candidate
|
|
279
|
+
// questionnaire branch always returned zero proposals.
|
|
280
|
+
const attack = loadJson("data/attack-techniques.json");
|
|
268
281
|
const cwe = loadJson("data/cwe-catalog.json");
|
|
269
282
|
const frameworkGaps = loadJson("data/framework-control-gaps.json");
|
|
270
283
|
|
package/lib/lint-skills.js
CHANGED
|
@@ -635,8 +635,13 @@ function loadContext() {
|
|
|
635
635
|
*/
|
|
636
636
|
function findOrphanSkillFiles(manifestSkills) {
|
|
637
637
|
if (!fs.existsSync(SKILLS_DIR)) return [];
|
|
638
|
+
// F19 — manifest paths are stored as forward-slash strings by contract
|
|
639
|
+
// (lib/verify.js validateSkillPath() rejects backslashes). The previous
|
|
640
|
+
// path.sep split was a no-op on Linux and incorrect on Windows when
|
|
641
|
+
// mixed separators arrived through other ingest paths; the cleaner
|
|
642
|
+
// contract is to normalise the comparison key directly.
|
|
638
643
|
const referenced = new Set(
|
|
639
|
-
manifestSkills.map((s) => s.path
|
|
644
|
+
manifestSkills.map((s) => String(s.path).replace(/\\/g, '/')),
|
|
640
645
|
);
|
|
641
646
|
const orphans = [];
|
|
642
647
|
for (const entry of fs.readdirSync(SKILLS_DIR, { withFileTypes: true })) {
|