Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions cmd/git_harden_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ import (
func rawGit(t *testing.T, repo string, args ...string) {
t.Helper()
cmd := exec.Command("git", append([]string{"-C", repo}, args...)...)
cmd.Env = append(os.Environ(), "GIT_PAGER=cat",
"GIT_AUTHOR_NAME=t", "GIT_AUTHOR_EMAIL=t@t", "GIT_COMMITTER_NAME=t", "GIT_COMMITTER_EMAIL=t@t")
cmd.Env = gitIsolatedEnv("GIT_PAGER=cat")
if out, err := cmd.CombinedOutput(); err != nil {
t.Fatalf("git %v: %v\n%s", args, err, out)
}
Expand Down Expand Up @@ -82,7 +81,7 @@ func TestGitSync_InsteadOfExtNeutralized(t *testing.T) {
rawMarker := filepath.Join(markerDir, "raw.txt")
writeExtConfig(rawMarker)
rawFetch := exec.Command("git", "-C", repo, "-c", "fetch.recurseSubmodules=no", "fetch", "--no-recurse-submodules", "--no-tags", "origin")
rawFetch.Env = append(os.Environ(), "GIT_PAGER=cat", "GIT_TERMINAL_PROMPT=0")
rawFetch.Env = gitIsolatedEnv("GIT_PAGER=cat")
_, _ = rawFetch.CombinedOutput()
if _, err := os.Stat(rawMarker); err != nil {
t.Skipf("ext:: did not fire under raw git on this platform (%v) — fixture inert here", err)
Expand Down Expand Up @@ -112,7 +111,7 @@ func TestGitSync_MaliciousFsmonitorNeutralized(t *testing.T) {

// Baseline: raw (unhardened) git status FIRES the fsmonitor — the fixture is real.
rawStatus := exec.Command("git", "-C", repo, "status", "--porcelain")
rawStatus.Env = append(os.Environ(), "GIT_PAGER=cat")
rawStatus.Env = gitIsolatedEnv("GIT_PAGER=cat")
_, _ = rawStatus.CombinedOutput()
if _, err := os.Stat(rawMarker); err != nil {
t.Skipf("fsmonitor did not fire under raw git on this platform (%v) — fixture inert here", err)
Expand Down
42 changes: 42 additions & 0 deletions cmd/gittest_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package cmd

import (
"os"
"strings"
)

// gitIsolatedEnv returns the environment for a git subprocess in a cmd-package
// test that cannot read or mutate the developer's real git configuration, or any
// repo outside the test's temp space — even if a call omits `-C`/`cmd.Dir`, or the
// ambient repo's git state is corrupted (e.g. core.bare flipped by a concurrent
// operation). It mirrors the evals harness helper of the same name.
//
// `append(os.Environ(), …)` is unsafe here: an inherited GIT_DIR/GIT_WORK_TREE
// could redirect the command at the host repo, and git would read the host
// ~/.gitconfig — making tests non-deterministic and, under adverse conditions,
// letting a test's identity or fixture commits leak into the working repo. So this
// strips every inherited GIT_* variable, then pins a deterministic identity,
// non-interactive behaviour, and neutralised config discovery (no system config,
// an empty global config). The repo's own LOCAL .git/config is untouched, so tests
// that seed hostile local config (git-hardening tests) still exercise it.
//
// The identity is deliberately distinctive (`ferry-test`) so that if it ever does
// leak, it is instantly recognisable as a test fixture — unlike the bare `t` that
// previously made such a leak hard to trace.
func gitIsolatedEnv(extra ...string) []string {
env := make([]string, 0, len(os.Environ())+8)
for _, kv := range os.Environ() {
if strings.HasPrefix(kv, "GIT_") {
continue // drop GIT_DIR/GIT_WORK_TREE/GIT_INDEX_FILE/GIT_CONFIG*/… host bleed
}
env = append(env, kv)
}
env = append(env,
"GIT_TERMINAL_PROMPT=0",
"GIT_CONFIG_NOSYSTEM=1",
"GIT_CONFIG_GLOBAL=/dev/null",
"GIT_AUTHOR_NAME=ferry-test", "GIT_AUTHOR_EMAIL=ferry-test@localhost",
"GIT_COMMITTER_NAME=ferry-test", "GIT_COMMITTER_EMAIL=ferry-test@localhost",
)
return append(env, extra...)
}
3 changes: 1 addition & 2 deletions cmd/init_github_gate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,12 @@ func TestWholeCommitGate_BlocksNonZshrcFile(t *testing.T) {
repo := t.TempDir()
run := func(args ...string) {
cmd := exec.Command("git", append([]string{"-C", repo}, args...)...)
cmd.Env = gitIsolatedEnv()
if out, err := cmd.CombinedOutput(); err != nil {
t.Fatalf("git %v: %v\n%s", args, err, out)
}
}
run("init", "-q")
run("config", "user.email", "t@localhost")
run("config", "user.name", "t")

// A committed file that is NOT ~/.zshrc — e.g. a generated manifest — carrying a
// fake secret. The gate must catch it.
Expand Down
7 changes: 2 additions & 5 deletions cmd/sync_restore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,7 @@ import (
func testGit(t *testing.T, repo string, args ...string) string {
t.Helper()
cmd := exec.Command("git", append([]string{"-C", repo}, args...)...)
cmd.Env = append(os.Environ(),
"GIT_TERMINAL_PROMPT=0", "GIT_PAGER=cat",
"GIT_AUTHOR_NAME=t", "GIT_AUTHOR_EMAIL=t@t", "GIT_COMMITTER_NAME=t", "GIT_COMMITTER_EMAIL=t@t",
)
cmd.Env = gitIsolatedEnv("GIT_PAGER=cat")
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("git %v: %v\n%s", args, err, out)
Expand Down Expand Up @@ -69,7 +66,7 @@ func newStashRepo(t *testing.T) (repo string, s *snapshot, realStashSHA string)
func stashCount(t *testing.T, repo string) int {
t.Helper()
cmd := exec.Command("git", "-C", repo, "stash", "list")
cmd.Env = append(os.Environ(), "GIT_PAGER=cat")
cmd.Env = gitIsolatedEnv("GIT_PAGER=cat")
out, _ := cmd.CombinedOutput()
n := 0
for _, l := range strings.Split(strings.TrimSpace(string(out)), "\n") {
Expand Down
Loading