kodelyth-ecc 2.24.2 → 2.24.4

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
@@ -2,6 +2,125 @@
2
2
 
3
3
  All notable changes to Kodelyth ECC are documented here.
4
4
 
5
+ ## v2.24.4 — fix catastrophic backtracking in the prompt-injection guard (October 2026)
6
+
7
+ **Security fix.** The guard that scans untrusted text for prompt injection could
8
+ be hung indefinitely by the text it was scanning.
9
+
10
+ ### What was wrong
11
+
12
+ `override-prior-instructions` — the critical-severity pattern matching the single
13
+ most common injection phrase — was written as
14
+
15
+ \s+ (group)? \s* (group)? \s*
16
+
17
+ Three whitespace quantifiers with optional groups between them. With both groups
18
+ matching empty they sat adjacent, so a run of N spaces could be partitioned
19
+ between them in O(N^2) ways, and every partition was retried once the trailing
20
+ noun failed to match. On `"ignore" + N spaces + "x"`:
21
+
22
+ | N | time |
23
+ |---|---|
24
+ | 2,000 | 1.5s |
25
+ | 4,000 | 12.5s |
26
+ | 8,000 | never observed to finish |
27
+ | 19,000 | never observed to finish |
28
+
29
+ The guard caps input at 20,000 characters, so the cap does not help: the blow-up
30
+ begins around N=2,000, well inside it. Confirmed end to end through the hook's own
31
+ stdin path with the payload delivered in `tool_response`, which is where
32
+ untrusted file and network content arrives.
33
+
34
+ ### Why it is more than a hang
35
+
36
+ This hook runs on every tool call and is fail-open by design. In the default
37
+ `warn` mode the session stalls until the harness kills the hook, and no warning is
38
+ ever emitted. In `block` mode it is worse: a guard that never returns never exits
39
+ 2, so the critical pattern it exists to catch goes unblocked. The denial of
40
+ service doubles as a bypass of the control itself.
41
+
42
+ ### The fix
43
+
44
+ Each optional segment now carries its own leading `\s+` inside the group —
45
+ `(?:\s+X)?` rather than `\s+(X)?\s*` — so a whitespace run has exactly one valid
46
+ partition and there is nothing to backtrack through. The pattern now takes 4.8ms
47
+ at the full 20,000-character cap, and stays linear beyond it: 3.9ms on a million
48
+ spaces.
49
+
50
+ `system-prompt-leak` carried the same shape one group shallower, making it
51
+ quadratic rather than catastrophic (~590ms at 32,000 spaces, ~200ms at the cap).
52
+ Not a denial of service today, but the identical defect and one optional group
53
+ away from becoming one, so it is rewritten the same way. The other ten patterns
54
+ were swept with trigger words they actually match and are unaffected (4-5ms at
55
+ the cap).
56
+
57
+ ### Detection is unchanged
58
+
59
+ Verified rather than assumed. Both rewrites were checked against every phrase
60
+ their grammars generate — 1,140 for the first, 483 for the second — and agree
61
+ with the originals on all 1,623, with no phrase matched by one and not the other.
62
+
63
+ New tests cover the detections that must still fire, the ordinary text that must
64
+ not, and the timing. The timing test runs in a child process with a hard timeout
65
+ on purpose: a catastrophic regex is synchronous and CPU-bound, so node:test's own
66
+ timeout cannot interrupt it — against the old pattern the assertion was never
67
+ reached and the suite simply hung, which is a red build with no explanation. The
68
+ child turns the same regression into a named failure. Verified in both
69
+ directions: the old regex is killed at 15s with `ETIMEDOUT`, the new one finishes
70
+ in 59ms.
71
+
72
+ **668 tests across 43 files.**
73
+
74
+ ## v2.24.3 — remove decorative emoji from docs and catalog (October 2026)
75
+
76
+ Documentation only. No code, no behaviour change.
77
+
78
+ `rules/common/coding-style.md` bans decorative emoji and names the permitted
79
+ status indicators: `PASS`/`FAIL` or the text characters `✓` (U+2713) and `✗`
80
+ (U+2717). Three shipped files were not following it.
81
+
82
+ ### README comparison table
83
+
84
+ 39 emoji across 11 rows replaced with `✓` / `✗`.
85
+
86
+ This also fixed a polarity bug the emoji were hiding. In every row `❌` meant
87
+ "lacks this", where lacking it is the bad outcome. In the telemetry row it meant
88
+ "none", where none is the *good* outcome — so one glyph carried opposite meanings
89
+ in the same column, and ECC's `❌` sat beside a competitor's `❌` looking like
90
+ agreement while reading as praise and criticism. A mechanical swap would have
91
+ preserved that, so the row now states the value instead of a verdict:
92
+
93
+ | Telemetry | **None** | Varies | None | Varies |
94
+
95
+ ### Agent and command bodies
96
+
97
+ 10 decorative `❌` prefixes removed from bullet lists in
98
+ `agents/chaos-engineer.md` and `commands/devil-mode.md`. Dropped rather than
99
+ swapped for `✗`: both lists sit under headings that already state the negation —
100
+ "What You DON'T Do" and "When NOT to Use" — so every bullet was marked negative
101
+ twice.
102
+
103
+ These two files were also the upstream source of the emoji appearing on the
104
+ website. `ecc-web` syncs agent bodies into `src/lib/agents.json`, so the site
105
+ inherited them and could not be fixed there; a site-side edit would be
106
+ overwritten by the next sync.
107
+
108
+ ### Deliberately left alone
109
+
110
+ `rules/common/coding-style.md` still contains `✅ 🔍 🎯 🚀 ❌`. Every one sits in
111
+ the **Wrong** column of the table teaching which emoji not to use. They are
112
+ quoted specimens, not decoration — stripping them would empty the column and
113
+ leave the rule unable to demonstrate its own point. Future emoji sweeps should
114
+ skip that file.
115
+
116
+ The `← ↑ ↓ ⚙` in README.md are also kept. They sit inside terminal-output code
117
+ blocks and reproduce what the CLI actually prints — the gear comes from
118
+ `scripts/cli/menu.js:243`. Changing them would make the README stop matching the
119
+ tool.
120
+
121
+ Catalog parsing verified unchanged: 70 agents, 103 commands, frontmatter intact.
122
+ **665 tests across 43 files.**
123
+
5
124
  ## v2.24.2 — adversarial pass: path traversal in get_rule, unrecallable memories (October 2026)
