Preventing Sensitive Data Leaks: Implementing Husky and Git-Secrets in Your Git Workflow

Learn how to integrate Husky and git-secrets to prevent the accidental exposure of confidential information

Krunal Modi
Simform Engineering
7 min readJun 26, 2024

--

In software development, it’s crucial to ensure that sensitive information, such as AWS keys, Stripe secret keys, and other confidential data, never accidentally gets pushed to a repository. This blog post will guide you through using git-secrets and pre-commit hook to prevent such mishaps and keep your secrets safe.

You will learn how to integrate Husky and git-secrets to prevent the accidental exposure of passwords and other confidential information in your Git repository. These proactive measures significantly reduce the risk of leaking API keys and secrets within your codebase, ensuring better security practices and peace of mind.

What is Husky?

Husky is a widely-used npm package (with over 8 million downloads per week) that enables you to run custom scripts against your repository. It seamlessly integrates with any project that uses a package.json file, supporting all Git hooks such as pre-commit, commit-msg, and more.

What is git-secrets?

git-secrets, maintained by AWS Lab, is a powerful tool designed to prevent the accidental committing of passwords and other sensitive information to a Git repository. While it primarily focuses on reducing the risk of exposing AWS secrets, it also supports custom patterns, allowing you to safeguard any sensitive information within your codebase.

How to use husky and git-secrets?

I have detailed the entire process below:

Prerequisites

To get started, you need to have git-secrets installed on your local machine. Here's how you can install git-secrets on different operating systems:

*nix(Linux/macOS)

  1. Clone the git-secrets repository.
git clone https://github.com/awslabs/git-secrets.git
cd git-secrets

2. Use the provided Makefile to install git-secrets.

make install

Ensure that git-secrets is placed somewhere in your PATH so that it is picked up by Git when running Git commands.

Windows

  1. Download or clone the git-secrets repository.
  2. Run the provided PowerShell script to install:
PS > ./install.ps1

This script will copy the necessary files to the installation directory (default is %USERPROFILE%/.git-secrets) and add this directory to your user PATH.

Homebrew (for macOS users)

If you’re using macOS, you can easily install git-secrets using Homebrew:

brew install git-secrets

Setting up git-secrets in your repository

Once you have git-secrets installed, you need to set it up for each repository you wish to protect. This involves installing the git hooks and registering any patterns you want to check for.

  1. Navigate to your repository:
cd /path/to/my/repo

2. Install git-secrets hooks:

git secrets --install

3. Register AWS secret patterns:

git secrets --register-aws

Integrating with Husky

By integrating git-secrets with Husky, you can ensure that your repository is scanned for secrets on each commit.

  1. Install Husky:
npm install husky --save-dev

2. Enable Husky in your project:

npx husky init

It will set up Husky, modify your package.json, and create sample files for every git hook, which you can modify.

Look at the ./.husky/pre-commit hook file:

#!/bin/sh
. "$(dirname "$0")/_/husky.sh"


npm test

To prevent committing passwords and other sensitive information to a Git repository, we need to configure Husky with a pre-commit hook.

  • The pre-commit hook is run first before you even type in a commit message. It’s used to inspect the snapshot that’s about to be committed, to see if you’ve forgotten something, to make sure tests run, or to examine whatever you need to inspect in the code. Exiting non-zero from this hook aborts the commit.

We will update the .husky/pre-commit file with the following content to check for any sensitive data in the codebase:

#!/bin/sh
. "$(dirname "$0")/_/husky.sh"


GIT_SECRETS_PATH="/usr/local/bin/git-secrets" # Adjust this path if necessary
# Section for git-secrets
if [ ! -x "$GIT_SECRETS_PATH" ]
# if ! command -v git-secrets &> /dev/null
then
echo "git-secrets is not installed. Please run 'brew install git-secrets' or visit https://github.com/awslabs/git-secrets#installing-git-secrets"
exit 1
fi

# Initialise git-secrets configuration for AWS
git-secrets --register-aws > /dev/null


# Custom REGEX patterns Array to check for various custom secrets
patterns="sk_live_[0-9a-zA-Z]{99} [0-9]+-[0-9A-Za-z_]{32}\.apps\.googleusercontent\.com (-){5}\s*(BEGIN\sRSA\sPRIVATE\sKEY)\s*(-){5}"

# Log file path
log_file="git_secrets.log"

# Function to add a pattern if it does not already exist
add_pattern_if_not_exists() {
pattern="$1"
existing_patterns=$(git secrets --list 2>>"$log_file")
echo "pattern===" $pattern
if echo "$existing_patterns" | grep -Fqe "$pattern"; then
echo "Pattern '$pattern' already exists. No need to add."
else
echo "Pattern '$pattern' not found. Adding pattern..."
git secrets --add "$pattern" 2>>"$log_file"
if [ $? -eq 0 ]; then
echo "Pattern '$pattern' added successfully."
else
echo "Failed to add pattern '$pattern'."
exit 1
fi
fi
}

