Daniel S. Billing

Securing Git Commits: Why GPG Signing is Essential for Protecting Your Codebase

4 minute read · 158 views · 1 like

As someone with over 12 years of experience in this field, I understand the critical importance of protecting both our source code and that of our clients. One challenge I have often faced with Git committing is ensuring proper commit attribution. When a developer pushes a commit to a repository, their email address becomes part of that commit’s metadata. In Git-based SCM systems, such as GitHub, this email address is linked to a specific user account. From a security standpoint, relying on something as easily accessible as an email address for attribution raises some concerns.

GitHub, for example, has the option to "claim an email address," but this introduces a significant security risk. Since anyone can commit using any name or email address, it's possible for someone to spoof a high-level team member’s identity, such as a CTO of a company, making it look like they authored a commit they never touched.

To mitigate these risks, it’s crucial that every developer verifies all of their emails with GitHub, uses their full name, and ideally adds a profile picture for better identification. Enabling two-factor authentication (2FA) is also a necessary step for securing their accounts. However, the best way to ensure the authenticity of a commit is through GPG signing, which provides a cryptographic method of verifying the committer’s identity and safeguarding the integrity of our codebase.

Getting started with GPG-Signing

With GPG-signing, we add another layer to secure down the commits done to any repository from a specific user. Instead of just accepting the commits at a whim, the GPG signing feature of Git will match the email address of your Git account with a GPG key, and sign them before pushing them to the server. GitHub handles signed commits by comparing the signature with your known public key, displaying a “Verified” flag next to the commit as long as it passes verification.

Step 1a: Windows Setup

  1. Download Gpg4win and install it using the installer.
  2. Go to the Start menu and start Kleopatra
  3. Click on “File” then “New Key Pair”
  4. Click on Create a Personal OpenPGP key pair
  5. Enter your name in the “Name” field
  6. Enter your email (used for commits) in the “Email” field
  7. Review and Create the key
  8. In the pop-up; Enter a passphrase and click “Ok”
  9. Click “Finish”
  10. Double-click the key to see the certificate details
  11. Click on “export” and copy the public GPG Key
  12. Go to the GitHub Setup section.

Step 1b: Mac Setup

  1. Download and install GPG Suite
  2. Open GPG Suite and click on “New”
  3. Enter your name in the “Name” field
  4. Enter your email (used for commits) in the “Email” field
  5. Enter a password and confirm it
  6. Click “Create Key”
  7. In the pop-up; provide a passphrase and click “OK”
  8. Right-click the key you just generated and click “Copy”.
  9. Go to the GitHub Setup section.

Step 2: GitHub Setup

This should be done once you have done step 1a or 1b. So once you have generated a GPG key we need to add it to your GitHub account.

  1. In the upper-right corner of any page, click your profile photo, then click “Settings”.
  2. In the "Access" section of the sidebar, click “SSH and GPG keys”.
  3. Click “New GPG key”.
  4. In the "Key" field, paste the GPG key you copied in the previous step.
  5. Click “Add GPG key” and confirm your password.

Committing signed commits

For this to work you must have defined your email and name as you defined them in the GPG Key. If you are using GitHub Desktop it is easy to update that there. If you are using Git GUI integrated into your IDE you would to set that with these commands:

git config --global user.name "John Doe"
git config --global user.email "john.doe@example.com"

Automatically

To configure your Git client to sign commits by default for a specific local repository, run the following command in your terminal:

git config commit.gpgsign true

The following command will allow you to sign all commits across all repositories by default on your computer (my recommendation):

git config --global commit.gpgsign true

When you've finished making some test commits locally, push them to your remote repository on GitHub.

Note: GitHub Desktop only supports commit signing if your Git client is configured to sign commits globally.

Manually

When committing changes in your local branch, add the -S flag to the git commit command:

git commit -S -m "your commit message"

If you're using GPG, after you create your commit, provide the passphrase you set up when you generated your GPG key.

When you've finished creating commits locally, push them to your remote repository on GitHub.

Verify signing works

To verify that the commit was signed successfully go to GitHub, and navigate to your pull request or branch. Then click Commits, and make sure it says “Verified” on your latest commit.

Troubleshooting

This is the only problem that I have encountered during the past 2-3 years of doing this myself and helping others setting this up, your mileage may vary.

Problem:

error: gpg failed to sign the data
fatal: failed to write commit object

Solution: gist.github.com/paolocarrasco/18ca8fe6e63490ae1be23e84a7039374