#!/bin/bash function init-config(){ # White-listed Repos WHITELISTED_NAMES=( "zebar_neon_theme" ) ABSOLUTE_PATH="$(git rev-parse --show-toplevel)" REPO_NAME=$(basename "$ABSOLUTE_PATH") } function welcome-title(){ echo echo "┌──────────────────────────────────────┐" echo "│ │" echo "│ PRE-PUSH: Prevent leaks │" echo "│ critical/sentitive data │" echo "│ │" echo "└──────────────────────────────────────┘" echo } function is_whitelisted () { IS_ALLOWED=false for name in "${WHITELISTED_NAMES[@]}"; do if [ "$REPO_NAME" = "$name" ]; then IS_ALLOWED=true break fi done } function check-prerequisite(){ echo "############### CHECKING PREREQUISITES ###############" if ! command -v ggshield 2>&1 >/dev/null then echo -e "- ${RED}[FAILED ❌]${NC} ggshield command could not be found. Please install it first." exit 1 else echo -e "- ${GREEN}[CHECKED ✅]${NC} ggshield exists" fi if ! command -v trufflehog 2>&1 >/dev/null then echo -e "- ${RED}[FAILED ❌]${NC} trufflehog command could not be found. Please install it first." exit 1 else echo -e "- ${GREEN}[CHECKED ✅]${NC} trufflehog exists" fi if ! command -v jq 2>&1 >/dev/null then echo -e "- ${RED}[FAILED ❌]${NC} jq command could not be found. Please install it first." exit 1 else echo -e "- ${GREEN}[CHECKED ✅]${NC} jq exists" fi if ! command -v jtbl 2>&1 >/dev/null then echo -e "- ${RED}[FAILED ❌]${NC} jtbl command could not be found. Please install it first." exit 1 else echo -e "- ${GREEN}[CHECKED ✅]${NC} jtbl exists" fi } function run-ggshield(){ echo echo -e "############### ${CYAN}[GGSHIELD]${NC} - Secrets Directory Scanner ###############" echo "y" | ggshield secret scan path . --recursive --all-secrets --json > ggshield.json } function run-trufflehog(){ echo echo -e "############### ${CYAN}[TRUFFLEHOG]${NC} - Git Commit History Scanner ###############" echo trufflehog git file://. --branch HEAD --results=verified,unknown --no-update --json 2> /dev/null | jq -s '{"ScannerResults": .}' > trufflehog.json } function ggshield-summary(){ local generic_password_nums=$(jq -r '.entities_with_incidents[].incidents[]? | select(.type != null) | select(.type == "Generic Password") | .type' ggshield.json | wc -l) local other_secrets_nums=$(jq -r '.entities_with_incidents[].incidents[]? | select(.type != null) | select(.type != "Generic Password") | .type' ggshield.json | wc -l) GGSHIELD_INC_NUMS=${other_secrets_nums} if [[ ! -z "$generic_password_nums" ]]; then echo echo "+--------------------------------------------------------+" echo -e "+ ${YELLOW}[WARNING ⚠️]${NC} There are Generic Passwords detected" echo "+ NOTE: Chaos-based string may be not a sensitive data, used to" echo "+ obfuscate the real value or test data." echo "+--------------------------------------------------------+" echo fi if [[ ! -z "$other_secrets_nums" ]]; then echo echo "+--------------------------------------------------------+" echo -e "+ ${RED}[ALERTING 🚨]${NC} There are Sensitive Secrets detected" echo "+ NOTE: Leak keys may lead to critical security issues." echo "+ Please double check codebase & remove them if possible." echo "+--------------------------------------------------------+" echo fi echo echo -e "${YELLOW}PLEASE RE-VERIFY THE FOLLOWING FILES IN THE TABLES !!!${NC}" for filepath in $other_secrets_filepath do echo "- $filepath" done # GitGuardian Summary Table echo echo "Git Guardian Summary Table" echo jq -r ' if (.entities_with_incidents | length) > 0 then .entities_with_incidents[] | select(.total_incidents > 0) | { "Filename": .filename, "Total Incidents": (.total_incidents | tostring), "Total Occurrences": (.total_occurrences | tostring), "Types": ([.incidents[].type] | unique | join(", ")) } else { "Filename": "-", "Total Incidents": "-", "Total Occurrences": "-", "Types": "-" } end ' ggshield.json | jtbl } function trufflehog-summary(){ local num_trufflehog_incidents=$(jq '.ScannerResults | length' trufflehog.json) echo echo -e "${RED}[ALERTING 🚨]${NC} Found: $num_trufflehog_incidents incidents" echo "PLEASE REVIEW THE FOLLOWING COMMITS IN THE BELOW TABLE !!!" echo TRUFFLEHOG_INC_NUMS=$num_trufflehog_incidents # Trufflehog Summary Table echo echo "Trufflehog Summary Table" echo jq -r ' if (.ScannerResults | length) > 0 then .ScannerResults[] | { "Commit ID": .SourceMetadata.Data.Git.commit, "File Name": .SourceMetadata.Data.Git.file, "Author": .SourceMetadata.Data.Git.email, "Line": (.SourceMetadata.Data.Git.line | tostring), "Timestamp": .SourceMetadata.Data.Git.timestamp } else { "Commit ID": "-", "File Name": "-", "Author": "-", "Line": "-", "Timestamp": "-" } end ' trufflehog.json | jtbl } # MAIN function main(){ welcome-title source <(curl -sS https://raw.githubusercontent.com/khangtictoc/Productive-Workspace-Set-Up/refs/heads/main/linux/utility/library/bash/ansi_color.sh) init-ansicolor check-prerequisite is_whitelisted if [ "$IS_ALLOWED" != true ]; then run-ggshield ggshield-summary run-trufflehog trufflehog-summary if [ "$GGSHIELD_INC_NUMS" -gt 0 ] || [ "$TRUFFLEHOG_INC_NUMS" -gt 0 ]; then echo $GGSHIELD_INC_NUMS echo $TRUFFLEHOG_INC_NUMS # Prompt user echo "Are you sure you want to push to $REPO_NAME? (yes/no)" read answer < /dev/tty if [ "$answer" != "yes" ]; then echo echo -e "${PURPLE}Exiting...${NC}" echo -e "${PURPLE}Push aborted.${NC}" exit 1 echo fi echo ">>>>> CLEAN UP" rm ggshield.json trufflehog.json .cache_ggshield else echo ">>>>> CLEAN UP" rm ggshield.json trufflehog.json .cache_ggshield fi fi } main "$@"