@blamejs/exceptd-skills 0.15.49 → 0.15.51

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 CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.15.51 — 2026-05-30
4
+
5
+ Catalog: three new supply-chain entries. CVE-2022-23812 — the node-ipc "peacenotwar" protestware incident, where a trusted maintainer shipped a geo-targeted file-wiper in the package main module, so `--ignore-scripts` (the usual npm-supply-chain mitigation) does not stop it. TrapDoor — a cross-ecosystem (npm / PyPI / crates.io) credential-stealer campaign whose novel vector plants zero-width-Unicode instructions in `.cursorrules` / `CLAUDE.md` files to subvert AI coding assistants into discovering and exfiltrating local secrets. MOIKA — the catalog's first dependency-confusion entry: public packages published under squatted internal scopes at inflated versions, with a postinstall stager that exfiltrates the full process environment. Each carries its paired zero-day lesson and new framework-lag controls (main-module-payload detection, AI-assistant config-file poisoning detection, internal-scope→registry pinning).
6
+
7
+ Supply-chain playbook: a package-capability taxonomy (network / filesystem / shell / env / eval / install-script / telemetry / native-binary) as a CVE-independent screening lens. Two new detectors flag a dependency that gains a capability across a version bump, and a no-CVE package whose install-script combines with shell / network / env access (the credential-harvesting delivery shape) — both gated by false-positive checks for the build-tooling and native-addon class.
8
+
9
+ ## 0.15.50 — 2026-05-30
10
+
11
+ Hardening: `--operator` validation and the operator-text sanitizer now classify and strip Unicode threat codepoints — Trojan-Source bidirectional overrides (CVE-2021-42574), zero-width/invisible marks, C0 controls, and null — through a shared vendored codepoint-threat table, and the `--operator` rejection now names the specific codepoint family (for example "bidirectional-override codepoint") instead of a generic message. Unicode General Category C remains the reject/strip backstop, so the broader control / private-use / unassigned set is still refused.
12
+
13
+ Internal: a new codebase-pattern gate class, `bidi-codepoint-literal`, blocks raw bidi-override / zero-width / null codepoints embedded literally in source (invisible-in-review code reordering — the Trojan-Source class); source must escape them or route through the shared table.
14
+
3
15
  ## 0.15.49 — 2026-05-30
4
16
 
5
17
  Internal: a new predeploy gate, `scripts/check-codebase-patterns.js`, enforces code-shape bug classes that recurred across releases. It blocks a library-callable function that writes to stdout and then calls `process.exit()` (which truncates buffered output when the stream is piped — the class the v0.15.47 validate-cves fix addressed) and a stale or reason-less `// allow:` suppression marker, and warns on dynamic `RegExp` construction. The flagged `process.exit` sites across the catalog, playbook, package, and vendor validators were converted to the flush-safe `safeExit` form, and the dynamic-`RegExp` sites carry inline justification markers. A companion advisory, wired into the release `prepare` step, flags when the upstream pattern catalog grows a class exceptd hasn't triaged. No change to the shipped CLI surface, catalogs, or skills.
package/bin/exceptd.js CHANGED
@@ -63,6 +63,7 @@ const PKG_ROOT = path.resolve(__dirname, "..");
63
63
  const { EXIT_CODES, listExitCodes } = require(path.join(PKG_ROOT, "lib", "exit-codes.js"));
64
64
  const { validateIdComponent } = require(path.join(PKG_ROOT, "lib", "id-validation.js"));
65
65
  const { suggestFlag, flagsFor, VERB_FLAG_ALLOWLIST } = require(path.join(PKG_ROOT, "lib", "flag-suggest.js"));
66
+ const codepointClass = require(path.join(PKG_ROOT, "vendor", "blamejs", "codepoint-class.js"));
66
67
 
67
68
  // Union of every flag known to ANY verb. A flag that is valid somewhere but
68
69
  // not on the active verb (e.g. `--csaf-status` on `brief`) is cross-verb
@@ -1524,6 +1525,7 @@ function dispatchPlaybook(cmd, argv) {
1524
1525
  // Cc / Cf / Co / Cn — bidi overrides (U+202E "RTL OVERRIDE"),
1525
1526
  // zero-width joiners (U+200B-D), invisible format chars, private-use
1526
1527
  // codepoints, unassigned codepoints. An operator string like
1528
+ // allow:bidi-codepoint-literal — illustrative bidi-forgery example in the --operator reject-path doc comment
1527
1529
  // "alice‮evilbob" renders as "alicebobevila" in any UI that respects
1528
1530
  // bidi — a forgery surface where the attested name looks like Bob but the
1529
1531
  // bytes are Alice. Reject anything outside a positive allowlist of
@@ -1552,18 +1554,27 @@ function dispatchPlaybook(cmd, argv) {
1552
1554
  );
1553
1555
  }
