Verifying code changes in Git repositories plays a key role in keeping development workflows secure and reliable. Git's SSH signature verification checks that a commit or tag was signed by a particular cryptographic key. Still, this step alone does not confirm that the key belongs to the person named in the commit metadata.
How Git SSH Signature Verification Works
Git lets users sign commits and tags with SSH keys. The configuration gpg.format=ssh tells Git to use SSH signatures for signing and verification. When a developer signs a commit, Git checks the cryptographic validity of the signature. This confirms that a specific key created the signature. However, it does not automatically link the key to the claimed identity in the commit message.
To solve this, Git uses the gpg.ssh.allowedSignersFile configuration. This file, often called the allowed signers file or trust file, maps trusted identities (principals) to their public keys. Git's documentation states, "A file with allowed signers is required to verify signatures." During verification, Git checks if the signing key appears in this file and matches the expected principal. If the key is missing from the allowed signers file, the signature might be valid, but its trust level for the repository stays undefined. The allowed signers file lists entries that connect one or more principals with a public key. This setup lets organizations specify which keys are authorized for which identities. As Git documentation puts it, "The allowed signers file is a file that contains a list of allowed signers."
This method follows the trust and policy models in OpenSSH, where cryptographic validity, identity association, and policy acceptance are handled as separate steps. The OpenBSD SSH documentation details controls for certificate authorities and signature algorithms, showing that a valid cryptographic signature does not equal authorization under a security policy. Git applies this by requiring the allowed signers file to decide which principals can use certain public keys for signing commits and tags. For more technical background, see the OpenBSD ssh_config(5) manual.
Why Trust Files Matter for Secure Workflows
Depending only on the presence of a signature can leave security gaps. For instance, an automated verifier that checks only for a valid signature might accept a commit signed by a key never authorized for the repository or organization. Using the allowed signers file, teams can control which keys are trusted for signing commits or tags. This distinction matters in automated review and release pipelines, where unauthorized keys could introduce unreviewed or malicious changes. Git shows SSH-signature status in verification output, including whether the signature is valid and if the signer is trusted under the configured file. In practice, "valid" and "trusted" are separate verification results, not interchangeable terms.
Signing Is Not Authorization
Signing a commit identifies a cryptographic actor, but does not always mean an authorized contributor. Repository permissions set what actions a user can take. Even with a valid signature, a commit could bring in unwanted or harmful code if the account or key is compromised. The signature helps track provenance and spot some tampering, but it does not replace code review, branch protection, or secure build steps. Git's documentation notes that verification tracks the signer identity in the signature, but organizations must choose which identities are trusted for certain purposes. For example, a developer's SSH key may differ from a release or automation key. Mapping keys too broadly can weaken the separation the trust file is meant to enforce. Git's design puts the responsibility for trust on the operator who sets up the allowed signers file, making authorization a local policy call. Claims about legal authorization, corporate identity, or organizational membership should not be linked to Git’s signature verifier unless a separate identity-management system supports them.
Managing Allowed Signers Files as Code
To keep workflows secure, store the allowed signers file in a reviewed repository or managed configuration system. Assign clear ownership and set up a rotation process for updating keys. When possible, keep a one-to-one mapping between principals and keys. Remove keys quickly when people leave, devices are lost, or automation identities are retired. Treat changes to the allowed signers file with the same care as production code, since adding a key grants signature trust. In continuous integration (CI), use commands like git verify-commit or git verify-tag and require a successful trust result, not just a readable signature. Pin the Git version used for verification and record its output in the build log. Reject signatures from unknown or untrusted keys. If the repository manages its own allowed signers file, protect the branch that controls it and consider how a malicious commit could change both the signer list and the verification workflow in one move. The allowed signers file itself must be protected, reviewed, and updated when personnel, keys, or organizational roles change.
Testing Signature Verification and Trust
To make sure your workflow separates signature validity from authorization, test both success and failure cases. First, verify a commit signed by an approved key and check that the expected principal is reported. Then, confirm that a valid signature from a key not in the trust file is correctly rejected. Include a test for deleted or expired identities. These checks help avoid the mistake of confusing signature validity with actual authorization. Signed history gives useful evidence of provenance, but does not guarantee code safety. Strong workflows connect signing with protected branches, independent review, reproducible builds, and artifact provenance. Git provides the cryptographic base, but organizations must define who is trusted and what a trusted signature allows. For more details, see the official Git documentation on gpg.ssh.allowedSignersFile and git verify-commit.
