11#! /bin/bash
22# Socket Security Pre-push Hook
3- # Final security check before pushing to remote.
3+ # MANDATORY ENFORCEMENT LAYER - Cannot be bypassed with --no-verify.
4+ # Validates all commits being pushed for security issues and AI attribution.
45
56set -e
67
@@ -10,7 +11,7 @@ YELLOW='\033[1;33m'
1011GREEN=' \033[0;32m'
1112NC=' \033[0m'
1213
13- echo " ${GREEN} Running final security validation before push ...${NC} "
14+ echo " ${GREEN} Running mandatory pre-push validation...${NC} "
1415
1516# Allowed public API key (used in socket-lib).
1617ALLOWED_PUBLIC_KEY=" sktsec_t_--RAN5U4ivauy4w37-6aoKyYPDt5ZbaT5JBVMqiwKo_api"
@@ -19,6 +20,8 @@ ALLOWED_PUBLIC_KEY="sktsec_t_--RAN5U4ivauy4w37-6aoKyYPDt5ZbaT5JBVMqiwKo_api"
1920remote=" $1 "
2021url=" $2 "
2122
23+ TOTAL_ERRORS=0
24+
2225# Read stdin for refs being pushed.
2326while read local_ref local_sha remote_ref remote_sha; do
2427 # Get the range of commits being pushed.
@@ -30,59 +33,122 @@ while read local_ref local_sha remote_ref remote_sha; do
3033 range=" $remote_sha ..$local_sha "
3134 fi
3235
33- # Get all files changed in these commits.
34- CHANGED_FILES=$( git diff --name-only " $range " 2> /dev/null || echo " " )
35-
36- if [ -z " $CHANGED_FILES " ]; then
37- continue
38- fi
39-
4036 ERRORS=0
4137
42- # Check for sensitive files.
43- if echo " $CHANGED_FILES " | grep -qE ' ^\.env(\.local)?$' ; then
44- echo " ${RED} ✗ BLOCKED: Attempting to push .env file!${NC} "
45- echo " Files: $( echo " $CHANGED_FILES " | grep -E ' ^\.env(\.local)?$' ) "
46- ERRORS=$(( ERRORS + 1 ))
47- fi
38+ # ============================================================================
39+ # CHECK 1: Scan commit messages for AI attribution
40+ # ============================================================================
41+ echo " Checking commit messages for AI attribution..."
4842
49- # Check for .DS_Store.
50- if echo " $CHANGED_FILES " | grep -q ' \.DS_Store' ; then
51- echo " ${YELLOW} ⚠ WARNING: .DS_Store file in push${NC} "
52- echo " Files: $( echo " $CHANGED_FILES " | grep ' \.DS_Store' ) "
53- fi
43+ # Check each commit in the range for AI patterns.
44+ while IFS= read -r commit_sha; do
45+ full_msg=$( git log -1 --format=' %B' " $commit_sha " )
5446
55- # Sample files for API keys (only check files that exist).
56- for file in $CHANGED_FILES ; do
57- if [ -f " $file " ] && [ ! -d " $file " ]; then
58- # Skip test files.
59- if echo " $file " | grep -qE ' \.(test|spec)\.|/test/|/tests/|fixtures/|\.example$' ; then
60- continue
61- fi
62-
63- # Check for Socket API keys.
64- if grep -E ' sktsec_[a-zA-Z0-9_-]{40,}' " $file " 2> /dev/null | grep -v " $ALLOWED_PUBLIC_KEY " | grep -v ' your_api_key_here' | grep -v ' fake-token' | grep -v ' test-token' | grep -q . ; then
65- echo " ${RED} ✗ BLOCKED: Real API key detected in push!${NC} "
66- echo " File: $file "
67- echo " Line(s):"
68- 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
69- ERRORS=$(( ERRORS + 1 ))
47+ if echo " $full_msg " | grep -qiE " (Generated with|Co-Authored-By: Claude|Co-Authored-By: AI|🤖 Generated|AI generated|Claude Code|@anthropic|Assistant:|Generated by Claude|Machine generated)" ; then
48+ if [ $ERRORS -eq 0 ]; then
49+ echo " ${RED} ✗ BLOCKED: AI attribution found in commit messages!${NC} "
50+ echo " Commits with AI attribution:"
7051 fi
52+ echo " - $( git log -1 --oneline " $commit_sha " ) "
53+ ERRORS=$(( ERRORS + 1 ))
7154 fi
72- done
55+ done < <( git rev-list " $range " )
7356
7457 if [ $ERRORS -gt 0 ]; then
7558 echo " "
76- echo " ${RED} ✗ Push blocked by security validation! ${NC} "
77- echo " Remove sensitive data from your commits before pushing ."
59+ echo " These commits were likely created with --no-verify, bypassing the "
60+ echo " commit-msg hook that strips AI attribution ."
7861 echo " "
7962 echo " To fix:"
80- echo " 1. Remove sensitive data from files"
81- echo " 2. Amend or rebase your commits"
82- echo " 3. Push again"
83- exit 1
63+ echo " git rebase -i $remote_sha "
64+ echo " Mark commits as 'reword', remove AI attribution, save"
65+ echo " git push"
66+ fi
67+
68+ # ============================================================================
69+ # CHECK 2: File content security checks
70+ # ============================================================================
71+ echo " Checking files for security issues..."
72+
73+ # Get all files changed in these commits.
74+ CHANGED_FILES=$( git diff --name-only " $range " 2> /dev/null || echo " " )
75+
76+ if [ -n " $CHANGED_FILES " ]; then
77+ # Check for sensitive files.
78+ if echo " $CHANGED_FILES " | grep -qE ' ^\.env(\.local)?$' ; then
79+ echo " ${RED} ✗ BLOCKED: Attempting to push .env file!${NC} "
80+ echo " Files: $( echo " $CHANGED_FILES " | grep -E ' ^\.env(\.local)?$' ) "
81+ ERRORS=$(( ERRORS + 1 ))
82+ fi
83+
84+ # Check for .DS_Store.
85+ if echo " $CHANGED_FILES " | grep -q ' \.DS_Store' ; then
86+ echo " ${RED} ✗ BLOCKED: .DS_Store file in push!${NC} "
87+ echo " Files: $( echo " $CHANGED_FILES " | grep ' \.DS_Store' ) "
88+ ERRORS=$(( ERRORS + 1 ))
89+ fi
90+
91+ # Check for log files.
92+ if echo " $CHANGED_FILES " | grep -E ' \.log$' | grep -v ' test.*\.log' | grep -q . ; then
93+ echo " ${RED} ✗ BLOCKED: Log file in push!${NC} "
94+ echo " Files: $( echo " $CHANGED_FILES " | grep -E ' \.log$' | grep -v ' test.*\.log' ) "
95+ ERRORS=$(( ERRORS + 1 ))
96+ fi
97+
98+ # Check file contents for secrets.
99+ for file in $CHANGED_FILES ; do
100+ if [ -f " $file " ] && [ ! -d " $file " ]; then
101+ # Skip test files, example files, and hook scripts.
102+ if echo " $file " | grep -qE ' \.(test|spec)\.(m?[jt]s|tsx?)$|\.example$|/test/|/tests/|fixtures/|\.git-hooks/|\.husky/' ; then
103+ continue
104+ fi
105+
106+ # Check for hardcoded user paths.
107+ if grep -E ' (/Users/[^/\s]+/|/home/[^/\s]+/|C:\\Users\\[^\\]+\\)' " $file " 2> /dev/null | grep -q . ; then
108+ echo " ${RED} ✗ BLOCKED: Hardcoded personal path found in: $file ${NC} "
109+ grep -n -E ' (/Users/[^/\s]+/|/home/[^/\s]+/|C:\\Users\\[^\\]+\\)' " $file " | head -3
110+ ERRORS=$(( ERRORS + 1 ))
111+ fi
112+
113+ # Check for Socket API keys.
114+ 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
115+ echo " ${RED} ✗ BLOCKED: Real API key detected in: $file ${NC} "
116+ 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
117+ ERRORS=$(( ERRORS + 1 ))
118+ fi
119+
120+ # Check for AWS keys.
121+ if grep -iE ' (aws_access_key|aws_secret|AKIA[0-9A-Z]{16})' " $file " 2> /dev/null | grep -q . ; then
122+ echo " ${RED} ✗ BLOCKED: Potential AWS credentials found in: $file ${NC} "
123+ grep -n -iE ' (aws_access_key|aws_secret|AKIA[0-9A-Z]{16})' " $file " | head -3
124+ ERRORS=$(( ERRORS + 1 ))
125+ fi
126+
127+ # Check for GitHub tokens.
128+ if grep -E ' gh[ps]_[a-zA-Z0-9]{36}' " $file " 2> /dev/null | grep -q . ; then
129+ echo " ${RED} ✗ BLOCKED: Potential GitHub token found in: $file ${NC} "
130+ grep -n -E ' gh[ps]_[a-zA-Z0-9]{36}' " $file " | head -3
131+ ERRORS=$(( ERRORS + 1 ))
132+ fi
133+
134+ # Check for private keys.
135+ if grep -E ' -----BEGIN (RSA |EC |DSA )?PRIVATE KEY-----' " $file " 2> /dev/null | grep -q . ; then
136+ echo " ${RED} ✗ BLOCKED: Private key found in: $file ${NC} "
137+ ERRORS=$(( ERRORS + 1 ))
138+ fi
139+ fi
140+ done
84141 fi
142+
143+ TOTAL_ERRORS=$(( TOTAL_ERRORS + ERRORS))
85144done
86145
87- echo " ${GREEN} ✓ Security validation passed!${NC} "
146+ if [ $TOTAL_ERRORS -gt 0 ]; then
147+ echo " "
148+ echo " ${RED} ✗ Push blocked by mandatory validation!${NC} "
149+ echo " Fix the issues above before pushing."
150+ exit 1
151+ fi
152+
153+ echo " ${GREEN} ✓ All mandatory validation passed!${NC} "
88154exit 0
0 commit comments