@blamejs/exceptd-skills 0.12.40 → 0.13.0

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.
Files changed (97) hide show
  1. package/AGENTS.md +17 -0
  2. package/ARCHITECTURE.md +7 -4
  3. package/CHANGELOG.md +215 -248
  4. package/CONTEXT.md +2 -2
  5. package/README.md +2 -8
  6. package/agents/threat-researcher.md +2 -2
  7. package/bin/exceptd.js +179 -81
  8. package/data/_indexes/_meta.json +50 -50
  9. package/data/_indexes/activity-feed.json +1 -1
  10. package/data/_indexes/catalog-summaries.json +1 -1
  11. package/data/_indexes/chains.json +485 -13
  12. package/data/_indexes/frequency.json +4 -0
  13. package/data/_indexes/jurisdiction-map.json +15 -4
  14. package/data/_indexes/section-offsets.json +1224 -1224
  15. package/data/_indexes/token-budget.json +170 -170
  16. package/data/atlas-ttps.json +54 -11
  17. package/data/attack-techniques.json +113 -17
  18. package/data/cve-catalog.json +38 -52
  19. package/data/cwe-catalog.json +8 -2
  20. package/data/exploit-availability.json +1 -0
  21. package/data/framework-control-gaps.json +149 -6
  22. package/data/global-frameworks.json +1 -0
  23. package/data/playbooks/ai-api.json +5 -0
  24. package/data/playbooks/cicd-pipeline-compromise.json +970 -0
  25. package/data/playbooks/cloud-iam-incident.json +4 -1
  26. package/data/playbooks/cred-stores.json +10 -0
  27. package/data/playbooks/crypto-codebase.json +13 -0
  28. package/data/playbooks/framework.json +16 -0
  29. package/data/playbooks/hardening.json +4 -0
  30. package/data/playbooks/identity-sso-compromise.json +951 -0
  31. package/data/playbooks/idp-incident.json +3 -0
  32. package/data/playbooks/kernel.json +6 -0
  33. package/data/playbooks/llm-tool-use-exfil.json +963 -0
  34. package/data/playbooks/mcp.json +6 -0
  35. package/data/playbooks/runtime.json +4 -0
  36. package/data/playbooks/sbom.json +13 -0
  37. package/data/playbooks/secrets.json +6 -0
  38. package/data/playbooks/webhook-callback-abuse.json +916 -0
  39. package/data/zeroday-lessons.json +1 -0
  40. package/lib/cross-ref-api.js +33 -13
  41. package/lib/cve-curation.js +12 -1
  42. package/lib/exit-codes.js +29 -0
  43. package/lib/lint-skills.js +25 -3
  44. package/lib/playbook-runner.js +8 -4
  45. package/lib/refresh-external.js +10 -1
  46. package/lib/scoring.js +64 -1
  47. package/lib/sign.js +40 -7
  48. package/lib/verify.js +5 -5
  49. package/manifest.json +83 -83
  50. package/orchestrator/README.md +7 -7
  51. package/orchestrator/index.js +46 -25
  52. package/orchestrator/scheduler.js +2 -2
  53. package/package.json +1 -1
  54. package/sbom.cdx.json +135 -91
  55. package/scripts/check-test-coverage.js +6 -6
  56. package/scripts/predeploy.js +7 -13
  57. package/scripts/refresh-reverse-refs.js +107 -20
  58. package/scripts/refresh-sbom.js +21 -4
  59. package/skills/age-gates-child-safety/skill.md +1 -5
  60. package/skills/ai-attack-surface/skill.md +11 -4
  61. package/skills/ai-c2-detection/skill.md +11 -2
  62. package/skills/ai-risk-management/skill.md +4 -2
  63. package/skills/api-security/skill.md +7 -8
  64. package/skills/attack-surface-pentest/skill.md +2 -2
  65. package/skills/cloud-iam-incident/skill.md +1 -5
  66. package/skills/cloud-security/skill.md +0 -4
  67. package/skills/compliance-theater/skill.md +10 -2
  68. package/skills/container-runtime-security/skill.md +1 -3
  69. package/skills/dlp-gap-analysis/skill.md +3 -4
  70. package/skills/email-security-anti-phishing/skill.md +1 -8
  71. package/skills/exploit-scoring/skill.md +7 -2
  72. package/skills/framework-gap-analysis/skill.md +1 -1
  73. package/skills/fuzz-testing-strategy/skill.md +1 -2
  74. package/skills/global-grc/skill.md +3 -2
  75. package/skills/identity-assurance/skill.md +1 -3
  76. package/skills/idp-incident-response/skill.md +1 -4
  77. package/skills/incident-response-playbook/skill.md +1 -5
  78. package/skills/kernel-lpe-triage/skill.md +2 -2
  79. package/skills/mcp-agent-trust/skill.md +13 -3
  80. package/skills/mlops-security/skill.md +3 -4
  81. package/skills/ot-ics-security/skill.md +0 -3
  82. package/skills/policy-exception-gen/skill.md +11 -3
  83. package/skills/pqc-first/skill.md +4 -2
  84. package/skills/rag-pipeline-security/skill.md +2 -0
  85. package/skills/ransomware-response/skill.md +1 -5
  86. package/skills/researcher/skill.md +4 -3
  87. package/skills/sector-energy/skill.md +0 -4
  88. package/skills/sector-federal-government/skill.md +2 -3
  89. package/skills/sector-financial/skill.md +1 -4
  90. package/skills/sector-healthcare/skill.md +0 -5
  91. package/skills/sector-telecom/skill.md +0 -4
  92. package/skills/security-maturity-tiers/skill.md +1 -2
  93. package/skills/skill-update-loop/skill.md +4 -3
  94. package/skills/supply-chain-integrity/skill.md +4 -3
  95. package/skills/threat-model-currency/skill.md +1 -1
  96. package/skills/threat-modeling-methodology/skill.md +2 -1
  97. package/skills/webapp-security/skill.md +0 -5