1554
1556
  if (/\p{C}/u.test(normalized)) {
1555
- // Find the offending codepoint to surface a useful hint without
1556
- // round-tripping the raw bytes into the error body.
1557
+ // \p{C} (Cc/Cf/Cs/Co/Cn) is the reject gate it is strictly broader
1558
+ // than the named family regexes (bidi / C0-control / zero-width / null),
1559
+ // so it stays the backstop and catches the divergent remainder the
1560
+ // family tables miss (U+007F, U+0080-009F, private-use, unassigned).
1561
+ // The vendored codepoint tables only CLASSIFY the first offending
1562
+ // codepoint into a human family name for the hint.
1557
1563
  let offending = "";
1564
+ let family = "control / format / private-use / unassigned codepoint";
1558
1565
  for (const cp of normalized) {
1559
1566
  if (/\p{C}/u.test(cp)) {
1560
1567
  offending = "U+" + cp.codePointAt(0).toString(16).toUpperCase().padStart(4, "0");
1568
+ if (codepointClass.BIDI_RE.test(cp)) family = "bidirectional-override codepoint";
1569
+ else if (codepointClass.ZERO_WIDTH_RE.test(cp)) family = "zero-width / invisible codepoint";
1570
+ else if (cp === codepointClass.NULL_BYTE) family = "null byte";
1571
+ else if (codepointClass.C0_CTRL_RE.test(cp)) family = "C0 control character";
1561
1572
  break;
1562
1573
  }
1563
1574
  }
1564
1575
  return emitError(
1565
- `${cmd}: --operator contains a Unicode control / format / private-use / unassigned codepoint (${offending}). Bidi overrides (U+202E), zero-width joiners (U+200B–D), and format marks corrupt attestation rendering and enable name-forgery. Use printable identifiers only.`,
1566
- { verb: cmd, provided_length: args.operator.length, offending_codepoint: offending },
1576
+ `${cmd}: --operator contains a Unicode ${family} (${offending}). Bidi overrides, zero-width joiners, and format marks corrupt attestation rendering and enable name-forgery. Use printable identifiers only.`,
1577
+ { verb: cmd, provided_length: args.operator.length, offending_codepoint: offending, offending_family: family },
1567
1578
  pretty
1568
1579
  );
1569
1580
  }
