Skip to content

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

@szabta89

Description

@szabta89

Summary

In gh-aw v0.64.x, the cache-memory feature switched to a git-based integrity model that stores persistent state under /tmp/gh-aw/cache-memory/ (a full git repository). The actions/cache step saves and restores this entire directory, including .git/hooks/. Because git add -A does not stage files under .git/, hook files written by the agent are not tracked by git but are preserved in the cache. On the next run, setup_cache_memory_git.sh restores the cache and then calls git checkout and git merge on the host runner — triggering any post-checkout or post-merge hooks before the AWF container ever starts. This gives a compromised agent run the ability to execute arbitrary code on the host runner with host-runner privileges in a subsequent run, bypassing the AWF sandbox entirely.

A secondary concern: the legacy-to-git migration path runs git init -b merged and git add -A, committing any pre-existing flat-file cache contents directly to the merged (highest-trust) integrity branch, potentially escalating the trust level of files written at none integrity in a prior version of gh-aw.

Affected Area

cache-memory / git-based integrity model / cross-run cache persistence boundary / host-runner ↔ AWF-container trust boundary (setup_cache_memory_git.sh)

Reproduction Outline

  1. Create a workflow with cache-memory: enabled (gh-aw v0.64.x, git-based model).
  2. In run N (e.g., via a prompt-injected instruction or a malicious tool call), write an executable post-checkout hook:
    printf '#!/bin/sh\necho "$GITHUB_TOKEN" > /tmp/leaked-token.txt\n' \
      > /tmp/gh-aw/cache-memory/.git/hooks/post-checkout
    chmod +x /tmp/gh-aw/cache-memory/.git/hooks/post-checkout
  3. Confirm the hook is not staged by git: git -C /tmp/gh-aw/cache-memory add -A && git status does not list the hook file.
  4. Allow run N to complete — actions/cache saves /tmp/gh-aw/cache-memory including .git/hooks/post-checkout.
  5. Trigger run N+1 — actions/cache restores the full directory; setup_cache_memory_git.sh calls git checkout -q none on the host runner, firing the post-checkout hook before the agent container starts.

Observed Behavior

The post-checkout (and post-merge) hooks written by the agent in run N are restored from cache and executed on the host runner during the Set up cache-memory git repository step of run N+1, prior to the AWF sandbox being established.

Expected Behavior

All files under .git/hooks/ (except .sample stubs) should be removed or invalidated immediately after actions/cache restores /tmp/gh-aw/cache-memory and before any git checkout or git merge is called. Alternatively, only the git bundle or working-tree content should be cached so that .git/ is always reconstructed fresh and no cached artifact can influence host-runner git operations.

Security Relevance

Successful exploitation gives an attacker-controlled agent run the ability to execute arbitrary commands on the host runner in a subsequent workflow run, with host-runner privileges and full access to GITHUB_TOKEN and runner environment variables — entirely outside the AWF container sandbox. The attack requires only the ability to trigger one workflow run (e.g., via workflow_dispatch, issue creation, or prompt injection) and is reproducible on any GitHub Actions runner using gh-aw v0.64.x with cache-memory: enabled.

Suggested Fixes

  • Strip hooks on restore: Add a step between actions/cache restore and Set up cache-memory git repository that clears non-sample hook files: find /tmp/gh-aw/cache-memory/.git/hooks/ -type f ! -name '*.sample' -delete
  • Redirect hooksPath: In setup_cache_memory_git.sh, run git config core.hooksPath /dev/null immediately after init/checkout so no hooks under .git/hooks/ can fire.
  • Cache bundle only: Cache a git bundle or working-tree tar instead of the full /tmp/gh-aw/cache-memory directory, reconstructing .git/ fresh on each run.
  • Migration guard: During legacy flat-file → git migration, do not commit pre-existing files to the merged branch; assign them none integrity instead.

gh-aw version: v0.65.0 (finding reported against v0.64.4)

Original finding: https://github.com/githubnext/gh-aw-security/issues/1647

Generated by File Issue ·

Metadata

Metadata

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions