-
Notifications
You must be signed in to change notification settings - Fork 529
Expand file tree
/
Copy pathfile-guard.sh
More file actions
executable file
·113 lines (94 loc) · 2.59 KB
/
file-guard.sh
File metadata and controls
executable file
·113 lines (94 loc) · 2.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#!/bin/bash
# .claude/hooks/file-guard.sh
# Event: PreToolUse
# Unified file protection with pattern matching and bash bypass detection
# Prevents Claude from reading/writing protected files
set -euo pipefail
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')
# Only check file operations
if [[ "$TOOL_NAME" != "Read" && "$TOOL_NAME" != "Write" && "$TOOL_NAME" != "Edit" ]]; then
exit 0
fi
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // ""')
# Load protection patterns from .agentignore or .aiignore
IGNORE_FILE=""
if [[ -f ".agentignore" ]]; then
IGNORE_FILE=".agentignore"
elif [[ -f ".aiignore" ]]; then
IGNORE_FILE=".aiignore"
fi
# Default critical patterns (if no ignore file)
CRITICAL_PATTERNS=(
".env"
".env.local"
".env.production"
"*.key"
"*.pem"
"*.p12"
"credentials.json"
"secrets.yaml"
"config/secrets/*"
".aws/credentials"
".ssh/id_*"
)
# Check against patterns
is_protected() {
local file="$1"
# Check ignore file patterns
if [[ -n "$IGNORE_FILE" ]]; then
while IFS= read -r pattern; do
# Skip comments and empty lines
[[ "$pattern" =~ ^#.*$ || -z "$pattern" ]] && continue
# Convert gitignore pattern to bash glob
if [[ "$file" == $pattern || "$file" =~ $pattern ]]; then
return 0
fi
done < "$IGNORE_FILE"
fi
# Check critical patterns
for pattern in "${CRITICAL_PATTERNS[@]}"; do
if [[ "$file" == $pattern || "$file" =~ $pattern ]]; then
return 0
fi
done
return 1
}
# Detect bash variable expansion bypass attempts
detect_bypass() {
local file="$1"
# Check for variable expansion patterns
if [[ "$file" =~ \$\{?[A-Za-z_][A-Za-z0-9_]*\}? ]]; then
return 0
fi
# Check for command substitution
if [[ "$file" =~ \$\( || "$file" =~ \` ]]; then
return 0
fi
return 1
}
# Validate file path
if [[ -z "$FILE_PATH" ]]; then
exit 0
fi
# Check for bypass attempts
if detect_bypass "$FILE_PATH"; then
cat << EOF
{
"block": true,
"systemMessage": "⛔ File access blocked: Variable expansion detected in path\n\nPath: $FILE_PATH\n\nThis looks like a bypass attempt. Use literal paths only."
}
EOF
exit 1
fi
# Check protection patterns
if is_protected "$FILE_PATH"; then
cat << EOF
{
"block": true,
"systemMessage": "⛔ File access blocked: Protected file\n\nPath: $FILE_PATH\n\nThis file is protected by .agentignore or security policy.\nTo access it, remove from ignore file and confirm manually."
}
EOF
exit 1
fi
exit 0