@@ -27,6 +27,7 @@ const { dispatch, routeQuery, getSkillContext } = require('./dispatcher');
27
27
  const { currencyCheck, initPipeline } = require('./pipeline');
28
28
  const { bus, EVENT_TYPES } = require('./event-bus');
29
29
  const { start: startScheduler, stop: stopScheduler, runCurrencyNow } = require('./scheduler');
30
+ const { EXIT_CODES, safeExit } = require('../lib/exit-codes');
30
31
 
31
32
  const cmd = process.argv[2];
32
33
  const args = process.argv.slice(3);
@@ -145,7 +146,12 @@ Examples:
145
146
  exceptd framework-gap NIST-800-53 CVE-2026-31431
146
147
  exceptd framework-gap PCI-DSS-4.0 "prompt injection"
147
148
  exceptd framework-gap all CVE-2025-53773 --json`);
148
- process.exit(2);
149
+ // v0.13 exit-code class fix: usage error is GENERIC_FAILURE (1),
150
+ // not DETECTED_ESCALATE (2). Pre-v0.13 the orchestrator emitted
151
+ // exit 2 for usage errors, colliding with CI gates that branch on
152
+ // exit 2 to mean "verb ran + detected escalation-worthy finding".
153
+ safeExit(EXIT_CODES.GENERIC_FAILURE);
154
+ return;
149
155
  }
150
156
 
151
157
  const root = path.join(__dirname, '..');
@@ -155,7 +161,8 @@ Examples:
155
161
  cveCatalog = JSON.parse(fs.readFileSync(path.join(root, 'data', 'cve-catalog.json'), 'utf8'));
156
162
  } catch (err) {
157
163
  console.error(`[framework-gap] cannot read catalog: ${err.message}`);
158
- process.exit(2);
164
+ safeExit(EXIT_CODES.GENERIC_FAILURE);
165
+ return;
159
166
  }
160
167
 
161
168
  const requested = args[0].toLowerCase() === 'all'
@@ -292,20 +299,20 @@ async function runDispatch() {
292
299
 
293
300
  function runSkillContext(skillName) {
294
301
  if (!skillName) {
295
- // Cycle 20 A P2 (v0.12.40): operator-facing surface must reference
296
- // the canonical `exceptd skill <name>` form, not the orchestrator
297
- // path that's an implementation detail. CLAUDE.md global rule:
298
- // "no internal narrative in operator-facing artifacts."
299
302
  console.error('Usage: exceptd skill <skill-name>');
300
303
  console.error(' (Lists available skills: exceptd brief --all)');
301
- process.exit(1);
304
+ safeExit(EXIT_CODES.GENERIC_FAILURE);
305
+ return;
302
306
  }
303
307
 
304
308
  const context = getSkillContext(skillName);
305
309
  if (!context) {
306
- // Unified error shape across the CLI surface — see v0.10.3 bug #18.
307
- process.stderr.write(JSON.stringify({ ok: false, error: `Skill not found: ${skillName}`, verb: "skill", hint: "Run `exceptd brief --all` or check skills/ for available skill IDs." }) + "\n");
308
- process.exit(1);
310
+ // v0.13 envelope harmonization: ok:false bodies land on stdout
311
+ // alongside successful results so a single consumer can parse the
312
+ // verb's envelope without splitting across two streams.
313
+ process.stdout.write(JSON.stringify({ ok: false, verb: "skill", error: `Skill not found: ${skillName}`, hint: "Run `exceptd brief --all` or check skills/ for available skill IDs." }) + "\n");
314
+ safeExit(EXIT_CODES.GENERIC_FAILURE);
315
+ return;
309
316
  }
310
317
 
311
318
  console.log(`Skill: ${context.skill.name} v${context.skill.version}`);
@@ -332,7 +339,7 @@ function runPipeline(triggerType, payload) {
332
339
  console.log(` Agent: ${stage.agent_path}`);
333
340
  }
334
341
  console.log('\nTo run each stage, load the agent definition and follow its instructions:');
335
- console.log(' node orchestrator/index.js skill skill-update-loop');
342
+ console.log(' exceptd skill skill-update-loop');
336
343
  return run;
337
344
  }
338
345
 
@@ -368,12 +375,18 @@ async function runReport(format) {
368
375
  // string. Now: reject with structured JSON error matching other verbs.
369
376
  const VALID_REPORT_FORMATS = ['executive', 'technical', 'compliance', 'csaf'];
370
377
  if (!VALID_REPORT_FORMATS.includes(format)) {
371
- process.stderr.write(JSON.stringify({
378
+ // v0.13 envelope harmonization: ok:false body on stdout, exit 1
379
+ // (GENERIC_FAILURE) not 2 (DETECTED_ESCALATE). Pre-v0.13 the
380
+ // body went to stderr and exit was 2; both broke CI consumers
381
+ // that expected the dispatch-error vs verb-finding distinction.
382
+ process.stdout.write(JSON.stringify({
372
383
  ok: false,
373
- error: `report: format "${format}" not in accepted set ${JSON.stringify(VALID_REPORT_FORMATS)}.`,
374
384
  verb: 'report',
385
+ error: `report: format "${format}" not in accepted set ${JSON.stringify(VALID_REPORT_FORMATS)}.`,
386
+ accepted_formats: VALID_REPORT_FORMATS,
375
387
  }) + '\n');
376
- process.exit(2);
388
+ safeExit(EXIT_CODES.GENERIC_FAILURE);
389
+ return;
377
390
  }
378
391
 
379
392
  // v0.11.1 feature #55: `report csaf` emits a CSAF 2.0 envelope covering
@@ -693,7 +706,8 @@ async function runValidateCves(rawArgs = []) {
693
706
  catalog = JSON.parse(fs.readFileSync(catalogPath, 'utf8'));
694
707
  } catch (err) {
695
708
  console.error(`[validate-cves] cannot read ${catalogPath}: ${err.message}`);
696
- process.exit(2);
709
+ safeExit(EXIT_CODES.GENERIC_FAILURE);
710
+ return;
697
711
  }
698
712
 
699
713
  // --since <ISO|YYYY-MM-DD>: scope-limit validation to CVEs whose
@@ -863,7 +877,7 @@ async function runValidateCves(rawArgs = []) {
863
877
  }
864
878
  if (driftFound > 0) {
865
879
  console.log(`\n[validate-cves] DRIFT DETECTED on ${driftFound} CVE(s). Update data/cve-catalog.json and bump source_verified.`);
866
- if (!noFail) process.exit(1);
880
+ if (!noFail) { safeExit(EXIT_CODES.GENERIC_FAILURE); return; }
867
881
  } else {
868
882
  console.log('[validate-cves] No drift detected against reachable sources.');
869
883
  }
@@ -914,7 +928,8 @@ async function runValidateRfcs(rawArgs = []) {
914
928
  refs = JSON.parse(fs.readFileSync(refsPath, 'utf8'));
915
929
  } catch (err) {
916
930
  console.error(`[validate-rfcs] cannot read ${refsPath}: ${err.message}`);
917
- process.exit(2);
931
+ safeExit(EXIT_CODES.GENERIC_FAILURE);
932
+ return;
918
933
  }
919
934
 
920
935
  // --since <ISO|YYYY-MM-DD>: scope-limit (parity with validate-cves).
@@ -1043,7 +1058,7 @@ async function runValidateRfcs(rawArgs = []) {
1043
1058
  console.log();
1044
1059
  if (driftFound > 0) {
1045
1060
  console.log(`[validate-rfcs] DRIFT DETECTED on ${driftFound} entry(ies). Update data/rfc-references.json and bump last_verified.`);
1046
- if (!noFail) process.exit(1);
1061
+ if (!noFail) { safeExit(EXIT_CODES.GENERIC_FAILURE); return; }
1047
1062
  } else if (unreachable > 0) {
1048
1063
  console.log(`[validate-rfcs] ${unreachable} entry(ies) unreachable. Network/IETF Datatracker is intermittent — re-run later.`);
1049
1064
  } else if (!offline && validator) {
@@ -1078,7 +1093,8 @@ function runWatchlist(rawArgs = []) {
1078
1093
  manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
1079
1094
  } catch (err) {
1080
1095
  console.error(`[watchlist] cannot read ${manifestPath}: ${err.message}`);
1081
- process.exit(2);
1096
+ safeExit(EXIT_CODES.GENERIC_FAILURE);
1097
+ return;
1082
1098
  }
1083
1099
 
1084
1100
  // Exclude entries that are explicitly marked `status: "deprecated"` so
@@ -1125,7 +1141,12 @@ function runWatchlist(rawArgs = []) {
1125
1141
 
1126
1142
  const jsonOut = rawArgs.includes('--json');
1127
1143
  if (jsonOut) {
1144
+ // v0.13.0 envelope harmonization: top-level `ok: true` so every
1145
+ // verb's JSON body shares the contract whether emitted by
1146
+ // bin/exceptd.js emit() (which auto-defaults `ok`) or by the
1147
+ // orchestrator dispatch (which writes stdout directly).
1128
1148
  const out = {
1149
+ ok: true,
1129
1150
  generated_at: new Date().toISOString(),
1130
1151
  skills_scanned: skills.length,
1131
1152
  parse_errors: parseErrors,
@@ -1378,11 +1399,11 @@ Environment variables:
1378
1399
  EXCEPTD_SCAN_TARGETS Directories to scan for MCP configs
1379
1400
 
1380
1401
  Examples:
1381
- node orchestrator/index.js scan
1382
- node orchestrator/index.js skill kernel-lpe-triage
1383
- node orchestrator/index.js currency
1384
- node orchestrator/index.js report executive
1385
- node orchestrator/index.js watch
1402
+ exceptd scan
1403
+ exceptd skill kernel-lpe-triage
1404
+ exceptd currency
1405
+ exceptd report executive
1406
+ exceptd watch
1386
1407
  `);
