Install
$ agentstack add skill-carloscape-octorato-command-boundary-hook-matching ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ● Dynamic code execution Used
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Command-Boundary Hook Matching
Problem
A naive "gh pr merge" in command check fires on:
git commit -m "do not run gh pr merge 96 yet" # mention in commit message
echo "about to run gh pr merge" # echo
for pr in 95 96; do gh pr merge $pr; done # loop — fires twice, wrong context
None of these are the real invocation you want to intercept. The hook either over-fires (false positives trigger unnecessary blocks) or under-fires (quoted indirection evades detection).
Fix — Quote-Aware Sub-Command Splitter
Split the raw command string on unquoted shell separators only, then anchor the pattern at the start of each sub-command.
Step 1 — Join continuations
command = command.replace("\\\n", " ")
Step 2 — Quote-aware split on unquoted separators
Separators: ; && || | \n and grouping ( ) { }.
import re
def _split_subcmds(cmd: str) -> list[str]:
parts, buf, depth, in_sq, in_dq = [], [], 0, False, False
i = 0
while i [^\s]+\s+' # >file
r'|2>[^\s]+\s+' # 2>file
r')*'
)
def _strip_prefix(sub: str) -> str:
return _STRIP.sub('', sub)
Step 4 — Anchored pattern match
_PAT_MERGE = re.compile(r'^\s*gh\s+pr\s+merge\b')
def is_merge_command(command: str) -> tuple[bool, str | None]:
for sub in _split_subcmds(command):
clean = _strip_prefix(sub)
if _PAT_MERGE.match(clean):
# extract PR number
m = re.search(r'\bgh\s+pr\s+merge\s+(\d+)', clean)
return True, m.group(1) if m else None
return False, None
^\s*gh\s+pr\s+merge\b anchored at the sub-command start ensures it cannot match mid-string inside a quoted arg.
Fail-Open vs Fail-Closed
| Hook type | On parse error / ambiguity | |---|---| | Context-injection (informational) | FAIL-OPEN — skip, never block | | Gate/block (authorization) | FAIL-CLOSED — treat ambiguous = not authorized, block |
If shell indirection (bash -c "...", eval) makes the real command opaque, a fail-closed gate correctly blocks until a human grants the env-var approval (see [[agent-proof-approval-gate]]).
Residual Risk
Shell indirection still evades string-based detection:
bash -c "gh pr merge 96" # sub-command content is inside a string literal
$(echo gh pr merge 96) # command substitution
This is accepted. The string-matching layer identifies the action; the env-var layer authorizes it. The env channel is immune to indirection (see [[agent-proof-approval-gate]]).
When to Use
- Any PreToolUse hook that decides based on what a Bash command does.
- Gates on
git push --force,wrangler deploy,psql ... DROP, etc. - Logging/telemetry hooks that want to capture only real invocations.
Reference Implementation
~/.claude/scripts/qa-merge-gate.py — _split_subcmds + _strip_prefix + anchored _PAT_MERGE / _PAT_DELETE.
See also
- [[agent-proof-approval-gate]] — the authorization layer that complements this parsing layer
- [[dry-run-gate-pattern]] — preview-before-execute for destructive ops
- [[hook-profile-gating]] — profile-based hook activation
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: CarlosCaPe
- Source: CarlosCaPe/octorato
- License: MIT
- Homepage: https://www.dataqbs.com/octorato
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.