At a Glance
Git commit verification is essential to ensure code authenticity and prevent impersonation. Without verification, anyone can commit code under another’s identity, as Git allows changing the author email in the configuration. This poses risks, especially in open-source and collaborative projects, where unauthorized or malicious code could be introduced under a trusted name.
We have been using Git for a long time, and it’s been a great tool. Recently, I noticed the feature for verifying commits, which GitHub has made more visible. It makes perfect sense to set this up and verify the identity of the person who committed the actual code.
What’s the catch, why is it important?
When you commit code, you add changes to files and with that, it also adds a record about you, the author of the code. This data of the author is an email address. This address can be changed within the git config file or your source control application. Nothing needs to be verified here. So I can create a commit with another commit author. On GitHub we have many open source repositories without verification in place. Sure, we have steps to make sure code is proper and get’s checked. But overall, everybody is welcome to contribute. I could absolutely push data with a wrong name and it will show up like that.
Commits can be faked and pushed to open source repos without difficulties
When committing, we can add everything. We can even push those data to a public repository. Let’s see an example. I just pushed a “new version” to my public repo with the author data of DHH. Even it links to his profile on GitHub.
I pushed it on a “test” branch in my example. In case I’m evil and want to ship malicious code, I probably have to get approval from somebody to get it merged into the master branch. But since I’m a “famous developer”, code review may not be done properly and it slips into.
This article doesn’t touch on how open source repos have to be protected, but I just want to add that main branches have to be protected and things have to go through review to maintain good and secure code. But let’s continue with the commit issue.
When looking closer, we notice that the commit isn’t verified. That’s the only way we can’t 100% assure the author isn’t DHH. But as long as not everyone is verifying the commits, this isn’t a very useful way to check.
If you’re an owner of a repo or even a company. You should make sure commits are verified. Even if developers push code within a private organisation repo, they are able to push code as someone else within the company. In open source, this problem is just way more spread out since everyone has access to contribute and push (hopefully not on the critical branches).
The only way to fully ensure code integrity is by verifying commits. Without it, we can’t be certain of the author’s identity.
Git commit signing
The solution to the problem demonstrated above is the option to verify your commit somehow. The basics were added by Git in 2012 (v1.7.9). In November 2021 (v2.34) they improved usability and added support for SSH-based commit signing. With that it’s not that hard and most people already have an SSH key setup to get access to repos or servers.
Start verifying your commits now and require others to do so in your repository.
Setup
Let’s do it and get that green “verified” label on your commits in the future.
I assume that you already have an SSH key on your local machine. If not, read about it and create one. Now, we have to add the keys to Git via the config. Add those lines in your terminal to adjust the global git config.
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_rsa.pub
git config --global commit.gpgsign true
Next, you have to let GitLab/GitHub/Bitbucket/etc. know about your public key so they can verify it with your account.
If you used a Git client, you’re probably fine. The commits are signed automatically. If you do the commits via your terminal, you have to add one more parameter to the command. Which is -S (GPG sign commit)
.
git commit -S -m "Test signed commit"
That was easy. On your next commit & push, you should be able to see that your commit was verified. So everyone knows it was you.
Additional useful cases
Case 1: Verify the Commit Signature locally
After you committed, you can check the signature locally with the following command (git log --show-signature -1
), but this will tell you: “No signature
“. Which isn’t correct. You just added a signed commit. So what’s wrong.
If you want to verify if it works locally, then you have to let your machine know which public keys are allowed. Same as what you did just before with the platform.
For that you have to adjust the global git config again and add another config which provides the SSH keys. Create the config with the following command
mkdir -p ~/.config/git
cat > ~/.config/git/allowed_signers
[your_git_username] ssh-rsa AAAAB3... [your_email@example.com]
P.S: You can also add multiple keys in the config.
After that, we have to add file to the Git config so it knows where to read from. For that another command.
git config --global gpg.ssh.allowedSignersFile ~/.config/git/allowed_signers
If we run the commit verification command again, we finally should get something green.
Good "git" signature for [your_email@example.com] with RSA key [your_rsa_key]
Case 2: Using 1Password
1Password has a feature called “1Password for SSH & Git“. This is very handy to help you manage SSH keys everywhere you need them. This also included Git Commit Signing.
Please refer to their guide, which will support you with everything we discussed above (and a bit more). Essentially, you’re all set even without prior knowledge. I have been using Git Commit Signing for around a year now without actively recognizing it. Since I set up the 1Password SSH Agent, it also managed the commit signing for me. Now, after diving deeper into the topic, I understand how it works and what it actually resolves.
Case 3: Multiple accounts (private and work repo)
You’re probably like me. You push code for your work and have a separate and private account for your other projects besides working. You want to make commit signing work with both accounts and also push the code with the proper author (email). Until now I don’t know of automatic/non error prown way to do it.
Every time I clone a repo to my local machine, I have to remind myself to adjust the git config and adjust my author details and new also the signing SSH key.
git config user.email "your_other_email@example.com"
git config user.signingkey ~/.ssh/id_rsa_COMPANY.pub
I have two SSH Keys. One for my personal usage, which is the default one id_rsa
and one for professional one id_rsa_COMPANY
. Depending on your setup you have to adjust the config. The default is set in the global git config (as explained above) and all others you have to override on a per project basis. With that said, you also have to upload the correct public keys to the provider where you host the repo.
But with that you’ll be fine. Your commit gets signed with either the correct SSH key.
Conclusion
Start using Git commit signing now. It’s easy to set up. Help others to adopt this practice as well. If you are an administrator, consider implementing rules that allow only verified commits to be pushed. This will help address the issue of unverified commits circulating in the wild. Verified commits should become a standard, much like SSL is for websites today.