Two defenses for tag mode where an attacker with repo write access could craft a prompt injection payload in an issue/PR to gain RCE on the Actions runner: 1. git-push wrapper (H1 #3556799) The Bash(git\ push:*) rule permitted arbitrary flags and remotes, including combinations that execute shell commands locally. Replaced with scripts/git-push.sh which allowlists exactly 'origin <ref>' with no flags, validates the ref via check-ref-format. Same pattern as scripts/gh.sh. 2. acceptEdits instead of blanket Write/Edit (Asana 1213310082312048) Edit/MultiEdit/Write in allowedTools granted write access to the whole runner filesystem (~/.bashrc etc). Removed from allowedTools and set --permission-mode acceptEdits, which auto-accepts edits inside cwd ($GITHUB_WORKSPACE) and denies outside. Headless SDK has no prompt handler so 'ask' becomes deny. Also: - Noted that create-prompt/index.ts exports ALLOWED_TOOLS env var that nothing reads. The live path is modes/tag/index.ts. Mirrored the fix in both so the file the H1 report likely points to stays in sync. - Updated prompt text (3 callsites) to reference the wrapper. - Updated tests (4 prompt-content asserts, 7 tool-list asserts).
37 lines
968 B
Bash
Executable File
37 lines
968 B
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# Wrapper around `git push` that only allows `origin <ref>` with no flags.
|
|
# Defends against --receive-pack / --exec RCE and arbitrary-remote exfiltration
|
|
# (H1 #3556799). `git push:*` in allowedTools permits `git push --receive-pack='sh -c ...' ext::sh`
|
|
# which runs arbitrary shell on the Actions runner. This wrapper closes that.
|
|
#
|
|
# Usage:
|
|
# git-push.sh origin HEAD
|
|
# git-push.sh origin claude/issue-123-20260304
|
|
|
|
if [[ $# -ne 2 ]]; then
|
|
echo "Error: exactly two arguments required: origin <ref>" >&2
|
|
exit 1
|
|
fi
|
|
|
|
for arg in "$@"; do
|
|
if [[ "$arg" == -* ]]; then
|
|
echo "Error: flags are not allowed (got: $arg)" >&2
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
if [[ "$1" != "origin" ]]; then
|
|
echo "Error: remote must be 'origin' (got: $1)" >&2
|
|
exit 1
|
|
fi
|
|
|
|
REF="$2"
|
|
if [[ "$REF" != "HEAD" ]] && ! git check-ref-format --branch "$REF" >/dev/null 2>&1; then
|
|
echo "Error: invalid ref: $REF" >&2
|
|
exit 1
|
|
fi
|
|
|
|
exec git push origin "$REF"
|