Skip to content

fix(security): clear .git/hooks/ and disable hooksPath in cache-memory git setup#23929

Merged
pelikhan merged 2 commits intomainfrom
copilot/fix-cache-memory-setup
Apr 1, 2026
Merged

fix(security): clear .git/hooks/ and disable hooksPath in cache-memory git setup#23929
pelikhan merged 2 commits intomainfrom
copilot/fix-cache-memory-setup

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 1, 2026

Git hook files under .git/hooks/ are preserved in the actions/cache snapshot 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/:

    if [ -d .git/hooks ]; then
      find .git/hooks -type f ! -name '*.sample' -delete
    fi
  • Disable hooks via config — set git config core.hooksPath /dev/null in 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 to none only, 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
    • Triggering command: /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
    • Triggering command: /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)
    • Triggering command: /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)
    • Triggering command: /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
    • Triggering command: /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
    • Triggering command: /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
    • Triggering command: /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
    • Triggering command: /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
    • Triggering command: /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
    • Triggering command: /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
    • Triggering command: /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
    • Triggering command: /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)
    • Triggering command: /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)
    • Triggering command: /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
    • Triggering command: /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
    • Triggering command: /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)
    • Triggering command: /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)
    • Triggering command: /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
    • Triggering command: /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
    • Triggering command: /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
    • Triggering command: /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)
    • Triggering command: /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
    • Triggering command: /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
    • Triggering command: /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:

… 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>
Copilot AI changed the title [WIP] Fix cache-memory setup to clear .git/hooks after restore fix(security): clear .git/hooks/ and disable hooksPath in cache-memory git setup Apr 1, 2026
Copilot AI requested a review from szabta89 April 1, 2026 16:42
@pelikhan pelikhan marked this pull request as ready for review April 1, 2026 18:59
Copilot AI review requested due to automatic review settings April 1, 2026 18:59
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.hooksPath to /dev/null for both new and existing repos.
  • Change legacy migration to seed all branches from an empty baseline commit and commit legacy files only to the none branch.

💡 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
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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

Copilot uses AI. Check for mistakes.
Comment on lines +66 to 70
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
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 uses AI. Check for mistakes.
@pelikhan
Copy link
Copy Markdown
Collaborator

pelikhan commented Apr 1, 2026

@copilot review comments

Copilot AI requested a review from pelikhan April 1, 2026 19:19
@pelikhan pelikhan merged commit b721ac4 into main Apr 1, 2026
177 of 178 checks passed
@pelikhan pelikhan deleted the copilot/fix-cache-memory-setup branch April 1, 2026 23:50
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.

cache-memory setup must clear .git/hooks/ after cache restore, before running git checkout

4 participants