---
name: git-integration-exploitation
description: Exploit git integrations in SaaS and cloud services -- argument injection per git subcommand, JGit vs native git attack path selection, .git/config append-only takeover, error-based file read via --pathspec-from-file, and symlink-based filesystem escape. Use when target has git-backed features like web IDEs, CI/CD pipelines, deployment from repo, LookML/Dataform-style config, or any feature that clones/pulls/commits on the server side.
---

# Git Integration Exploitation

Systematic audit methodology for SaaS services that integrate git server-side. The attack surface is not git itself -- it is the service's assumptions about what git operations are safe.

## When to Use

- Target has a web IDE, notebook, or config editor backed by git
- CI/CD pipeline clones user-controlled repos
- Deployment feature pulls from git (Heroku-style, Cloud Build, Dataform)
- Service accepts git URLs as input (import, migration, dependency resolution)
- `.git/` directory or git CLI invocation visible in errors, headers, or source

## Recon: Identify the Git Implementation

The first decision point. Different implementations have different exploitable surfaces.

| Implementation | Hooks | fsmonitor | symlinks | Argument injection |
|---|---|---|---|---|
| **Native git CLI** | Yes | Yes | Yes (Linux/macOS default) | Yes |
| **JGit (Java)** | No | No | Only if `core.symlinks=true` in config | No (API-based) |
| **libgit2 / go-git** | No | No | Varies | No (API-based) |

**How to fingerprint:**
- Error messages: Java stack traces (JGit), C/Go traces (libgit2/go-git), shell errors (native)
- Timing: native git shells out (slower cold start), JGit is in-process
- Behavior: create a repo with a `post-checkout` hook -- if it fires, native git

**Rule:** If JGit, skip hooks/fsmonitor -- pivot to symlinks or config-based file read/write. If native git, hooks and fsmonitor are the fastest path to RCE.

## Attack Primitives

### 1. Argument Injection (native git only)

The service constructs a git CLI command with user-controlled input (branch name, file path, remote URL). If the input starts with `-`, git interprets it as an option.

**The surface is per-command** -- enumerate which git subcommand the service calls, then check that command's dangerous flags:

| Git command | Dangerous flag | Effect |
|---|---|---|
| `git clone` / `git fetch` | `--upload-pack=<cmd>` | Arbitrary command execution |
| `git rm` | `--pathspec-from-file=<path>` | Read arbitrary file (contents leak via error) |
| `git diff` | `--output=<path>` | Write diff output to arbitrary path |
| `git log` | `--output=<path>` | Write log output to arbitrary path |
| `git apply` | `--directory=<path>` | Control patch application target directory |
| `git push` | `--receive-pack=<cmd>` | Arbitrary command execution on remote |

**Error-based file read via `--pathspec-from-file`:** Create a file or folder named `--pathspec-from-file=/etc/passwd`. When the service runs `git rm` on it, git reads the target file, tries to parse each line as a pathspec, and dumps non-matching lines in error output. Works best on text files with non-path characters. Binary files or files with path-like content may not leak meaningfully. Test with `/etc/hostname` (short, predictable) before targeting larger files.

### 2. Config Append-Only Takeover

Git's `.git/config` uses INI format where duplicate `[core]` sections are merged -- last value wins (see `config-file-parsing-bugs` skill for the general INI parser pattern). Append-only write access to `.git/config` lets you override any config key, including `core.fsmonitor` (RCE on next `git status`) and `core.symlinks` (enable symlink following on JGit).

**Where to look:** Any API that writes to the repo working directory without path sanitization (`WriteFile`, file upload, template generation). Test: write to `.git/config` directly -- many services forget to block the `.git/` prefix.

### 3. Symlink Filesystem Escape

When `core.symlinks = true` (default on Linux/macOS for native git), git creates real filesystem symlinks during checkout. A repo containing a symlink to `/` exposes the entire filesystem through the service's file browser. For symlink attacks via archive upload (non-git), see `archive-path-traversal` skill.

**JGit twist:** JGit defaults `core.symlinks = false`. But if you can write to `.git/config` (primitive #2), add `symlinks = true` under `[core]`. Next checkout (triggered by pull, merge, or reset) creates real symlinks.

**Cross-tenant escalation:** In multi-tenant cloud services, filesystem escape via symlink often reaches other tenants' repo directories on shared infrastructure.

### 4. Embedded Bare Repository

Push a repo containing a subdirectory structured as a bare git repo (has `HEAD`, `config`, `objects/`, `refs/`). If the service runs any git command from within that subdirectory, git discovers the embedded config.

Weaponize: set `bare = false` + `core.worktree = .` + `core.fsmonitor = <cmd>` in the embedded config. Any `git status` from that directory triggers execution.

### 5. TOCTOU on Config Regeneration

Services that regenerate `.git/config` before each git operation (as a safety measure) create a race window. Concurrent requests -- one writing the malicious config, one triggering the git operation -- can win the race.

**Test:** Use an intruder/fuzzer with two request groups running in parallel. Usually wins within 5-20 attempts.

## Audit Checklist

```
1. [ ] Does the service expose git-backed features? (IDE, deploy, import, CI)
2. [ ] Which git implementation? (native / JGit / libgit2 / go-git)
3. [ ] Can you write to .git/config? (file API, upload, template injection)
4. [ ] Which git subcommands does the service call? (trigger commit/push/pull/diff,
       grep responses for subcommand names, review client JS for action/command params)
5. [ ] Is user input used in git CLI arguments? (branch, path, remote URL, ref name)
6. [ ] Does the file browser follow symlinks? (create symlink in repo, check UI)
7. [ ] Does the service regenerate config before operations? (race condition window)
8. [ ] Multi-tenant? (filesystem escape = cross-tenant = critical)
```

## References

- [CVE-2024-32002](https://nvd.nist.gov/vuln/detail/CVE-2024-32002) -- Git recursive clone RCE via embedded bare repo + symlink
- [CVE-2022-39253](https://nvd.nist.gov/vuln/detail/CVE-2022-39253) -- Git local clone file disclosure via symlink
- [GCP-2025-045](https://cloud.google.com/dataform/docs/security-bulletins) -- Google Dataform cross-tenant via symlink (CVSS 10.0)
- [Tenable: LookOut](https://www.tenable.com/blog/google-looker-vulnerabilities-rce-internal-access-lookout) -- Google Looker RCE via hook override + race condition
