Skip to main content

Pre-receive

Prelude#

A pre-receive hook allows you to reject commits from being pushed to a git repository if they do not validate every check. Please refer to our learning center for more information.

GitGuardian pre-receive hook is performed through our CLI application ggshield. ggshield is a wrapper around GitGuardian API for secrets detection that requires an API key to work.

Since pre-receive hooks are configured to run programmatically on the VCS instance, we recommend the use of a dedicated service account to authenticate ggshield calls. To create a service account, sign in to your GitGuardian workspace and go to the API section.

You can find ggshield's pre-receive hook samples in the doc/pre-receive.sample and doc/pre-receive-docker.sample.

Preview#

pre-receive preview

Gitlab Self-Managed and Bitbucket Server#

Install ggshield git pre-receive hook#

The sample script can be found in pre-receive.sample.

  1. This pre-receive hook requires the host machine to have python>=3.8 and pip installed

  2. Install ggshield from pip: pip install ggshield

  3. Move pre-receive.sample to .git/hooks/pre-receive or to your provider's git hook directory

  4. Mark the script executable with chmod +x .git/hooks/pre-receive

  5. Define the GITGUARDIAN_API_KEY environment variable. Either in a machine wide configuration file or in the .git/hooks/pre-receive file, as instructed in the sample file.

How do I add ignored matches and use a custom config in this pre-receive hook?

  • Create a gitguardian.yaml somewhere in the system. An example config file is available here.

  • Replace in the pre-receive hook

    ggshield secret scan pre-receive

    with:

    ggshield -c <INSERT path to gitguardian.yaml> secret scan pre-receive

Install ggshield git pre-receive hook with docker#

For the pre-receive hook to work, the directory where the repositories are stored must also be mounted on the container.

The sample script can be found in pre-receive-docker.sample

  1. This pre-receive hook requires the host machine to have docker installed.
  2. Move pre-receive-docker.sample to .git/hooks/pre-receive
  3. Do not forget to chmod +x .git/hooks/pre-receive
  4. either set an environment variable machine wide GITGUARDIAN_API_KEY or set it in the .git/hooks/pre-receive as instructed in the sample file.

GitHub Enterprise#

Installing a git pre-receive hook on GitHub Enterprise requires 2 components:

  • a script executed for each push event,
  • an environment to execute the script in.

For more information: visit GitHub Enterprise documentation about pre-receive hook

The pre-receive environment#

A pre-receive hook environment is a Linux chroot. It can be generated either from an existing chroot or from a Docker image. We recommend using the ggshield Docker image to create it.

ggshield running in a chroot, you need to provide the API key to this context. The pre-receive script has to be in a repository hosted in the Github Enterprise instance. Instead of setting its value in the script, the best practice is to store the value in a file within the environment.

To generate the pre-receive environment:

mkdir /tmp/ggshieldcd /tmp/ggshielddocker create --name ggshield-environment gitguardian/ggshield:latest /bin/truedocker export ggshield-environment -o ggshield-env-exporttar xf ggshield-env-exportrm etc/localtimecp usr/share/zoneinfo/Etc/UTC etc/localtimeecho <your_gitguardian_api_key> > app/api_keyrm ggshield-env-exporttar -czvf ggshield-environment.tar.gz .

You can then upload this file to the GitHub Enterprise Server and add it using the following command:

ghe-hook-env-create ggshield-environment ~/ggshield-environment.tar.gz

Or you can upload this file to a server and pass its URL to the GitHub Enterprise web user interface to add it.

Script#

You need to add the following script to a repository hosted in the GitHub Enterprise server:

#!/bin/bash
# If you don't use the Saas product, you need to setup your onprem public api url:# export GITGUARDIAN_API_URL=<your onprem public api url>export GITGUARDIAN_API_KEY=$(cat /app/api_key)/app/.venv/bin/ggshield secret scan pre-receive

This script file should have execute permission. Since the script name appears in the pre-receive hook result, we recommend to name it pre-receive.sh.

Create the pre-receive hook#

You are now able to follow GitHub Enterprise documentation to create the pre-receive hook.

Troubleshooting#

If you encounter the following error when pushing code:

$ git push origin main
Enumerating objects: 3, done.Counting objects: 100% (3/3), done.Writing objects: 100% (3/3), 231 bytes | 231.00 KiB/s, done.Total 3 (delta 0), reused 0 (delta 0), pack-reused 0remote: pre-receive.sh: failed with exit status 1remote: cp: '/etc/localtime' and '/tmp/hooks-overlay-1fFe7b/etc/localtime' are the same file
To https://my-ghe-instance.com/my-repository.git
! [remote rejected] main -> main (pre-receive hook declined)
error: failed to push some refs to 'https://my-ghe-instance.com/my-repository.git'

It is because the environment you provide contains a /etc/localtime pointing to the same file as the GitHub Enterprise Server. It is why we replace the /etc/localtime symlink with a copy of the file it originally targets.

Skipping the pre-receive hook#

ggshield's pre-receive hook can be skipped by adding -o breakglass to the git push command.

For the -o breakglass option to be taken into account, the remote repository must have the receive.advertisePushOptions git configuration option turned on.

This option can be turned on by running the following command on the server side:

git config receive.advertisePushOptions true

Some Git hosting services enable this option globally by default. Others do not.