This GPG error appears when verifying a signed Git commit or tag and the signature does not match the content. This indicates the signed content was modified after signing or there is a key mismatch issue.
When you verify a GPG-signed commit or tag in Git using commands like `git verify-commit`, `git verify-tag`, or `git merge --verify-signatures`, GPG checks that the cryptographic signature matches the content that was signed. A "BAD signature" means this verification failed. This is a serious warning because it indicates one of two things: either the content was modified after it was signed (which could indicate tampering), or there's a technical issue with how the signature was created or is being verified. Unlike "Can't check signature: public key not found" (which just means you don't have the signer's key), a BAD signature means GPG has the key and verified that the signature is invalid. This warrants investigation.
First, check what GPG reports for the specific commit or tag:
# For a commit
git verify-commit <commit-sha>
# For a tag
git verify-tag <tag-name>
# See signature details in log
git log --show-signature -1 <commit-sha>Note the key ID mentioned in the error. This tells you which key GPG is trying to use for verification.
Verify which key Git is configured to use for signing:
# Check global signing key
git config --global user.signingkey
# Check local signing key (overrides global)
git config --local user.signingkey
# List your GPG keys
gpg --list-secret-keys --keyid-format=longEnsure the key ID in your Git config matches the key you intend to use. The key should show [SC] or [S] capability for signing.
If the key is not trusted, GPG may report signature issues. Set the trust level:
gpg --edit-key <your-key-id>In the GPG prompt:
gpg> trust
# Select option 5 (ultimate trust) for your own keys
gpg> quitThen try verifying the signature again.
If you have multiple subkeys and GPG is choosing the wrong one, append ! to force a specific key:
# Get your subkey fingerprints
gpg --list-keys --keyid-format=long <your-key-id>
# Configure Git to use a specific subkey (note the ! at the end)
git config --global user.signingkey <SUBKEY_ID>!The exclamation mark tells GPG to use that exact key rather than selecting automatically.
If the key may be corrupted, export and re-import it:
# Export public key
gpg --export --armor <key-id> > public.key
# Export private key (store securely!)
gpg --export-secret-keys --armor <key-id> > private.key
# Delete and re-import
gpg --delete-secret-keys <key-id>
gpg --delete-keys <key-id>
gpg --import public.key
gpg --import private.keyMake sure to set the trust level again after re-importing.
GPG needs terminal access for passphrase prompts. Add this to your shell profile:
# Add to ~/.bashrc, ~/.zshrc, or equivalent
export GPG_TTY=$(tty)Then reload your shell:
source ~/.zshrc # or ~/.bashrcThis is especially important in VS Code integrated terminals or when running Git commands from scripts.
On macOS, conflicts between Homebrew GPG and GPG Suite can cause issues:
# Check which gpg is being used
which gpg
gpg --version
# If using Homebrew, install pinentry-mac
brew install pinentry-mac
# Configure GPG to use it
echo "pinentry-program $(which pinentry-mac)" >> ~/.gnupg/gpg-agent.conf
# Restart the GPG agent
gpgconf --kill gpg-agentIf you upgraded macOS recently, reinstalling may help:
brew reinstall gnupg
# Or for GPG Suite
brew reinstall --cask gpg-suite### Investigating Potential Tampering
A BAD signature on a commit you didn't create could indicate tampering. Before assuming configuration issues, verify:
1. Check the commit history: git log --oneline --graph
2. Compare with the remote: git diff <remote>/<branch>
3. Verify with the original signer if possible
If the commit came from a trusted source and shows a bad signature, it's most likely a key configuration issue rather than actual tampering.
### Subkey Selection Behavior
GPG automatically selects the most recent signing-capable subkey unless told otherwise. This can cause issues if:
- You created a new subkey after signing old commits
- The signing subkey also has authentication capability
- You're verifying commits signed with an old subkey
To check which subkey was used for a signature:
git log --format='%G? %GK %GS' -1 <commit>### Disabling Signature Verification
If you need to merge despite signature issues (not recommended for production):
# One-time merge without verification
git merge --no-verify-signatures <branch>
# Disable signature verification globally (not recommended)
git config --global commit.gpgsign falseWarning: Only do this if you've confirmed the signature issue is a configuration problem, not actual tampering.
### CI/CD Pipeline Considerations
In CI environments, GPG keys may not be available. To handle this:
# Import key from environment variable
echo "$GPG_PRIVATE_KEY" | gpg --batch --import
# Trust the key non-interactively
echo -e "5\ny\n" | gpg --batch --command-fd 0 --edit-key <key-id> trust quitOr configure CI to skip signature verification if appropriate for your security requirements.
kex_exchange_identification: Connection closed by remote host
Connection closed by remote host when connecting to Git server
fatal: unable to access: Proxy auto-configuration failed
How to fix 'Proxy auto-configuration failed' in Git
fatal: unable to access: Authentication failed (proxy requires basic auth)
How to fix 'Authentication failed (proxy requires basic auth)' in Git
fatal: unable to access: no_proxy configuration not working
How to fix 'no_proxy configuration not working' in Git
fatal: unable to read tree object in treeless clone
How to fix 'unable to read tree object in treeless clone' in Git