- Location
- scripts/rule_gate.py:70
- Finding
- PreToolUse Guardrail Can Be Bypassed Through Uninspected Fields and Fail-Open Parsing<![CDATA[
## Vulnerability Details
**File Location**: `scripts/rule_gate.py:70-85, 109-115`; hook configuration in `SKILL.md:125-143`
**Vulnerability Type**: Incomplete security-control mediation and fail-open input handling
**Risk Level**: Medium
### Vulnerable Code
From `scripts/rule_gate.py:70-85`:
```python
def _compose_from_stdin() -> str:
"""Claude Code PreToolUse hook payload → one searchable description."""
raw = sys.stdin.read() if not sys.stdin.isatty() else ""
if not raw.strip():
return "" # no payload → pass (fail open)
try:
obj = json.loads(raw)
except Exception:
return "" # malformed payload → pass (fail open)
tool = str(obj.get("tool_name", ""))
ti = obj.get("tool_input") or {}
parts = [tool]
if isinstance(ti, dict):
for k in ("command", "description", "prompt", "text", "query", "path"):
v = ti.get(k)
if v:
parts.append(str(v))
return " ".join(parts)
```
From `scripts/rule_gate.py:109-115`:
```python
else:
desc = _compose_from_stdin()
if not desc:
return 0 # hook with no/empty payload → pass (fail open)
hits = check(desc, load_rules())
if hits:
print("⛔ action blocked — violates a rule you set:", file=sys.stderr)
```
The recommended configuration in `SKILL.md` applies the hook to every tool:
```json
{
"hooks": {
"PreToolUse": [
{
"matcher": "*",
"hooks": [
{ "type": "command",
"command": "python ~/.claude/skills/evermind/scripts/rule_gate.py" }
]
}
]
}
}
```
### Technical Analysis
Although the recommended hook matcher covers every tool, the gate only examines six top-level `tool_input` fields:
- `command`
- `description`
- `prompt`
- `text`
- `query`
- `path`
It ignores other security-relevant fields such as `content`, `file_path`, `new_string`, `old_string`, `url`, recipient fields, hea
...[truncated 1864 chars]
- Remediation
- <![CDATA[
## Remediation Suggestions
1. Parse and validate the complete documented hook schema rather than selecting a small fixed set of fields.
2. Recursively canonicalize all scalar values in `tool_input`, including nested objects and arrays, as a minimum compatibility measure.
3. Prefer tool-specific structured rules over keyword matching. For example:
- File-deletion rules should inspect canonical operation type and target paths.
- External-message rules should inspect tool name, destination, recipient, and payload.
- Write restrictions should inspect `file_path`, `content`, and edit fields.
4. Fail closed for protected tool classes when payload parsing fails, the schema is unsupported, or configured rules cannot be loaded.
5. Distinguish “no applicable rule” from “security control unavailable” and report the latter prominently.
6. Validate rule-file integrity and permissions; do not silently disable enforcement when it is corrupt.
7. Normalize command aliases, shell syntax, Unicode, case, paths, and encoded arguments before policy evaluation.
8. Add regression tests for Write, Edit, Bash, HTTP, messaging, nested payloads, malformed JSON, missing fields, and alternate representations of prohibited actions.
9. Document that keyword matching is advisory unless comprehensive structured enforcement is implemented.
]]>