fix(git): refuse repository config that runs a program before push, release and gc

An agent that can write a repository's .git/config could make the operator's pkgmgr push, release or branch gc run a program or reroute the push. UNSAFE_CONFIG lists the local keys that do (core.sshCommand, gitProxy, askPass, fsmonitor, alternateRefsCommand, credential helpers, gpg programs, protocol.*, config hooks, gc.recentObjectsHook, http proxy/TLS/cookie keys, remote pack programs and proxy, url rewrites). push and release refuse up front; gc skips its fetch and keeps remote branches. Filter drivers, hooksPath, gpg.format and include stay allowed for git-lfs, husky and per-repo signing.

SCAN_FLAGS add --no-pager and switch off config-defined hooks (hook.<event>.enabled=false), which core.hooksPath does not cover. The signing amend, gc's fetch, delete push and branch -D run under them. Remote and ref names sit behind -- in every push, fetch, ls-remote and remote get-url, fetches and pushes no longer recurse into submodules, and a staged gitlink is no longer folded into the signed HEAD. gc skips a compose project that also has containers outside the worktree.

🎯 Fix: 92 %
💥 Break: 4 %
💸 Cost: 91 %
⏱️ Time: 89 %
🛡️ Security: 100 %
🏆 Score: 100
🚦 Gate: ✅ 90/5, cost and time <= 100, security 100 %

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kevin Veen-BirkenbachandClaude Opus 5.5 committed 2026-11-07 13:26:40 +00:00
1 parent fb6183838b
commit 4c8b137449
13 files changed
+467 -22

No files matched your search

+10
View File
@@ -448,6 +448,16 @@ class TestWorktreeUp(WorktreeFixture, unittest.TestCase):
self.assertFalse(os.path.exists(parsed))
self.assertFalse(os.path.exists(ran))
def test_checkout_runs_no_config_hook(self) -> None:
marker = os.path.join(self.root, "hooked")
git(self.repo, "config", "hook.probe.command", f"touch {marker}")
git(self.repo, "config", "hook.probe.event", "post-checkout")
code, _ = self._up("feature/h", None)
self.assertEqual(code, 0)
self.assertFalse(os.path.exists(marker))
def test_origin_url_cannot_escape_the_worktrees_dir(self) -> None:
git(self.repo, "remote", "set-url", "origin", "https://host/../../escape")