# Iterate over the space-separated list of patterns and add them if they don't exist
for pattern in $patterns; do
add_pattern_if_not_exists "$pattern"
done


echo "Running git-secrets..."
# This command will scan whole codebase and will report any sensitive information where pattern is matched.
git-secrets --scan -r

# Scans only the files that are about to be committed.
# git-secrets --pre_commit_hook -- "$@"


npm test

Script breakdown

#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

This line ensures that Husky’s environment is properly set up before running the script. Husky is a tool that allows you to run scripts before committing or pushing your code.

GIT_SECRETS_PATH="/usr/local/bin/git-secrets"  # Adjust this path if necessary

This line sets the path to the git-secrets executable. Adjust this path based on where git-secrets is installed on your system. You can get the path by running whereis git-secrets in your terminal.

if [ ! -x "$GIT_SECRETS_PATH" ]
# if ! command -v git-secrets &> /dev/null
then
echo "git-secrets is not installed. Please run 'brew install git-secrets' or visit https://github.com/awslabs/git-secrets#installing-git-secrets"
exit 1
fi

This block checks if git-secrets is executable. If it’s not installed, it prompts the user to install it and exits the script.

Registering AWS patterns with git-secrets

# Initialise git-secrets configuration for AWS
git-secrets --register-aws > /dev/null

This command initializes git-secrets with patterns specific to AWS to automatically scan for AWS keys.

Custom regex patterns for additional secrets

# Custom REGEX patterns to check for various custom secrets
patterns="sk_live_[0-9a-zA-Z]{98} [0-9]+-[0-9A-Za-z_]{32}\.apps\.googleusercontent\.com (-){5}\s*(BEGIN\sRSA\sPRIVATE\sKEY)\s*(-){5}"

This variable contains custom regex patterns to identify other potential secrets. Each pattern is designed to match common formats of sensitive information like Stripe API keys, Google OAuth client IDs, and RSA private keys.

Log file configuration

log_file="git_secrets.log"

This sets the path to the log file where errors and other information will be logged.

Adding patterns if they don’t exist

# Function to add a pattern if it does not already exist
add_pattern_if_not_exists() {
pattern="$1"
existing_patterns=$(git secrets --list 2>>"$log_file")
echo "pattern===" $pattern
if echo "$existing_patterns" | grep -Fqe "$pattern"; then
echo "Pattern '$pattern' already exists. No need to add."
else
echo "Pattern '$pattern' not found. Adding pattern..."
git secrets --add "$pattern" 2>>"$log_file"
if [ $? -eq 0 ]; then
echo "Pattern '$pattern' added successfully."
else
echo "Failed to add pattern '$pattern'."
exit 1
fi
fi
}

This function checks if a given pattern already exists in git-secrets. If the pattern is not found, it adds the pattern. Errors are logged to the specified log file. You can check existing patterns by running the command git secrets — list.

Iterating over and adding patterns

for pattern in $patterns; do
add_pattern_if_not_exists "$pattern"
done

This loop iterates over each custom pattern and calls the function add_pattern_if_not_exists to ensure it is added to git-secrets.

Running git-secrets

echo "Running git-secrets..."
git-secrets --scan -r

This command runs git-secrets to scan the entire repository recursively for any secrets that match the registered patterns. Alternatively, you can run git-secrets --pre-commit -- "$@" command also just to scan files that are about to be committed.

Let’s test the script by making a commit. In one of my files, index.js, there is some code that exposes a Stripe secret key and an RSA private key. After running this script, the commit will be blocked, preventing sensitive information from being committed to the repository. Even if the keys are commented out, the script will still detect these patterns and stop the commit.

By following these steps, you can leverage Husky and Git-Secrets to automatically scan your code for sensitive information before committing. This proactive approach helps prevent accidental leaks of secrets, such as API keys and passwords, thereby enhancing the security of your codebase.

Conclusion

Incorporating Husky and git-secrets into your Git workflow is a proactive step towards enhancing data security and ensuring that sensitive information remains confidential throughout the development process. Embracing these tools not only protects your current projects but also sets a precedent for secure coding practices that can benefit future endeavors. By prioritizing security at every stage of development, teams can uphold trust, protect assets, and maintain compliance with industry standards, ultimately fostering a resilient and secure software ecosystem.

For more updates on the latest tools and technologies, follow the Simform Engineering blog.

Follow Us: Twitter | LinkedIn

--

--

Krunal Modi
Simform Engineering

Backend Developer (5+ yrs) | Node.js, AWS | Cloud Enthusiast