6
125
 
7
126
  **Security fix.** Three defects found by attacking the memory store, MCP server
package/CLAUDE.md CHANGED
@@ -26,7 +26,7 @@ scripts/ → Node.js utilities: MCP server, dashboard, swarm, replay, router
26
26
  bundles/ → 3 power bundles (indie-hacker, red-team, enterprise)
27
27
  actions/ → GitHub Action (CI/CD integration for PR review)
28
28
  docs/ → Feature docs (arena.md, mcp.md, dashboard.md, swarm.md, replay.md, evolve.md, supply-chain.md)
29
- tests/ → 665 passing tests across 43 test files
29
+ tests/ → 668 passing tests across 43 test files
30
30
  ```
31
31
 
32
32
  ## Running Tests
package/README.md CHANGED
@@ -107,18 +107,18 @@ Most "AI agent kits" are folders of markdown files you have to remember the name
107
107
  | Feature | **Kodelyth ECC** | `agency-agents` | `awesome-claude-agents` | Generic prompt libs |
108
108
  |---|---|---|---|---|
109
109
  | Specialist agents | **70** | ~30 | ~20 | Varies |
110
- | Skills as separate layer | ✅ 196 | ❌ | ❌ | ❌ |
111
- | Slash commands | ✅ 103 | Some | Some | ❌ |
112
- | **Parallel multi-agent commands** | ✅ 8 (incl. `/devil-mode`) | ❌ | ❌ | ❌ |
113
- | **Intent routing (plain language → agent)** | ✅ 10-tier rule | ❌ | ❌ | ❌ |
114
- | **Local BM25 self-learning memory** | ✅ | ❌ | ❌ | ❌ |
115
- | **Compound learning from corrections** | ✅ `tasks/lessons.md` | ❌ | ❌ | ❌ |
116
- | **Adversarial / red-team agents** | ✅ 8 (devil-mode) | ❌ | ❌ | ❌ |
117
- | **Adversarial build/attack loop** | ✅ `/arena` — scored, verified, converges | ❌ | ❌ | ❌ |
118
- | Quality hooks | ✅ 44 | Some | ❌ | ❌ |
110
+ | Skills as separate layer | ✓ 196 | ✗ | ✗ | ✗ |
111
+ | Slash commands | ✓ 103 | Some | Some | ✗ |
112
+ | **Parallel multi-agent commands** | ✓ 8 (incl. `/devil-mode`) | ✗ | ✗ | ✗ |
113
+ | **Intent routing (plain language → agent)** | ✓ 10-tier rule | ✗ | ✗ | ✗ |
114
+ | **Local BM25 self-learning memory** | ✓ | ✗ | ✗ | ✗ |
115
+ | **Compound learning from corrections** | ✓ `tasks/lessons.md` | ✗ | ✗ | ✗ |
116
+ | **Adversarial / red-team agents** | ✓ 8 (devil-mode) | ✗ | ✗ | ✗ |
117
+ | **Adversarial build/attack loop** | ✓ `/arena` — scored, verified, converges | ✗ | ✗ | ✗ |
118
+ | Quality hooks | ✓ 44 | Some | ✗ | ✗ |
119
119
  | IDE platforms | **11** (Claude Code, Windsurf, Cursor, Codex, Antigravity, OpenCode, Cline, Roo Code, Aider, Kimi, Gemini CLI) | 1-2 | 1 | Varies |
120
- | Telemetry | ❌ none | Varies | ❌ | Varies |
121
- | Test coverage | ✅ 665 tests | ❌ | ❌ | ❌ |
120
+ | Telemetry | **None** | Varies | None | Varies |
121
+ | Test coverage | ✓ 668 tests | ✗ | ✗ | ✗ |
122
122
  | Distributed via | `npx`, curl, clone | Manual | Manual | Manual |
123
123
 
124
124
  ---
@@ -173,13 +173,13 @@ curl -X POST localhost:3000/admin/flags/new-feature --data '{"enabled":true}'
173
173
 
174
174
  ## What You DON'T Do
175
175
 
176
- - ❌ Run experiments in production without an SRE on call and explicit sign-off
177
- - ❌ Touch production data without an explicit backup and tested restore
178
- - ❌ Cause unbounded blast radius (kill all services, all regions, all replicas)
179
- - ❌ Run during high-traffic events (peak hours, launches, marketing campaigns)
180
- - ❌ Run without monitoring (chaos without observability is just sabotage)
181
- - ❌ Continue past abort criteria — if abort fires, abort, no exceptions
182
- - ❌ Inject faults into systems you don't own without coordination
176
+ - Run experiments in production without an SRE on call and explicit sign-off
177
+ - Touch production data without an explicit backup and tested restore
178
+ - Cause unbounded blast radius (kill all services, all regions, all replicas)
179
+ - Run during high-traffic events (peak hours, launches, marketing campaigns)
180
+ - Run without monitoring (chaos without observability is just sabotage)
181
+ - Continue past abort criteria — if abort fires, abort, no exceptions
182
+ - Inject faults into systems you don't own without coordination
183
183
 
184
184
  ## Output Format
185
185
 
@@ -83,9 +83,9 @@ PRIORITIZED ACTIONS:
83
83
 
84
84
  ## When NOT to Use
85
85
 
86
- - ❌ On code you don't have permission to audit (run only on your own repos / authorized targets)
87
- - ❌ On production systems for `chaos-engineer` flag — chaos requires `--staging` or signed-off blast radius
88
- - ❌ As a substitute for actual security review — this finds patterns; humans verify exploitability
86
+ - On code you don't have permission to audit (run only on your own repos / authorized targets)
87
+ - On production systems for `chaos-engineer` flag — chaos requires `--staging` or signed-off blast radius
88
+ - As a substitute for actual security review — this finds patterns; humans verify exploitability
89
89
 
90
90
  ## Execute Now
91
91
 
@@ -20,13 +20,28 @@ const PATTERNS = [
20
20
  {
21
21
  id: 'override-prior-instructions',
22
22
  severity: 'critical',
23
- regex: /\b(ignore|disregard|forget)\s+(all|any|the|your|my|all\s+(?:prior|previous|above|earlier))?\s*(prior|previous|above|earlier|prev|preceding)?\s*(instructions?|rules?|prompt|system\s*prompt|directives?)\b/i,
23
+ // Each optional segment carries its own leading \s+, so a run of whitespace
24
+ // has exactly ONE valid partition. The previous form was
25
+ // \s+ (group)? \s* (group)? \s*
26
+ // — three whitespace quantifiers with optional groups between them. When both
27
+ // groups matched empty they sat adjacent, so N spaces could be split between
28
+ // them in O(N^2) ways, and every split was retried once the final noun failed
29
+ // to match. Measured on "ignore" + N spaces + "x": 1.5s at N=2000, 12.5s at
30
+ // N=4000, over 40s at N=8000 — all well inside this hook's own 20000-char
31
+ // input cap, and reachable through tool_response, which carries untrusted
32
+ // file and network content. Verified equivalent across 1140 generated phrases.
33
+ regex: /\b(?:ignore|disregard|forget)(?:\s+(?:all|any|the|your|my))?(?:\s+(?:prior|previous|above|earlier|prev|preceding))?\s+(?:instructions?|rules?|system\s*prompt|prompt|directives?)\b/i,
24
34
  why: 'Classic instruction-override prompt injection.',
25
35
  },
26
36
  {
27
37
  id: 'system-prompt-leak',
28
38
  severity: 'critical',
29
- regex: /\b(reveal|print|show|repeat|output|dump|leak|expose)\s+(your|the|all|any)?\s*(system\s*prompt|hidden\s*prompt|initial\s*(prompt|instructions?)|original\s*(prompt|instructions?)|first\s*(message|prompt|instruction))/i,
39
+ // Same adjacent-quantifier shape as above, one group shallower, so quadratic
40
+ // rather than catastrophic: ~590ms at 32000 spaces, ~200ms at the 20000 cap.
41
+ // Not a denial of service today, but the identical defect, and it would become
42
+ // one the moment another optional group is added. Verified equivalent across
43
+ // 483 generated phrases.
44
+ regex: /\b(?:reveal|print|show|repeat|output|dump|leak|expose)(?:\s+(?:your|the|all|any))?\s+(?:system\s*prompt|hidden\s*prompt|initial\s*(?:prompt|instructions?)|original\s*(?:prompt|instructions?)|first\s*(?:message|prompt|instruction))/i,
30
45
  why: 'Explicit attempt to extract the system prompt.',
31
46
  },
32
47
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kodelyth-ecc",
3
- "version": "2.24.2",
3
+ "version": "2.24.4",
4
4
  "description": "Production-grade AI coding toolkit — 70 agents (incl. devil-mode adversarial crew), 196 skills, 103 commands, parallel multi-agent commands, semantic intent routing, self-learning memory, and a built-in MCP server (16 tools / 6 prompts / 377 resources) that bridges to Claude Desktop, LangGraph, AutoGen, CrewAI, and OpenAI Agents SDK. Works on macOS, Linux and Windows with Claude Code, Windsurf, Cursor, Codex, Antigravity, OpenCode, Cline, RooCode, Aider, Kimi, and Gemini CLI.",
5
5
  "author": "Kodelyth <github.com/sifxprime>",
6
6
  "license": "MIT",