1387
1408
  }
1388
1409
 
@@ -1394,7 +1415,7 @@ Examples:
1394
1415
  if (require.main === module) {
1395
1416
  main().catch(err => {
1396
1417
  console.error('[orchestrator] Fatal:', err.message);
1397
- process.exit(1);
1418
+ process.exitCode = 1;
1398
1419
  });
1399
1420
  }
1400
1421
 
@@ -277,12 +277,12 @@ function runMonthlyCveValidation() {
277
277
  console.log(`[scheduler] Monthly CVE validation reminder — ${timestamp}`);
278
278
  console.log('[scheduler] Action: Verify all data/cve-catalog.json entries against NVD and CISA KEV.');
279
279
  console.log('[scheduler] Action: Update last_verified dates in data/exploit-availability.json.');
280
- console.log('[scheduler] Run: node orchestrator/index.js validate-cves');
280
+ console.log('[scheduler] Run: exceptd validate-cves');
281
281
 
282
282
  return {
283
283
  task: 'monthly_cve_validation',
284
284
  timestamp,
285
- action: 'Run node orchestrator/index.js validate-cves to check all CVE entries'
285
+ action: 'Run `exceptd validate-cves` to check all CVE entries'
286
286
  };
287
287
  }
288
288
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blamejs/exceptd-skills",
3
- "version": "0.12.40",
3
+ "version": "0.13.0",
4
4
  "description": "AI security skills grounded in mid-2026 threat reality, not stale framework documentation. 42 skills, 10 catalogs, 34 jurisdictions, pre-computed indexes, Ed25519-signed.",
5
5
  "keywords": [
6
6
  "ai-security",