Where does the bug appear (feature/product)?
Cursor IDE
Describe the Bug
beforeShellExecution hook: malformed JSON response silently allows command instead of blocking
Where does the bug appear (feature/product)?
Cursor IDE - Hooks (beforeShellExecution)
Describe the Bug
When a beforeShellExecution hook returns malformed JSON (e.g. due to unescaped special characters in the response), Cursor silently allows the command to execute instead of blocking it. This bypasses "permission": "deny" hooks without any indication to the user.
This is a security concern: hooks intended to block dangerous commands (like git push, rm -rf, etc.) can be silently bypassed by commands that contain quotes, newlines, or other characters that break the hook’s JSON output.
Steps to Reproduce
- Create a
beforeShellExecutionhook that blocksgit push:
#!/bin/bash
input=$(cat)
command=$(echo "$input" | jq -r '.command // empty')
if echo "$command" | grep -qE 'git.*push'; then
cat << EOF
{
"continue": true,
"permission": "deny",
"user_message": "Git push blocked.",
"agent_message": "Blocked command: $command"
}
EOF
else
cat << EOF
{
"continue": true,
"permission": "allow"
}
EOF
fi
- Run a simple command – hook correctly blocks it:
git push
- Run a command with special characters – hook is bypassed, push succeeds:
git commit -m "$(cat <<'EOF'
some message
EOF
)" && git push
The $command variable contains quotes and newlines which, when interpolated into the heredoc JSON response, produce invalid JSON. Cursor fails to parse it and silently falls back to allowing the command.
Expected Behavior
When Cursor cannot parse a hook’s JSON response, it should default to deny (or at minimum ask), not allow. A beforeShellExecution hook exists specifically to gate command execution – failing open defeats its purpose.
Ideally Cursor should also surface a warning to the user that a hook returned invalid output.
Workaround
Use jq to build the JSON response instead of heredoc interpolation:
if echo "$command" | grep -qE 'git.*push'; then
jq -n \
--arg cmd "$command" \
'{
continue: true,
permission: "deny",
user_message: "Git push blocked.",
agent_message: ("Blocked command: " + $cmd)
}'
fi
Operating System
macOS (darwin 25.3.0)
Current Cursor Version
2.5.17
Steps to Reproduce
See above
Operating System
MacOS
Version Information
See above.
Does this stop you from using Cursor
Sometimes - I can sometimes use Cursor