Skip to content

Instantly share code, notes, and snippets.

@hartfordfive
Last active April 12, 2023 13:07
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hartfordfive/b6408e0018c11bf17c6b7f710018357a to your computer and use it in GitHub Desktop.
Save hartfordfive/b6408e0018c11bf17c6b7f710018357a to your computer and use it in GitHub Desktop.
Git pre-commit hook to search for potentially sensitive data
# List of the patterns to search for
declare -a git_verification_patterns # Create an associative array
git_verification_patterns[0]="(\"|')?(AWS|aws|Aws)?_?(SECRET|secret|Secret)?_?(ACCESS|access|Access)?_?(KEY|key|Key)(\"|')?\s*(:|=>|=)\s*(\"|')?[A-Za-z0-9/\+=]{40}(\"|'|\s)?"
git_verification_patterns[1]="(\"|')?(AWS|aws|Aws)?_?(SECRET|secret|Secret)?_?(ACCESS|access|Access)?_?(KEY|key|Key)?_?(ID|id|Id)?(\"|')?\s*(:|=>|=)\s*(\"|')?[A-Za-z0-9/\+=]{20}(\"|'|\s)?"
git_verification_patterns[2]="(\s+|=|:)[a-z0-9]{64}(\s+|\|)" # DigitalOcean Personal Access Token
git_verification_patterns[3]='Authorization\s+"?Basic\s+[a-zA-Z0-9+/]+={0,2}'
git_verification_patterns[4]="BEGIN RSA PRIVATE KEY"
git_verification_patterns[5]="END RSA PRIVATE KEY"
# List of the pattern descriptions (in same order)
declare -a git_verification_patterns_desc
git_verification_patterns_desc[0]="AWS Secret Key, Github Personal Access Token"
git_verification_patterns_desc[1]="AWS Access Key ID"
git_verification_patterns_desc[2]="DigitalOcean Personal Access Token"
git_verification_patterns_desc[3]="Base64 Encoded HTTP Auth header"
git_verification_patterns_desc[4]="SSH Private Key File"
git_verification_patterns_desc[5]="SSH Private Key File"
# List of the white-list exceptions for the above patterns (in same order)
declare -a git_verification_patterns_whitelist
git_verification_patterns_whitelist[0]="(\s+|=)00000000000000000000(\s+|\|)"
git_verification_patterns_whitelist[1]="(\s+|=)0000000000000000000000000000000000000000(\s+|\|)"
git_verification_patterns_whitelist[2]="(\s+|=)0000000000000000000000000000000000000000000000000000000000000000(\s+|\|)"
git_verification_patterns_whitelist[3]='Authorization "Basic MDAwMDAwMDAwMDAwMDowMDAwMDAwMDAwMAo="' # 0000000000000:00000000000"
git_verification_patterns_whitelist[4]=""
git_verification_patterns_whitelist[5]=""
git_verification_patterns_ssh_key='^.{65}$'
#!/bin/sh
if git rev-parse --verify HEAD >/dev/null 2>&1
then
against=HEAD
else
# Initial commit: diff against an empty tree object
EMPTY_TREE=$(git hash-object -t tree /dev/null)
against=$EMPTY_TREE
fi
# Redirect output to stderr.
exec 1>&2
echo "======================================================="
echo "Running Verification for tokens, secret keys, etc..."
echo "======================================================="
echo ""
source ~/.git-verification-patterns
#FILES_MODIFIED=$(git diff --cached --name-only -z $against)
FILES_MODIFIED=$(git diff --cached --name-only)
NUM_FILES_CHECKED=0
NUM_FILES_OFFENCES=0
exec < /dev/tty
for F in $FILES_MODIFIED
do
for i in "${!git_verification_patterns[@]}"; do
MATCH=$(cat $F | egrep -i --line-number "${git_verification_patterns[$i]}")
if [ ! -z "$MATCH" ]; then
echo "\t FILE: $F"
echo "\tPATTERN: ${git_verification_patterns[$i]}"
echo "\t DESC: ${git_verification_patterns_desc[$i]}"
echo "\tLINE(S):"
for L in $MATCH; do
echo "\t\t$L"
done
while true; do
read -p "Commit file anyway? (y/N): " yn
case $yn in
[Yy] ) break;;
[Nn] ) NUM_FILES_OFFENCES=$((NUM_FILES_OFFENCES+1)); break;;
* ) echo "Answer y or n."; continue;;
esac
done
echo "\t---------------------------"
fi
done
# Now also do a verification pattern for an SSH private key file
MATCH=$(cat $F | egrep -i --line-number "${git_verification_patterns_ssh_key}")
NUM_SSH_PK_LINES_FOUND=$(cat $F | egrep -i --line-number ${git_verification_patterns_ssh_key} | wc -l | awk '{print $1}')
if (( $NUM_SSH_PK_LINES_FOUND >= 3 )); then
echo "\t FILE: $F"
echo "\tPATTERN: ${git_verification_patterns_ssh_key}"
echo "\t DESC: ${git_verification_patterns_desc[$i]}"
echo "\tLINE(S):"
for L in $MATCH; do
echo "\t\t$L"
done
while true; do
read -p "Commit file anyway? (y/N): " yn
case $yn in
[Yy] ) break;;
[Nn] ) NUM_FILES_OFFENCES=$((NUM_FILES_OFFENCES+1)); break;;
* ) echo "Answer y or n."; continue;;
esac
done
echo "\t---------------------------"
fi
NUM_FILES_CHECKED=$((NUM_FILES_CHECKED+1))
done
exec <&- # Release input
echo "======================= SUMMARY ======================="
echo " Files Checked: $NUM_FILES_CHECKED"
echo " Num File Offences: $NUM_FILES_OFFENCES"
if [ $NUM_FILES_OFFENCES -gt 0 ]; then
echo " Status: FAIL"
else
echo " Status: OK"
fi
echo "-------------------------------------------------------"
echo ""
# Exit code based on if > 0 offences found
if [ $NUM_FILES_OFFENCES -gt 0 ]; then
exit 1
else
exit 0
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment