This is the story of how I architected gittuf-git, a Git compatibility layer written in Go that intercepts clone, push, and pull operations to create tamper-evident audit trails and enforce security policies before delegating to native Git.
The Challenge: Git is powerful but wasn't designed with supply chain security in mind. Unauthorized commits, reference manipulation, and policy bypass are real threats in modern software development.
The Solution: A transparent security layer that developers don't even notice—until it protects them.
The Software Supply Chain Security Gap
Git is the backbone of modern software development, but it has a fundamental security problem: trust is implicit, not enforced.
Traditional solutions like GPG signing are optional and don't provide tamper-evident audit trails, policy enforcement at the protocol level, or transparent integration with existing workflows.
Enter Gittuf: A framework that uses The Update Framework (TUF) to bring cryptographic trust policies to Git, ensuring every operation is verified and recorded.
Designing a Git Compatibility Layer
My primary contribution was gittuf-git, a Go-based binary that acts as a transparent proxy between developers and Git.
How it works:
-
1
Intercept Git commands (clone, push, pull, fetch)
-
2
Enforce gittuf security checks (cryptographic verification, policy validation)
-
3
Record operations in a Reference State Log (RSL) for tamper-evident auditing
-
4
Delegate to native Git for actual repository operations
Key Design Principles: Transparent (developers use gittuf-git exactly like git), Secure by default, Non-breaking, and Auditable (every push/pull creates an immutable RSL entry).
Technical Deep Dive: Implementation Details
1. Command Routing & Argument Processing
The entry point analyzes Git commands and routes them appropriately. Only security-critical operations trigger gittuf verification. Commands like git status or git log pass through instantly, preserving developer experience.
// Simplified version of the routing logic
switch {
case gitArgs.Command == "clone":
err := cmd.Clone(gitArgs)
case gitArgs.Command == "push":
err := cmd.Push(gitArgs)
case (gitArgs.Command == "pull") || (gitArgs.Command == "fetch"):
err := cmd.PullOrFetch(gitArgs)
default:
// Pass-through to native Git
gitCmd := exec.Command("git", rawArgs...)
err := gitCmd.Run()
}
2. Push Workflow — Creating Tamper-Evident Audit Trails
The push operation is where security enforcement happens. Before pushing, we create an immutable record of what's being pushed, then sync both Git objects and security metadata.
// Simplified push logic
func Push(gitArgs args.Args) error {
repo, _ := repository.LoadRepository()
// 1. Record what we're pushing
repo.RecordRSLEntryForReference(refName, true)
// 2. Push normal Git objects
gitPushCmd := exec.Command("git", cmdArgs...)
gitPushCmd.Run()
// 3. Push RSL + Policy metadata
repo.PushRSL(remote)
repo.PushPolicy(remote)
return nil
}
The RSL (Reference State Log): Think of it as a blockchain for Git operations—every push creates a cryptographically signed entry that can't be altered without detection.
3. Pull/Fetch Workflow — Maintaining Security Metadata Consistency
Pulling is the inverse: sync Git objects, then separately sync security metadata. RSL and policy metadata live in different Git refs (refs/gittuf/rsl, refs/gittuf/policy). Keeping them separate ensures verification happens independently of code changes.
func PullOrFetch(gitArgs args.Args) error {
// 1. Pull normal Git changes
gitPullCmd := exec.Command("git", cmdArgs...)
gitPullCmd.Run()
// 2. Pull RSL changes
repo.PullRSL(remote)
// 3. Pull policy updates
repo.PullPolicy(remote)
return nil
}
4. Test Infrastructure — Ensuring Cryptographic Correctness
I built deterministic tests to validate the entire signing workflow. Cryptographic operations must be reproducible—if the same input produces different commit IDs, verification breaks.
func TestRepositoryCommitUsingSpecificKey(t *testing.T) {
// Create a commit with a known SSH key
commitID, _ := repo.CommitUsingSpecificKey(
treeID,
refName,
"Initial commit\n",
artifacts.SSHED25519Private,
)
// Verify the commit ID is deterministic
assert.Equal(t, expectedCommitID, commitID.String())
}
Cross-platform challenge: Windows handles file paths and process execution differently than Linux. I fixed compatibility issues that were causing CI failures, contributing to the +22% test coverage increase.
Measurable Impact
Security Improvements Delivered:
- Tamper-evident audit trails: Every push is cryptographically recorded
- Policy enforcement: Unauthorized commits are rejected before reaching remotes
- Attack surface reduction: Reference manipulation becomes detectable
What I Learned
1. Security UX is Hard
The best security tools are invisible. Users shouldn't have to think about cryptographic verification—it should just work.
2. Cross-Platform Development is Tricky
What works on Linux doesn't always work on Windows. Path handling, process execution, and file permissions all behave differently.
3. Open Source Collaboration is Powerful
Working with security researchers through design reviews and threat modeling discussions taught me how to think like an attacker while building defenses.
4. Testing is Security
Every bug I fixed in the test suite prevented a potential security bypass. Deterministic tests aren't just good practice—they're a security control.
Where This Matters
Software supply chain attacks are increasing. Tools like gittuf represent a shift from trust-based to verification-based development workflows.
🏢 Enterprise Development
- • Enforce code review policies cryptographically
- • Prevent unauthorized production deployments
- • Maintain audit trails for compliance (SOC 2, ISO 27001)
🌍 Open Source Projects
- • Protect against compromised maintainer accounts
- • Verify contributor identities
- • Detect supply chain attacks early
🏥 Regulated Industries
- • Healthcare (HIPAA compliance)
- • Finance (audit trails for algorithms)
- • Government (NIST 800-53 controls)
🛡️ Real Attack Prevention
In 2024, a major npm package was compromised when an attacker gained access to a maintainer's credentials. With gittuf, the unauthorized commit would have been rejected.
Real-world impact: Every use case represents a potential attack vector that gittuf closes through cryptographic verification and policy enforcement.