Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,21 @@ if [ -z "$command" ]; then
exit 0
fi

# SECURITY: Check for command chaining/injection patterns FIRST
# These checks must run before the "safe command" allowlist to prevent bypasses
# like: echo $(rm -rf /), ls; malicious, pwd && evil, whoami | exfil
# Note: This is not exhaustive - production hooks should consider additional
# patterns like newlines (\n), null bytes (\x00), and shell-specific syntax
# shellcheck disable=SC2016 # Single quotes intentional - matching literal $( and ` characters
if [[ "$command" == *";"* ]] || [[ "$command" == *"|"* ]] ||
[[ "$command" == *'$('* ]] || [[ "$command" == *'`'* ]] ||
[[ "$command" == *"&&"* ]] || [[ "$command" == *"||"* ]]; then
echo '{"hookSpecificOutput": {"permissionDecision": "ask"}, "systemMessage": "Command chaining detected - requires review"}' >&2
exit 2
fi

# Check for obviously safe commands (quick approval)
# IMPORTANT: This check is only safe because chaining patterns are caught above
if [[ "$command" =~ ^(ls|pwd|echo|date|whoami)(\s|$) ]]; then
exit 0
fi
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ if [ -z "$file_path" ]; then
fi

# Check for path traversal
# NOTE: This basic check catches literal ".." but has limitations:
# - Does not detect URL-encoded traversal (%2e%2e)
# - Cannot detect symlink-based traversal where resolved path escapes bounds
# - Shell expansion could bypass in some contexts
# For production hooks, consider using:
# resolved=$(realpath -m "$file_path" 2>/dev/null || echo "$file_path")
# and comparing against an allowed directory prefix
if [[ "$file_path" == *".."* ]]; then
jq -n --arg path "$file_path" \
'{"hookSpecificOutput": {"permissionDecision": "deny"}, "systemMessage": "Path traversal detected in: \($path)"}' >&2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,13 @@ input=$(cat)
file_path=$(echo "$input" | jq -r '.tool_input.file_path')

# Check for path traversal
# NOTE: This basic check catches literal ".." but has limitations:
# - Does not detect URL-encoded traversal (%2e%2e)
# - Cannot detect symlink-based traversal where resolved path escapes bounds
# - Shell expansion could bypass in some contexts
# For production hooks, consider using:
# resolved=$(realpath -m "$file_path" 2>/dev/null || echo "$file_path")
# and comparing against an allowed directory prefix
if [[ "$file_path" == *".."* ]]; then
echo '{"decision": "deny", "reason": "Path traversal detected"}' >&2
exit 2
Expand Down
Loading