Skip to content

Commit e82d3f4

Browse files
committed
chore: add generic security checks to pre-commit hook
Replace hardcoded /Users/jdalton/ checks with generic path detection. Add security-checks.sh script that detects: - .DS_Store, log files, .env files - API keys and tokens (Socket, AWS, GitHub) - Private keys - Personal paths (generic /Users/*, /home/*, C:\Users\* detection) Skips checking hook directories (.git-hooks, .husky) to avoid false positives on regex patterns. Runs before lint and test hooks to catch issues early. Installed across all Socket repos via install-hooks.sh.
1 parent e314c7d commit e82d3f4

File tree

3 files changed

+146
-44
lines changed

3 files changed

+146
-44
lines changed

.git-hooks/pre-commit

Lines changed: 20 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,19 @@
11
#!/bin/bash
2-
# Socket Security Pre-commit Hook
3-
# Prevents committing sensitive data, personal paths, and junk files.
4-
# This hook is enforced and cannot be bypassed with --no-verify.
2+
# Socket Security Checks
3+
# Prevents committing sensitive data and common mistakes.
54

65
set -e
76

8-
# Detect if --no-verify was used.
9-
if [ -n "$GIT_AUTHOR_DATE" ]; then
10-
# Hook is running during a commit.
11-
if ps -ocommand= -p $PPID | grep -q '\--no-verify'; then
12-
echo "ERROR: Security hooks cannot be bypassed with --no-verify"
13-
echo "These checks are required to prevent accidental credential exposure."
14-
exit 1
15-
fi
16-
fi
17-
187
# Colors for output.
198
RED='\033[0;31m'
209
YELLOW='\033[1;33m'
2110
GREEN='\033[0;32m'
22-
NC='\033[0m' # No Color
11+
NC='\033[0m'
2312

2413
# Allowed public API key (used in socket-lib).
2514
ALLOWED_PUBLIC_KEY="sktsec_t_--RAN5U4ivauy4w37-6aoKyYPDt5ZbaT5JBVMqiwKo_api"
2615

27-
echo "${GREEN}Running Socket Security pre-commit checks...${NC}"
16+
echo "${GREEN}Running Socket Security checks...${NC}"
2817

2918
# Get list of staged files.
3019
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM)
@@ -41,7 +30,6 @@ echo "Checking for .DS_Store files..."
4130
if echo "$STAGED_FILES" | grep -q '\.DS_Store'; then
4231
echo "${RED}✗ ERROR: .DS_Store file detected!${NC}"
4332
echo "$STAGED_FILES" | grep '\.DS_Store'
44-
echo "Remove with: git reset HEAD \$(git diff --cached --name-only | grep .DS_Store)"
4533
ERRORS=$((ERRORS + 1))
4634
fi
4735

@@ -50,7 +38,6 @@ echo "Checking for log files..."
5038
if echo "$STAGED_FILES" | grep -E '\.log$' | grep -v 'test.*\.log'; then
5139
echo "${RED}✗ ERROR: Log file detected!${NC}"
5240
echo "$STAGED_FILES" | grep -E '\.log$' | grep -v 'test.*\.log'
53-
echo "Log files should not be committed."
5441
ERRORS=$((ERRORS + 1))
5542
fi
5643

@@ -63,41 +50,33 @@ if echo "$STAGED_FILES" | grep -E '^\.env(\.local)?$'; then
6350
ERRORS=$((ERRORS + 1))
6451
fi
6552

66-
# Check for personal paths in file contents.
53+
# Check for hardcoded user paths (generic detection).
6754
echo "Checking for hardcoded personal paths..."
6855
for file in $STAGED_FILES; do
6956
if [ -f "$file" ]; then
70-
if grep -l '/Users/jdalton/' "$file" 2>/dev/null | grep -v '.test.'; then
71-
echo "${RED}✗ ERROR: Hardcoded personal path found in: $file${NC}"
72-
grep -n '/Users/jdalton/' "$file" | head -3
73-
echo "Replace with relative paths or environment variables."
74-
ERRORS=$((ERRORS + 1))
75-
fi
76-
if grep -l '/home/jdalton/' "$file" 2>/dev/null; then
77-
echo "${RED}✗ ERROR: Hardcoded personal path found in: $file${NC}"
78-
grep -n '/home/jdalton/' "$file" | head -3
79-
ERRORS=$((ERRORS + 1))
57+
# Skip test files and hook scripts.
58+
if echo "$file" | grep -qE '\.(test|spec)\.|/test/|/tests/|fixtures/|\.git-hooks/|\.husky/'; then
59+
continue
8060
fi
81-
if grep -l 'C:\\Users\\jdalton\\' "$file" 2>/dev/null; then
61+
62+
# Check for common user path patterns.
63+
if grep -E '(/Users/[^/\s]+/|/home/[^/\s]+/|C:\\Users\\[^\\]+\\)' "$file" 2>/dev/null | grep -q .; then
8264
echo "${RED}✗ ERROR: Hardcoded personal path found in: $file${NC}"
83-
grep -n 'C:\\Users\\jdalton\\' "$file" | head -3
65+
grep -n -E '(/Users/[^/\s]+/|/home/[^/\s]+/|C:\\Users\\[^\\]+\\)' "$file" | head -3
66+
echo "Replace with relative paths or environment variables."
8467
ERRORS=$((ERRORS + 1))
8568
fi
8669
fi
8770
done
8871

89-
# Check for Socket API keys (except the allowed public key).
72+
# Check for Socket API keys.
9073
echo "Checking for API keys..."
9174
for file in $STAGED_FILES; do
9275
if [ -f "$file" ]; then
93-
# Look for Socket API keys.
94-
if grep -E 'sktsec_[a-zA-Z0-9_-]+' "$file" 2>/dev/null | grep -v "$ALLOWED_PUBLIC_KEY" | grep -v 'your_api_key_here' | grep -v 'SOCKET_SECURITY_API_KEY=' | grep -q .; then
76+
if grep -E 'sktsec_[a-zA-Z0-9_-]+' "$file" 2>/dev/null | grep -v "$ALLOWED_PUBLIC_KEY" | grep -v 'your_api_key_here' | grep -v 'SOCKET_SECURITY_API_KEY=' | grep -v 'fake-token' | grep -v 'test-token' | grep -q .; then
9577
echo "${YELLOW}⚠ WARNING: Potential API key found in: $file${NC}"
96-
grep -n 'sktsec_' "$file" | grep -v "$ALLOWED_PUBLIC_KEY" | grep -v 'your_api_key_here' | head -3
78+
grep -n 'sktsec_' "$file" | grep -v "$ALLOWED_PUBLIC_KEY" | grep -v 'your_api_key_here' | grep -v 'fake-token' | grep -v 'test-token' | head -3
9779
echo "If this is a real API key, DO NOT COMMIT IT."
98-
echo "Allowed public key: $ALLOWED_PUBLIC_KEY"
99-
# Not blocking on this, just warning.
100-
# ERRORS=$((ERRORS + 1))
10180
fi
10281
fi
10382
done
@@ -106,8 +85,8 @@ done
10685
echo "Checking for potential secrets..."
10786
for file in $STAGED_FILES; do
10887
if [ -f "$file" ]; then
109-
# Skip test files and example files.
110-
if echo "$file" | grep -qE '\.(test|spec)\.(m?[jt]s|tsx?)$|\.example$|/test/|/tests/|fixtures/'; then
88+
# Skip test files, example files, and hook scripts.
89+
if echo "$file" | grep -qE '\.(test|spec)\.(m?[jt]s|tsx?)$|\.example$|/test/|/tests/|fixtures/|\.git-hooks/|\.husky/'; then
11190
continue
11291
fi
11392

@@ -135,13 +114,10 @@ done
135114

136115
if [ $ERRORS -gt 0 ]; then
137116
echo ""
138-
echo "${RED}Pre-commit check failed with $ERRORS error(s).${NC}"
117+
echo "${RED}Security check failed with $ERRORS error(s).${NC}"
139118
echo "Fix the issues above and try again."
140-
echo ""
141-
echo "To bypass this check (NOT RECOMMENDED):"
142-
echo " git commit --no-verify"
143119
exit 1
144120
fi
145121

146-
echo "${GREEN}✓ All pre-commit checks passed!${NC}"
122+
echo "${GREEN}✓ All security checks passed!${NC}"
147123
exit 0

.husky/pre-commit

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# Run security checks first.
2+
.husky/security-checks.sh
3+
14
if [ -z "${DISABLE_PRECOMMIT_LINT}" ]; then
25
pnpm lint --staged
36
else

.husky/security-checks.sh

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
#!/bin/bash
2+
# Socket Security Checks
3+
# Prevents committing sensitive data and common mistakes.
4+
5+
set -e
6+
7+
# Colors for output.
8+
RED='\033[0;31m'
9+
YELLOW='\033[1;33m'
10+
GREEN='\033[0;32m'
11+
NC='\033[0m'
12+
13+
# Allowed public API key (used in socket-lib).
14+
ALLOWED_PUBLIC_KEY="sktsec_t_--RAN5U4ivauy4w37-6aoKyYPDt5ZbaT5JBVMqiwKo_api"
15+
16+
echo "${GREEN}Running Socket Security checks...${NC}"
17+
18+
# Get list of staged files.
19+
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM)
20+
21+
if [ -z "$STAGED_FILES" ]; then
22+
echo "${GREEN}✓ No files to check${NC}"
23+
exit 0
24+
fi
25+
26+
ERRORS=0
27+
28+
# Check for .DS_Store files.
29+
echo "Checking for .DS_Store files..."
30+
if echo "$STAGED_FILES" | grep -q '\.DS_Store'; then
31+
echo "${RED}✗ ERROR: .DS_Store file detected!${NC}"
32+
echo "$STAGED_FILES" | grep '\.DS_Store'
33+
ERRORS=$((ERRORS + 1))
34+
fi
35+
36+
# Check for log files.
37+
echo "Checking for log files..."
38+
if echo "$STAGED_FILES" | grep -E '\.log$' | grep -v 'test.*\.log'; then
39+
echo "${RED}✗ ERROR: Log file detected!${NC}"
40+
echo "$STAGED_FILES" | grep -E '\.log$' | grep -v 'test.*\.log'
41+
ERRORS=$((ERRORS + 1))
42+
fi
43+
44+
# Check for .env files.
45+
echo "Checking for .env files..."
46+
if echo "$STAGED_FILES" | grep -E '^\.env(\.local)?$'; then
47+
echo "${RED}✗ ERROR: .env or .env.local file detected!${NC}"
48+
echo "$STAGED_FILES" | grep -E '^\.env(\.local)?$'
49+
echo "These files should never be committed. Use .env.example instead."
50+
ERRORS=$((ERRORS + 1))
51+
fi
52+
53+
# Check for hardcoded user paths (generic detection).
54+
echo "Checking for hardcoded personal paths..."
55+
for file in $STAGED_FILES; do
56+
if [ -f "$file" ]; then
57+
# Skip test files and hook scripts.
58+
if echo "$file" | grep -qE '\.(test|spec)\.|/test/|/tests/|fixtures/|\.git-hooks/|\.husky/'; then
59+
continue
60+
fi
61+
62+
# Check for common user path patterns.
63+
if grep -E '(/Users/[^/\s]+/|/home/[^/\s]+/|C:\\Users\\[^\\]+\\)' "$file" 2>/dev/null | grep -q .; then
64+
echo "${RED}✗ ERROR: Hardcoded personal path found in: $file${NC}"
65+
grep -n -E '(/Users/[^/\s]+/|/home/[^/\s]+/|C:\\Users\\[^\\]+\\)' "$file" | head -3
66+
echo "Replace with relative paths or environment variables."
67+
ERRORS=$((ERRORS + 1))
68+
fi
69+
fi
70+
done
71+
72+
# Check for Socket API keys.
73+
echo "Checking for API keys..."
74+
for file in $STAGED_FILES; do
75+
if [ -f "$file" ]; then
76+
if grep -E 'sktsec_[a-zA-Z0-9_-]+' "$file" 2>/dev/null | grep -v "$ALLOWED_PUBLIC_KEY" | grep -v 'your_api_key_here' | grep -v 'SOCKET_SECURITY_API_KEY=' | grep -v 'fake-token' | grep -v 'test-token' | grep -q .; then
77+
echo "${YELLOW}⚠ WARNING: Potential API key found in: $file${NC}"
78+
grep -n 'sktsec_' "$file" | grep -v "$ALLOWED_PUBLIC_KEY" | grep -v 'your_api_key_here' | grep -v 'fake-token' | grep -v 'test-token' | head -3
79+
echo "If this is a real API key, DO NOT COMMIT IT."
80+
fi
81+
fi
82+
done
83+
84+
# Check for common secret patterns.
85+
echo "Checking for potential secrets..."
86+
for file in $STAGED_FILES; do
87+
if [ -f "$file" ]; then
88+
# Skip test files, example files, and hook scripts.
89+
if echo "$file" | grep -qE '\.(test|spec)\.(m?[jt]s|tsx?)$|\.example$|/test/|/tests/|fixtures/|\.git-hooks/|\.husky/'; then
90+
continue
91+
fi
92+
93+
# Check for AWS keys.
94+
if grep -iE '(aws_access_key|aws_secret|AKIA[0-9A-Z]{16})' "$file" 2>/dev/null | grep -q .; then
95+
echo "${RED}✗ ERROR: Potential AWS credentials found in: $file${NC}"
96+
grep -n -iE '(aws_access_key|aws_secret|AKIA[0-9A-Z]{16})' "$file" | head -3
97+
ERRORS=$((ERRORS + 1))
98+
fi
99+
100+
# Check for GitHub tokens.
101+
if grep -E 'gh[ps]_[a-zA-Z0-9]{36}' "$file" 2>/dev/null | grep -q .; then
102+
echo "${RED}✗ ERROR: Potential GitHub token found in: $file${NC}"
103+
grep -n -E 'gh[ps]_[a-zA-Z0-9]{36}' "$file" | head -3
104+
ERRORS=$((ERRORS + 1))
105+
fi
106+
107+
# Check for private keys.
108+
if grep -E '-----BEGIN (RSA |EC |DSA )?PRIVATE KEY-----' "$file" 2>/dev/null | grep -q .; then
109+
echo "${RED}✗ ERROR: Private key found in: $file${NC}"
110+
ERRORS=$((ERRORS + 1))
111+
fi
112+
fi
113+
done
114+
115+
if [ $ERRORS -gt 0 ]; then
116+
echo ""
117+
echo "${RED}✗ Security check failed with $ERRORS error(s).${NC}"
118+
echo "Fix the issues above and try again."
119+
exit 1
120+
fi
121+
122+
echo "${GREEN}✓ All security checks passed!${NC}"
123+
exit 0

0 commit comments

Comments
 (0)