# Git ref and revision shell injection

Untrusted branch, ref, revision or patch data reaching a shell, prompt or git hook execution path

_Area: Web injection and code execution. Seen in 3 disclosed reports; latest 2026-10-05. Updated 2026-10-24._

## How it works
Git metadata (branch names, tags, remote refs, revisions, patch paths) is treated as inert text, but it is attacker-controlled and often flows into a shell string, a prompt, or a git apply/hook path. The broken assumption is that quoting makes a value safe. POSIX shells still expand `$(...)` and backticks inside double quotes, so a revision or branch name interpolated into a command line executes. Separately, git operations can materialize attacker-named paths onto disk where they execute.

## Where it shows up
- Git invocations built as shell strings with revisions/refs interpolated (merge-base, diff, show, fetch, checkout, config) [E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-w2vw-w76x-qr89.md)
- Prompt frameworks building PS1 from VCS metadata (branch, tag, remote) [E2](https://bugbountylibrary.com/r/h1%3A1785378.md)
- `git apply --index --cached -3` in a bare temp clone, where an add/add collision forces a worktree checkout into `$GIT_DIR` [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-rcr6-4jqh-j84m.md)
- Any place a branch name, revision, or patch path crosses into a shell, hook, or exec sink

## How to review
Trace every git-derived value to its sink. The invariant: untrusted refs/revisions/paths must reach git as argv elements (exec without a shell), never as part of a shell command string, and never as a path that can land under `hooks/`, `config`, or `objects/`. For prompts, the value must be escaped so PS1 does not re-evaluate it. For apply flows, confirm no three-way fallback can write outside the intended tree. Test with branch names containing `$(...)`, backticks, and `${IFS}` [E2](https://bugbountylibrary.com/r/h1%3A1785378.md)[E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-w2vw-w76x-qr89.md).

## Variants seen
- Shell string interpolation of revisions/refs in a CLI tool [E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-w2vw-w76x-qr89.md)
- Double evaluation of branch names through PS1 command substitution [E2](https://bugbountylibrary.com/r/h1%3A1785378.md)
- Patch path escaping into `$GIT_DIR/hooks` via three-way apply fallback [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-rcr6-4jqh-j84m.md)

## Why fixes fail
Double-quoting is mistaken for sanitization; POSIX still expands substitutions inside quotes [E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-w2vw-w76x-qr89.md). `--cached` is assumed to prevent worktree writes, but the `-3` fallback defeats it [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-rcr6-4jqh-j84m.md).

## Impact and severity
All three led to arbitrary command execution as the user or CI runner [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-rcr6-4jqh-j84m.md)[E2](https://bugbountylibrary.com/r/h1%3A1785378.md)[E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-w2vw-w76x-qr89.md). Severity is high because the trigger is often just opening, building, or applying a hostile repo. Worse when it runs on shared CI runners or developer machines with credentials.

## Evidence
- E1: https://bugbountylibrary.com/r/ghsa%3AGHSA-rcr6-4jqh-j84m.md
- E2: https://bugbountylibrary.com/r/h1%3A1785378.md
- E3: https://bugbountylibrary.com/r/ghsa%3AGHSA-w2vw-w76x-qr89.md
