fix(security): clear .git/hooks/ and disable hooksPath in cache-memory git setup#23929
fix(security): clear .git/hooks/ and disable hooksPath in cache-memory git setup#23929
Conversation
… in setup_cache_memory_git.sh - Clear all non-sample git hook files immediately after cache restore and before any git checkout or merge operations, preventing a compromised agent run from executing arbitrary code on the host runner via preserved post-checkout/post-merge hooks. - Set git config core.hooksPath /dev/null in both the new-init and existing-repo paths as belt-and-suspenders protection. - Fix legacy flat-file migration: commit pre-existing files to the 'none' branch only (not 'merged'), preventing trust escalation of data written at unknown integrity in prior gh-aw versions. Fixes: cache-memory setup must clear .git/hooks/ after cache restore Agent-Logs-Url: https://github.com/github/gh-aw/sessions/b35702d1-ef6e-4fb9-a039-99e93de0b243 Co-authored-by: szabta89 <1330202+szabta89@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Hardens the cache-memory git setup step against persisted malicious Git hooks in the Actions cache, and prevents trust escalation during legacy flat-file → git migration.
Changes:
- Clear non-sample files from
.git/hooks/immediately after cache restore (before any git operations). - Force-disable hook execution by setting
core.hooksPathto/dev/nullfor both new and existing repos. - Change legacy migration to seed all branches from an empty baseline commit and commit legacy files only to the
nonebranch.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # executed on the host runner before the AWF sandbox is established. Remove all | ||
| # non-sample hook files immediately after cache restore to prevent this. | ||
| if [ -d .git/hooks ]; then | ||
| find .git/hooks -type f ! -name '*.sample' -delete |
There was a problem hiding this comment.
The hook-clearing logic only deletes regular files (-type f), but it won’t remove symlinks placed in .git/hooks/. Since the preceding comment says “delete all non-sample files”, this is an implementation/documentation mismatch, and symlink hooks could still remain if core.hooksPath is ever not set for some reason. Consider deleting both regular files and symlinks (excluding *.sample), and consider making the deletion tolerant of undeletable files so the script doesn’t abort under set -e.
| find .git/hooks -type f ! -name '*.sample' -delete | |
| find .git/hooks \( -type f -o -type l \) ! -name '*.sample' -exec rm -f -- {} + 2>/dev/null || true |
| else | ||
| # Existing repo: disable hooks as belt-and-suspenders after the hook-file | ||
| # deletion above, ensuring no residual configuration can re-enable hooks. | ||
| git config core.hooksPath /dev/null | ||
| fi |
There was a problem hiding this comment.
git config core.hooksPath /dev/null will hard-fail the entire setup under set -e if .git/config is not writable (e.g., unexpected permissions restored from cache). To keep the security guarantee while avoiding a brittle dependency on writing repo config, consider using git -c core.hooksPath=/dev/null for the subsequent checkout/merge (and any commits) as a fallback, or making the config write best-effort with an explicit error message.
|
@copilot review comments |
Git hook files under
.git/hooks/are preserved in theactions/cachesnapshot but are not tracked by git, allowing a compromised agent run to plant executable hooks (e.g.post-checkout,post-merge) that fire on the host runner during the next run's setup step — before the AWF sandbox exists.Changes
Hook file clearing — immediately after
cd "$CACHE_DIR"and before any git operation, delete all non-sample files from.git/hooks/:Disable hooks via config — set
git config core.hooksPath /dev/nullin both the fresh-init and existing-repo code paths, ensuring no hook fires even if the deletion above were bypassed.Migration trust guard — during legacy flat-file → git migration, the previous code committed pre-existing files directly onto the
merged(highest-trust) branch. The fix initialises all branches from an empty commit and commits legacy files tononeonly, preventing trust escalation of data written at unknown integrity in prior gh-aw versions.Warning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
https://api.github.com/orgs/test-owner/actions/secrets/usr/bin/gh gh api /orgs/test-owner/actions/secrets --jq .secrets[].name go1.25.0 -c=4 -nolocalimports -importcfg /tmp/go-build1308815699/b138/importcfg -pack /home/REDACTED/go/pkg/mod/golang.org/x/oauth2@v0.34.0/deviceauth.go -o /tmp/go-build343-p -trimpath 64/bin/go -p main -lang=go1.25 go(http block)https://api.github.com/repos/actions/github-script/git/ref/tags/v8/usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha go1.25.0 -c=4 -nolocalimports -importcfg /tmp/go-build1308815699/b243/importcfg -pack /home/REDACTED/go/pkg/mod/golang.org/x/text@v0.35.0/internal/number/common.go -o /tmp/go-build343-p -trimpath 64/bin/go -p main -lang=go1.25 go(http block)/usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha /tmp/go-build343-p go 64/bin/go -p main -lang=go1.25 go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE g/sig_other.s(http block)/usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha /tmp/go-build343-p -trimpath 64/bin/go -p github.com/githu-o -lang=go1.25 go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)https://api.github.com/repos/github/gh-aw/actions/runs/1/artifacts/usr/bin/gh gh run download 1 --dir test-logs/run-1 o 64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/compile env g_.a hema-go@v0.4.2/jsonschema/annotations.go 64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/compile(http block)https://api.github.com/repos/github/gh-aw/actions/runs/12345/artifacts/usr/bin/gh gh run download 12345 --dir test-logs/run-12345 GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet env g_.a GO111MODULE 64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/compile(http block)https://api.github.com/repos/github/gh-aw/actions/runs/12346/artifacts/usr/bin/gh gh run download 12346 --dir test-logs/run-12346 GO111MODULE 64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/compile env g_.a @v1.19.2/ast/ast.go 64/pkg/tool/linux_amd64/compile on; \ echo "���git GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/compile(http block)https://api.github.com/repos/github/gh-aw/actions/runs/2/artifacts/usr/bin/gh gh run download 2 --dir test-logs/run-2 GO111MODULE 64/pkg/tool/linux_amd64/compile GOINSECURE dules/flatted/gorev-parse GOMODCACHE 64/pkg/tool/linux_amd64/compile env g_.a ibility.go 64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/compile(http block)https://api.github.com/repos/github/gh-aw/actions/runs/3/artifacts/usr/bin/gh gh run download 3 --dir test-logs/run-3 GO111MODULE 64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/compile env g_.a i.go 64/pkg/tool/linux_amd64/compile GOINSECURE s GOMODCACHE 64/pkg/tool/linux_amd64/compile(http block)https://api.github.com/repos/github/gh-aw/actions/runs/4/artifacts/usr/bin/gh gh run download 4 --dir test-logs/run-4 GO111MODULE 64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/compile env 3531062895/.github/workflows @v1.19.2/lexer/lexer.go 64/pkg/tool/linux_amd64/compile GOINSECURE go-sdk/oauthex GOMODCACHE 64/pkg/tool/linux_amd64/compile(http block)https://api.github.com/repos/github/gh-aw/actions/runs/5/artifacts/usr/bin/gh gh run download 5 --dir test-logs/run-5 rotocol/go-sdk@v1.4.1/oauthex/oa-test.run=^Test 64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/compile env 3531062895/.github/workflows @v1.19.2/parser/color.go 64/pkg/tool/linux_amd64/compile GOINSECURE obyte/asn1 GOMODCACHE 64/pkg/tool/linux_amd64/compile(http block)https://api.github.com/repos/github/gh-aw/actions/workflows/usr/bin/gh gh workflow list --json name,state,path go1.25.0 -c=4 -nolocalimports -importcfg /tmp/go-build1308815699/b248/importcfg -embedcfg /tmp/go-build1308815699/b248/embedcfg env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)/usr/bin/gh gh run list --json databaseId,number,url,status,conclusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle --workflow nonexistent-workflow-12345 --limit 100 GOMOD GOMODCACHE go env -json GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile(http block)/usr/bin/gh gh run list --json databaseId,number,url,status,conclusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle --workflow nonexistent-workflow-12345 --limit 6 GOMOD sm_wasm.s x_amd64/vet env -json GO111MODULE 64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/compile(http block)https://api.github.com/repos/github/gh-aw/git/ref/tags/v1.2.3/usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.2.3 --jq .object.sha -json d.go 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE x_amd64/asm GOINSECURE GOMOD GOMODCACHE x_amd64/asm(http block)https://api.github.com/repos/github/gh-aw/git/ref/tags/v2.0.0/usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq .object.sha -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile(http block)/usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq .object.sha -json .go 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE x_amd64/asm GOINSECURE GOMOD GOMODCACHE x_amd64/asm(http block)/usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq .object.sha -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env sm-opt -Oz (size-p GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile(http block)https://api.github.com/repos/github/gh-aw/git/ref/tags/v3.0.0/usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v3.0.0 --jq .object.sha -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE x_amd64/asm GOINSECURE GOMOD GOMODCACHE x_amd64/asm(http block)https://api.github.com/repos/nonexistent/repo/actions/runs/12345/usr/bin/gh gh run view 12345 --repo nonexistent/repo --json status,conclusion GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/compile env 2473059164/.github/workflows GO111MODULE 64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE gh-aw.opt.wasm gh-aw.wasm; \ AFTER=$(wc -c < g(http block)https://api.github.com/repos/owner/repo/actions/workflows/usr/bin/gh gh workflow list --json name,state,path --repo owner/repo 64/bin/go **/*.json --ignore-path ../../../.pretti/tmp/go-build1308815699/b103/_pkg_.a go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)/usr/bin/gh gh workflow list --json name,state,path --repo owner/repo 64/bin/go **/*.json --ignore-path ../../../.pretti/tmp/go-build1308815699/b121/_pkg_.a go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go(http block)https://api.github.com/repos/owner/repo/contents/file.md/tmp/go-build3946149/b396/cli.test /tmp/go-build3946149/b396/cli.test -test.testlogfile=/tmp/go-build3946149/b396/testlog.txt -test.paniconexit0 -test.v=true -test.parallel=4 -test.timeout=10m0s -test.run=^Test -test.short=true -importcfg /tmp/go-build1308815699/b224/importcfg -pack /home/REDACTED/go/pkg/mod/github.com/segmentio/asm@v1.1.3/ascii/ascii.go conf�� extensions.objec-p /usr/lib/systemdinternal/syscall/unix 64/bin/go 69 --log-level 64/bin/go go(http block)https://api.github.com/repos/test-owner/test-repo/actions/secrets/usr/bin/gh gh api /repos/test-owner/test-repo/actions/secrets --jq .secrets[].name che/go-build/f9/-p **/*.cjs 64/bin/go **/*.json --ignore-path ../../../.pretti/tmp/go-build1308815699/b167/_pkg_.a /opt/hostedtoolc-trimpath -o /tmp/go-build343-p -trimpath 64/bin/go -p github.com/githu-o -lang=go1.25 go(http block)If you need me to access, download, or install something from one of these locations, you can either: