-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathsecurity-scan.sh
More file actions
executable file
·147 lines (125 loc) · 3.87 KB
/
security-scan.sh
File metadata and controls
executable file
·147 lines (125 loc) · 3.87 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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/bin/sh
set -eu
repo_dir=${1:-.}
cd "$repo_dir"
found=0
excluded_dirs='(^|/)(\.git|vendor|node_modules|testdata|playwright-report|test-results|coverage|dist|build)/'
is_excluded_path() {
printf '%s\n' "$1" | grep -Eq "$excluded_dirs"
}
is_text_candidate() {
case "$1" in
*_test.go | *.png | *.jpg | *.jpeg | *.gif | *.ico | *.pdf | *.zip | *.tar | *.gz | *.tgz | *.woff | *.woff2 | *.ttf | *.eot | *.mp4 | *.mov | *.sqlite | *.db)
return 1
;;
esac
return 0
}
list_scan_files() {
git ls-files -co --exclude-standard 2>/dev/null | while IFS= read -r file; do
[ -n "$file" ] || continue
is_excluded_path "$file" && continue
is_text_candidate "$file" || continue
printf '%s\n' "$file"
done
}
scan_content_locations() {
pattern=$1
list_scan_files | while IFS= read -r file; do
grep -nEI "$pattern" "$file" 2>/dev/null | while IFS=: read -r line_no _; do
[ -n "$line_no" ] || continue
printf '%s:%s\n' "$file" "$line_no"
done
done | sort -u
}
is_config_candidate() {
case "$1" in
.env | .env.* | *.env | *.yaml | *.yml | *.json | *.toml | *.ini | *.conf | *.properties | *.tf | Dockerfile | docker-compose.yml | docker-compose.yaml)
return 0
;;
esac
return 1
}
scan_credential_locations() {
credential_name="(api[_-]?key|apikey|password|passwd|secret|client[_-]?secret|access[_-]?token|refresh[_-]?token|private[_-]?key|bearer|aws[_-]?access[_-]?key[_-]?id)"
source_pattern="$credential_name[[:space:]]*(:[[:space:]]+|=[[:space:]]*)['\"][A-Za-z0-9_./+=:@-]{8,}['\"]"
config_pattern="$credential_name[[:space:]]*(:[[:space:]]+|=[[:space:]]*)['\"]?[A-Za-z0-9_./+=:@-]{8,}"
list_scan_files | while IFS= read -r file; do
pattern=$source_pattern
if is_config_candidate "$file"; then
pattern=$config_pattern
fi
grep -nEI "$pattern" "$file" 2>/dev/null | while IFS=: read -r line_no _; do
[ -n "$line_no" ] || continue
printf '%s:%s\n' "$file" "$line_no"
done
done | sort -u
}
filter_allowed_logging_locations() {
while IFS= read -r location; do
file=${location%:*}
case "$file" in
internal/cli/auth/token.go | internal/cli/doctor.go | internal/cli/ai/config_main.go)
continue
;;
esac
printf '%s\n' "$location"
done
}
echo "=== Security Scan ==="
echo "Checking for hardcoded API keys..."
matches=$(scan_content_locations "nyk_v0[a-zA-Z0-9_]{20,}" || true)
if [ -n "$matches" ]; then
printf '%s\n' "$matches"
echo "WARNING: Possible API key found!"
found=1
else
echo "OK: No API keys found"
fi
echo ""
echo "Checking for credential patterns..."
matches=$(scan_credential_locations || true)
if [ -n "$matches" ]; then
printf '%s\n' "$matches"
echo "WARNING: Possible credentials found!"
found=1
else
echo "OK: No hardcoded credentials"
fi
echo ""
echo "Checking for full credential logging..."
logging_pattern="fmt\.(Print|Fprint|Sprint)[A-Za-z]*\([^)]*([A-Za-z0-9_]*[Aa]pi[Kk]ey|api_key)"
matches=$(scan_content_locations "$logging_pattern" | filter_allowed_logging_locations || true)
if [ -n "$matches" ]; then
printf '%s\n' "$matches"
echo "WARNING: Possible credential logging!"
found=1
else
echo "OK: No credential logging"
fi
echo ""
echo "Checking staged files..."
matches=$(git diff --cached --name-only 2>/dev/null | grep -E '(^|/)\.env([^/]*|$)|\.(key|pem|json)$|(^|/)secrets/' || true)
if [ -n "$matches" ]; then
printf '%s\n' "$matches"
echo "WARNING: Sensitive file staged!"
found=1
else
echo "OK: No sensitive files staged"
fi
echo ""
echo "Checking tracked files..."
matches=$(git ls-files 2>/dev/null | grep -Ei '(^|/)\.env([^/]*|$)|\.(key|pem)$|(^|/)secrets/|(^|/)[^/]*(secret|credential|credentials|service-account|private-key|private)[^/]*\.json$' || true)
if [ -n "$matches" ]; then
printf '%s\n' "$matches"
echo "WARNING: Sensitive tracked files found!"
found=1
else
echo "OK: No sensitive tracked files"
fi
echo ""
if [ "$found" -ne 0 ]; then
echo "Security scan failed"
exit 1
fi
echo "=== Security scan complete ==="