@@ -1,21 +1,21 @@
1
1
  {
2
2
  "schema_version": "1.1.0",
3
- "generated_at": "2026-05-30T20:22:06.536Z",
3
+ "generated_at": "2026-05-31T03:23:30.384Z",
4
4
  "generator": "scripts/build-indexes.js",
5
5
  "source_count": 54,
6
6
  "source_hashes": {
7
- "manifest.json": "b2d79207d42e38d82a76c13b827623baa3e951b16cfbcc05250572070eb76aed",
7
+ "manifest.json": "26f77d56ab70b31946f08cd83c8cd5fc43e807c77955a0e9d4ae9450d32e29c9",
8
8
  "data/atlas-ttps.json": "878b4a08bb73c8d20396d85cf433a88f2bc5e7a8cbf7f6ab773ce7ede0a11251",
9
- "data/attack-techniques.json": "84fad74c8497cab922ed64b814752f54aa4620c2a938cb06642ff1510e1c5cb3",
10
- "data/cve-catalog.json": "7a5f4e31401505e53330cdc4b54b39f8a8b04459d6b9411676d291c583ae535f",
11
- "data/cwe-catalog.json": "0fd275c2a61754958d68cea03a92794a67cf1c1d4d609f81a5728334df013ee3",
9
+ "data/attack-techniques.json": "318bf8e9c5aee1d0a4a1dc37c4b211f2fbc937bf332a401a22483cc7d0547252",
10
+ "data/cve-catalog.json": "cb5e305b5488a2a02e177f10e913d22f602d6016109f152903093e9614e0b470",
11
+ "data/cwe-catalog.json": "b0e4d8f90b655b2b35b1e91c682ee66f2aa51ae5d38efb14f0e1b77f75ec5f7b",
12
12
  "data/d3fend-catalog.json": "9a54bccb9f24f84b32024216cc3f53819a053721ac8ab43c326859e68fc0ffaf",
13
13
  "data/dlp-controls.json": "d2406c482dddd30e49203879999dc4b3a7fd4d0494d6a61d86b91ee76415df19",
14
14
  "data/exploit-availability.json": "ec2656f0d9a893610e27b43eb6035fe9b18e057c9f6dfaac7e7d4959bbcbb795",
15
- "data/framework-control-gaps.json": "29e7b6aa841ddf2530ca5971bdb60d7a715684b2f6264141ad49f0de9a039d78",
15
+ "data/framework-control-gaps.json": "49cfbcaf0f27662db7e12340839c29f05d4ae31bc255dc9fa49ad1b4a45d0fa3",
16
16
  "data/global-frameworks.json": "9ba563a85f7f8d6c3c957de64945e20925a89d0ed6ea6fc561cf093811acf558",
17
17
  "data/rfc-references.json": "b21d03b948c41bc8a854e2f057948ecf844bd8c105848aeb141d1eadf8192c31",
18
- "data/zeroday-lessons.json": "acf9b2b001844dd2cacf1d29c7175d60db49b103847c9fddd242d2a98087541d",
18
+ "data/zeroday-lessons.json": "c7419ef8265a8385ab29e37e3f3237f120dd2fa448692f9dc1aa2fd79339fc76",
19
19
  "skills/kernel-lpe-triage/skill.md": "0f79c641cef6e5f4a942eb94f43c460562bf83dfb67ae112d146c39c6b320fb0",
20
20
  "skills/ai-attack-surface/skill.md": "2880499993e0e69e3897a9d02b5e83aa0462c86a4dd2c1988b9968e375704a1f",
21
21
  "skills/mcp-agent-trust/skill.md": "0752834acde0303d6d1e36be4b320eac3d34fde715bb8d71f3ad9e801d701482",
@@ -35,7 +35,7 @@
35
35
  "skills/attack-surface-pentest/skill.md": "8d1137c3270763f1c90a3fa8c1c19ab5dc769623c1a35d6a71859bdb8cca2a3e",
36
36
  "skills/fuzz-testing-strategy/skill.md": "07e2ee5f773a3f0e82bd21b8a7e8cf6d5b1a8bf3ac6f71602f16550561ade553",
37
37
  "skills/dlp-gap-analysis/skill.md": "89dedc6c062fa2afd2284e608f4a51effda819e9288fbf38ab16a7891ccd8a10",
38
- "skills/supply-chain-integrity/skill.md": "7c568ee9805f4c822c16c266348e35fa6f2d7a3c76135fa34b0cfa77f003a878",
38
+ "skills/supply-chain-integrity/skill.md": "23d15c234afedec011d9c3e588334132373a22d09ef33cd2d943e479c88fcb43",
39
39
  "skills/defensive-countermeasure-mapping/skill.md": "212c0c31dcdaf30dfc68d870e43015dc1420674563e47e6cfb7036067a1b8713",
40
40
  "skills/identity-assurance/skill.md": "86649aa573bde5b2ef2456a77d2fbfa9d1b623a4ef1326dd7a7ab384d0419307",
41
41
  "skills/ot-ics-security/skill.md": "583f758ace33e638ddbbc985eda1ffc711bb040ce24f528d502fc13e5f7bb46e",
@@ -72,13 +72,13 @@
72
72
  "dlp_refs": 0
73
73
  },
74
74
  "trigger_table_entries": 538,
75
- "chains_cve_entries": 416,
75
+ "chains_cve_entries": 417,
76
76
  "chains_cwe_entries": 173,
77
77
  "jurisdictions_indexed": 29,
78
78
  "handoff_dag_nodes": 42,
79
79
  "summary_cards": 42,
80
80
  "section_offsets_skills": 42,
81
- "token_budget_total_approx": 418426,
81
+ "token_budget_total_approx": 418794,
82
82
  "recipes": 8,
83
83
  "jurisdiction_clocks": 29,
84
84
  "did_ladders": 8,
@@ -11,7 +11,7 @@
11
11
  "artifact": "data/cve-catalog.json",
12
12
  "path": "data/cve-catalog.json",
13
13
  "schema_version": "1.0.0",
14
- "entry_count": 427
14
+ "entry_count": 430
15
15
  },
16
16
  {
17
17
  "date": "2026-05-27",
@@ -165,7 +165,7 @@
165
165
  "artifact": "data/zeroday-lessons.json",
166
166
  "path": "data/zeroday-lessons.json",
167
167
  "schema_version": "1.1.0",
168
- "entry_count": 427
168
+ "entry_count": 430
169
169
  },
170
170
  {
171
171
  "date": "2026-05-17",
@@ -62,13 +62,13 @@
62
62
  "rebuild_after_days": 365,
63
63
  "note": "Per-entry last_verified governs decay. Skills depending on this catalog must check entry freshness before high-stakes use."
64
64
  },
65
- "entry_count": 427,
65
+ "entry_count": 430,
66
66
  "sample_keys": [
67
+ "CVE-2022-23812",
68
+ "MAL-2026-TRAPDOOR-CROSS-ECOSYSTEM",
69
+ "MAL-2026-MOIKA-DEPCONFUSION",
67
70
  "CVE-2025-0282",
68
- "CVE-2025-22457",
69
- "CVE-2025-31324",
70
- "CVE-2025-31161",
71
- "CVE-2025-30066"
71
+ "CVE-2025-22457"
72
72
  ]
73
73
  },
74
74
  "cwe-catalog.json": {
@@ -238,7 +238,7 @@
238
238
  "rebuild_after_days": 365,
239
239
  "note": "Per-entry last_verified governs decay. Skills depending on this catalog must check entry freshness before high-stakes use."
240
240
  },
241
- "entry_count": 427,
241
+ "entry_count": 430,
242
242
  "sample_keys": [
243
243
  "CVE-2026-31431",
244
244
  "CVE-2025-53773",