Skip to content

ci(hooks): resolve the policy cache from a worktree and harden the origin check - #24

Merged
tnunamak merged 2 commits into
mainfrom
fix/keyscan-worktree-and-origin-scrub
Aug 18, 2026
Merged

ci(hooks): resolve the policy cache from a worktree and harden the origin check#24
tnunamak merged 2 commits into
mainfrom
fix/keyscan-worktree-and-origin-scrub

Conversation

@tnunamak

Copy link
Copy Markdown
Member

The EVM key-scan bootstrap cannot pass from a git worktree, and its policy-cache origin check is satisfiable from the caller's environment. Both are fixed in the central policy (vana-com/.github#2) and in vana-sdk (vana-com/vana-sdk#189, merged); this applies the same fix here.

Worktree bug

Git exports GIT_DIR into hook processes. In a linked worktree that value is an absolute path, so git -C "$policy_dir" ... still resolves against the pushing repository and reports ITS remote, HEAD and status instead of the policy cache's. Validation then rejects a perfectly good cache:

Refusing unexpected policy-cache origin: ~/.local/share/vana-secret-scan/policy/<sha>

In a normal checkout GIT_DIR is the relative .git, which happens to resolve correctly under -C — which is why this only bites worktrees. A hook that cannot pass is a hook developers route around with --no-verify, which is the outcome this policy exists to prevent.

Origin check hardening

The scrub list is derived from git rev-parse --local-env-vars rather than hardcoded. Beyond the directory variables that fix the worktree bug, that covers the repository-local variables (GIT_SHALLOW_FILE, GIT_GRAFT_FILE, GIT_REPLACE_REF_BASE, GIT_IMPLICIT_WORK_TREE) and GIT_CONFIG_PARAMETERS/GIT_CONFIG_COUNT, which git -c foo=bar push exports into hooks.

GIT_CONFIG_GLOBAL is not in that list, so it is added explicitly. Without it, a caller can point remote.origin.url at vana-com/.github from its own environment and satisfy the origin check against a cache whose real origin is attacker-controlled. Verified on git 2.53.0: with the directory-only scrub the check returned the spoofed URL; with GIT_CONFIG_GLOBAL scrubbed it returns the real (attacker) URL and refuses.

The git rev-parse --show-toplevel that discovers the pushing repo deliberately keeps the inherited environment — that is exactly what it wants.

Policy SHA bump

CENTRAL_POLICY_SHA moves to 9990452 (the merge of vana-com/.github#2). This is what makes the fix end-to-end: until the pinned policy contained the same fix, install/status would fail one layer later in the central scripts.

Verification

Against the real merged policy, from a linked worktree with GIT_DIR set the way git sets it for hooks:

  • before: Refusing unexpected policy-cache origin, nothing scanned
  • after: validation passes and the policy cache is fetched at the pinned SHA
  • spoof test: with the cache's origin set to https://github.com/attacker/evil.git and GIT_CONFIG_GLOBAL claiming vana-com/.github, this branch refuses at the origin check
  • detection unchanged: verified in vana-sdk against the same policy — a range containing a key in a secret-shaped declaration still exits 1 with Potential EVM private key detected

This file is byte-identical across the five remaining repos, so the same patch applies to each.

Assisted-by: AI

tnunamak added 2 commits August 18, 2026 17:05
…igin check

Applies the fix already merged in vana-com/.github#2 and vana-com/vana-sdk#189.

Git exports an absolute GIT_DIR into hook processes from a linked worktree, so
a bare `git -C "$policy_dir"` read the pushing repo's remote/HEAD/status and
refused a valid policy cache. Routes every policy-targeting command through a
`policy_git` helper that scrubs the inherited repository environment, derived
from `git rev-parse --local-env-vars` plus the GIT_CONFIG_* file overrides —
without GIT_CONFIG_GLOBAL the origin check is satisfiable from the caller's
environment against an attacker-controlled cache.

Bumps CENTRAL_POLICY_SHA to vana-com/.github@9990452 so the fix is end-to-end.

Assisted-by: AI
The reusable workflow file is byte-identical between 5f1b4b1 and 9990452, so
CI behavior is unchanged — but the workflow calls install-gitleaks.sh, which
9990452 fixes for macOS (Darwin ships its own /sbin/sha256sum that rejects the
GNU long options, so the download checksum failed for every download). Keeps
the CI pin and the bootstrap pin on the same reviewed policy commit.

Assisted-by: AI
@tnunamak
tnunamak merged commit ce77e8c into main Aug 18, 2026
3 checks passed
@tnunamak
tnunamak deleted the fix/keyscan-worktree-and-origin-scrub branch August 18, 2026 22:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant