A discussion I have quit often is about the recommendation if companies should require all their developers to sign their commits locally or not. Here is my perspective on that matter.
Git is very powerful and gives you the possibility to alter existing commits. But this also means, that the author of a commit is not necessarily the one that is committing the code. A commit has two fields: author and committer. Both fields get set to the values of
git config plus a timestamp. If you rebase, for example, the committer changes to the current value – but the author stays the same. Both fields have absolutely nothing to do with the authentication to GitHub or any other server.
An example: you can look up the email address of Linus Torvalds in the Linux repository, configure your local git repository to use this email address, and commit to your repo. The commit will appear as if the author was Linus:
The link of the profile picture will also work and redirect you to the correct profile page. But the commit does not have a Verified badge unlike commits you perform on the server – either by modifying a file in the web UI or by using a pull request to merge your changes on the server.
This always scares a lot of customer if they see that it is so easy to fake the author of a commit.
Signing commits and tags locally
To sign your commits and tags locally you need a GPG key. If you don’t have one yet, you can create one using
gpg --full-gen-key (see generating a new GPG key):
$ gpg --full-gen-key
Follow the instructions or have a look at the documentation. Make sure to use your name and email address like you have configured them in
git config and leave the comment empty.
If they generation of the key was successful, display your keys and note the keyid:
$ gpg --list-secret-keys --keyid-format short
If you are using multiple email addresses you can edit the key and add them:
$ gpg --edit-key <keyid> $ gpg> adduid
Enter name, email address and o for OK. You also have to trust the new uid:
$ gpg> uid 2 $ gpg> trust $ gpg> 5 #ultimate $ gpg> save
Now you can configure git to use your key for signing:
$ git config --global user.signingkey <key-id>
To sign your commits or tags you have to use the
$ git commit -S $ git tag -S Tag-Name
Since people tend to forget this, you can also configure git to always sign commits or tags:
$ git config --global commit.gpgSign true $ git config --global tag.gpgSign true
For GitHub to verify your signature, you have to upload your public key to SSH und GPG keys. You can export the public key using the following command:
$ gpg --armor --export <keyid>
That was easy, right? Should we then enforce this for all developers?
Should we require all developers to sign their commits?
Signing your commits is not hard – if you always work on the same machine with the same identity. If you often change machines it gets much more complicated. If, for example, you use GitHub Codespaces, then you have to upload you PGP key to every Codespace before you can create a commit or a tag.
Edit: For Codespaces you can let GitHub sign all your commits if your name and mail address are correct. You can configure this in your personal settings. GitHub will sign the commit with the a GitHub key. The argument still stands for all other virtual development environments.
If you work with different email addresses you have to keep that in synch with your keys. Also, some IDEs or other tools with git integration do not have a good support for signing. Over all, it will cost you productivity of your teams.
And until now, I could not find one real reason, why an attacker that has gained push access to your repository would benefit from faking the author information of a commit or tag. If an attacker gains push access to your repo, they can happily use that credentials to inject malicious code or dependencies. The challenge is to bypass the code reviews – not to fake author information of commits. And the pull requests will always still be created with the identity of the real user! And that is also true for the forensic. If you find the malicious code, you check who created and approved the pull request – not at the author information of the commits.
One argument is sometimes that people do less code review if they are so impressed by the author of the commits. I think that is a fake argument. The pull request still comes from a real identity – and if one commit is from a trusted author that is not the owner of the pull request, this more suspicious then if author and pull request owner are the same.
If you can think of a real attack scenario, please let me know in the comments. I’m happy to change my mind on this – but for now I would not trade productivity for this.
What you should do
Software supply chain attacks are a real threat – and you should take it seriously. It’s just that signing your commits will not be a big help with that. What you should do code wise is picking a branching workflow – like MyFlow – that has protected branches and relies on pull requests and code reviews. If you merge or squash pull requests on the server, GitHub will sign the commits using its own PGP key. If you rely on tags for releasing, then you can sign these tags and add a tag protection.
What you should do is closely monitoring and managing your dependencies. Have a close look at all added dependencies: typo squatting and namespace shadowing are bigger threat than faked author information in commits. Make sure to update all dependencies on time. Most attacks are still based on known vulnerabilities that not have been patched yet. Add code scanning to you pipeline to make it harder to inject malicious code. And make sure to build and deploy your code in ephemeral environments with an end-to-end traceability. And prefer isolated, containerized development environments – like GitHub Codespaces – over lokal development environments. Especially if you developers would need local admin rights.
I encourage developers to sign their commits. I think this is a good practice. But I’m not recommending enforcing this as a policy. In some environments the productivity loss might be negligible – but in others it is not. And there is just no real value from a security perspective.