Signing, Trust, Secret Removal, fsck, Safe Directories, and Repository Integrity: Concepts, Architecture, and Mental Model
Separate Git object integrity, signer authenticity, authorization, credential secrecy, repository ownership trust, fsck evidence, and sensitive-history remediation into a precise production security model.
Learning objectives
- Distinguish object integrity, signer authenticity, authorization, credential secrecy, and repository trust.
- Explain OpenPGP, X.509, and SSH signing formats and the identity-policy layer above cryptographic verification.
- Treat exposed credentials as revocation/rotation incidents before Git history cleanup.
- Explain safe.directory as a narrow protected-configuration ownership exception.
- Use fsck as object/connectivity evidence without treating it as malware, secret, or authorization proof.
1. Source-control security has several different questions
A repository can be internally consistent and still be unsafe. A commit hash can prove that an object has not changed since its object ID was calculated, yet it does not prove who created it, whether that person was authorized to publish it, whether the content contains a credential, or whether the repository itself is trusted to execute local configuration and hooks.
Chapter 20 treated merge correctness as more than marker removal. Chapter 21 applies the same discipline to security: integrity, authenticity, authorization, credential secrecy, and repository trust are related controls, but they are not synonyms.
2. Start with read-only evidence
git --version
git status --short --branch
git log --graph --decorate --oneline --all --max-count=30
git log -1 --show-signature
git config --list --show-origin --show-scope
git config --show-origin --get-all safe.directory
git fsck --no-progress
A missing safe.directory output is not an error; it can
mean no explicit exceptions are configured. Likewise, an unsigned
commit is not automatically malicious. The point is to establish
what Git can actually prove before drawing a security conclusion.
3. Integrity, authenticity, authorization, and secrecy answer different questions
| Question | Git/security concept | What it does not prove |
|---|---|---|
| Did this object change? | Content-addressed object integrity | Who approved it |
| Did this signing key sign this payload? | Cryptographic signature verification | That the key belongs to an authorized person |
| May this actor update protected source? | Server/filesystem/hosting authorization policy | That committed content is secret-free |
| Is a token/password still usable by an attacker? | Credential lifecycle: revoke/rotate | That old repository copies no longer contain it |
| Should Git trust this repository ownership/config context? | Ownership and safe.directory protections |
That the repository is malware-free |
4. Git object IDs are integrity identifiers, not author identities
Blobs, trees, commits, and annotated tags are content-addressed. A commit object includes its tree, parents, author/committer metadata, and message, so changing any of those fields creates a different commit ID. That property makes accidental or malicious object mutation detectable, but an attacker who can create new objects can also create perfectly valid hashes.
5. Signed commits and tags add a cryptographic statement
Git can embed cryptographic signatures in commit and tag objects.
The signing backend is selected by gpg.format. Current
Git supports OpenPGP, X.509, and
SSH formats. The historical configuration prefix
and command wording still use “gpg” in many places even when the
selected format is SSH or X.509.
flowchart TD O[Commit or tag payload] --> H[Git object ID] O --> S[Cryptographic signature] S --> K[Public-key verification] K --> I[Identity / key trust mapping] I --> P[Organization authorization policy] H --> V[Object integrity check]
The object ID checks the stored object; the signature checks possession of a signing key; the identity/trust mapping connects the key to a principal; and organization policy decides whether that principal was authorized for this action.
6. OpenPGP verification needs both cryptographic validity and trust interpretation
git verify-commit and
git verify-tag invoke the configured signing backend. A
“good signature” means the signature mathematically matches the
payload and key. It does not by itself establish that the signer is
the release manager your organization intended to authorize.
7. SSH signing uses an allowed-signers trust mapping
With gpg.format=ssh, Git uses SSH signature tooling.
Current configuration supports
gpg.ssh.allowedSignersFile, which maps principals to
trusted public keys. Without an appropriate trust mapping, a
mathematically valid SSH signature is not automatically equivalent
to an organization-approved identity.
8. X.509 signing relies on certificate trust infrastructure
With gpg.format=x509, Git uses the X.509 signing
backend and a configured program such as gpgsm.
Certificate-chain validity and organizational authorization still
need a policy. Git does not turn a certificate into deployment
approval merely because the cryptographic check succeeds.
10. A leaked credential is an incident even if Git history is later rewritten
A token, password, private key, or other credential committed into Git may already have been copied to clones, caches, logs, forks, build artifacts, or mirrors. The primary containment action is to revoke or rotate the real credential. History rewriting is a secondary containment/cleanup step that reduces future exposure; it cannot retroactively make a previously usable credential safe.
11. Training uses fake markers, never real credentials
FAKE_TOKEN_DO_NOT_USE_2026
This course uses an intentionally non-sensitive marker. Never substitute a real token, private key, authorization header, credential-helper output, or password in a training repository, screenshot, terminal transcript, or support ticket.
12. Removing a secret from the working tree does not remove it from history
git log -S'FAKE_TOKEN_DO_NOT_USE_2026' --all -p
git grep 'FAKE_TOKEN_DO_NOT_USE_2026' $(git rev-list --all)
A later commit that deletes the string only makes the current snapshot clean. Older reachable commits still retain the blob unless history is rewritten or the containing refs are removed and old data eventually ages out of every relevant copy.
13. Secret removal changes commit identities
When a historical blob is changed, its blob ID changes, its containing tree changes, the commit containing that tree changes, and every descendant commit whose parent chain includes that commit also changes. Rewriting therefore coordinates a new history, not an in-place edit of old immutable objects.
14. Rewriting signed history invalidates the old signature relationship
A signature covers a specific commit or tag payload. If the payload
or parent chain changes, the original signature cannot remain a
valid signature of the rewritten object. Current
git filter-repo documentation notes that rewritten
commit signatures are stripped and signed tags become unsigned
annotated tags. After cleanup, establish new attestations according
to policy rather than pretending old signatures survived unchanged.
15. safe.directory is an ownership trust exception
Git normally refuses to operate on a repository owned by a different
user in security-sensitive circumstances.
safe.directory lets protected configuration declare
specific repositories trusted despite ownership differences. Because
an untrusted repository must not be able to whitelist itself, this
setting is respected only in protected configuration scopes.
16. Do not disable repository-ownership protection globally
Current Git supports safe.directory=* as a complete
opt-out. This course does not use it as a fix. If
ownership is legitimate, prefer correcting filesystem
ownership/permissions or adding one exact, reviewed path in
protected configuration. Broad wildcards turn a diagnostic warning
into a weakened trust boundary.
17. git fsck checks repository object validity and
connectivity
git fsck verifies object database consistency,
references, and reachability according to its mode. It can report
missing, malformed, dangling, and unreachable objects. That makes it
useful for integrity diagnostics, but it is not a malware scanner,
secret scanner, signer-authorization system, or proof that every
repository action was legitimate.
18. Dangling and unreachable objects are evidence, not automatic trash
Rebases, aborted work, temporary objects, and ref movement can leave objects outside current reachable history. Current Git documentation explicitly describes dangling objects as common and not inherently problematic. During an incident, preserve them until you understand whether they contain recoverable work or forensic evidence.
19. DevOps connection — source control is part of the software supply chain
A production operating model needs separate controls for object integrity, signer identity, repository authorization, credential rotation, ownership trust, server-side object validation, and incident evidence retention. Collapsing them into one “Git is secure” claim creates blind spots at exactly the moments when CI/CD and release provenance matter most.
20. Knowledge check
Question 1. Does a valid Git object hash prove who authored or approved the object?
Question 2. Does a mathematically valid signature automatically prove organizational authorization?
Question 3. What is the first security action after a real credential is exposed in Git?
Question 4. Why is safe.directory=* not the
default remediation?
Question 5. What can a clean fsck result not prove?
21. Summary
Git integrity, cryptographic authenticity, authorization, secret lifecycle, repository ownership trust, and fsck diagnostics are separate layers. Secure operations preserve that separation so each control answers the question it was designed to answer.
Authoritative references
Git signature formats
git-config signing and safe.directory
git-fsck
filter-branch warning and filter-repo recommendation
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.