← all lessons
Software Engineering · lesson 17 of 18

Security & Signing

Verified Commits & Secrets

Why it matters

Anyone can set git config user.name to ‘Linus Torvalds’. Signed commits prove identity cryptographically. And leaked secrets in Git history are a nightmare.

Key concepts

The idea

The Identity Problem

Git’s user.name and user.email are just text—anyone can fake them:

git config user.name "Elon Musk"
git config user.email "elon@tesla.com"
git commit -m "Fire everyone"

This commit would look like it came from Elon. Scary, right?

Signed commits solve this. They use cryptographic signatures that can only be created with your private key. GitHub shows a “Verified” badge on signed commits.

The Secrets Problem

Git remembers everything. If you commit an API key and then delete it, the key is still in history. Forever. Anyone who clones can find it.

# This shows ALL content ever committed
git log -p --all | grep "API_KEY"

Prevention is the only real solution—once secrets are in history, you need to rewrite history (painful) or rotate the credentials (essential).

Walkthrough

GPG Signed Commits

GnuPG (GPG) is the most common way to cryptographically sign commits and tags.

Setup GPG Key

# Generate key pair
gpg --full-generate-key
# Choose: RSA and RSA, 4096 bits, no expiration

# List keys (get the KEY_ID)
gpg --list-secret-keys --keyid-format=long
# Output: sec rsa4096/KEY_ID 2024-01-01 [SC]

# Export public key (add to GitHub)
gpg --armor --export KEY_ID

# Configure Git
git config --global user.signingkey KEY_ID
git config --global commit.gpgsign true   # Sign all commits

Signing Commits

# Sign a single commit
git commit -S -m "Signed commit"

# Verify signatures
git log --show-signature

# Verify specific commit
git verify-commit abc123

SSH Signed Commits (Git 2.34+)

# Configure SSH signing
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519.pub

# Sign commits (same as GPG)
git commit -S -m "SSH signed commit"

Protecting Secrets

Prevention: .gitignore

# Environment files
.env
.env.local
.env.*.local

# Credentials
*.pem
*.key
credentials.json
secrets.yaml

# IDE with potential secrets
.idea/
.vscode/settings.json

Prevention: git-secrets

# Install
brew install git-secrets  # macOS
# or build from source

# Initialize in repo
git secrets --install

# Add AWS patterns
git secrets --register-aws

# Add custom patterns
git secrets --add 'password\s*=\s*.+'
git secrets --add --allowed 'password = "example"'

# Scan history
git secrets --scan-history

Prevention: Pre-commit Hooks

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.18.0
    hooks:
      - id: gitleaks

Response: If Secrets Are Leaked

# 1. Immediately rotate the credential!
# This is the most important step.

# 2. Remove from history (if necessary)
# Use BFG Repo-Cleaner (faster than filter-branch)
bfg --replace-text secrets.txt repo.git

# 3. Force push (coordinate with team)
git push --force --all

# 4. Notify affected parties

GitHub Security Features

FeaturePurpose
Secret scanningAlerts on committed secrets
DependabotSecurity updates for dependencies
Code scanningSAST analysis
Branch protectionRequire signed commits
Verified badgeShows commit is signed

Key takeaways

Dos & don’ts

✅ DO

❌ DON’T

Going deeper

Requiring signed commits: GitHub branch protection can require all commits to be signed. Settings > Branches > Branch protection > Require signed commits.

Vigilant mode: GitHub can mark unsigned commits as “Unverified” rather than just not showing a badge. Helps identify potentially spoofed commits.

Rewriting history: BFG Repo-Cleaner is 10-100x faster than git filter-branch for removing secrets. But it requires force-push and coordination—everyone must re-clone.

Common mistakes

Deleting secret doesn’t remove it: git rm .env && git commit leaves .env in history. You need to rewrite history with BFG or filter-branch.

GPG key expiration: If your GPG key expires, old commits still show as verified. But you can’t make new signed commits until you extend or replace the key.