# Dulwich: Arbitrary File Write (RCE) on Windows via Unvalidated Drive Letters in Tree Paths

Dulwich on Windows fails to reject DOS drive-letter tree entries like `C:`, so a malicious repo checkout writes files to absolute paths outside the worktree, enabling RCE.

- Payout: Research
- Severity: high
- Program: Dulwich
- Found by: LukeBanto
- Disclosed: 2026-10-02
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-8mcx-5rqc-vhmf
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-8mcx-5rqc-vhmf
- Tags: area:oss domain:oss impact:integrity impact:rce kind:research platform:ghsa sev:high tech:python tech:windows technique:source-review vuln:path-traversal vuln:rce

**Target:** Git client checkout logic (dulwich/index.py, porcelain) on Windows
**Root cause:** `validate_path_element_ntfs` rejects `.git` variants, ADS, `git~1` and reserved device names but never checks for DOS drive-letter prefixes; `_tree_to_fs_path` then feeds the entry to `os.path.join(root, b"C:\\...")`, which discards `root` on Windows.
**Steps:**
1. Author a tree containing a directory entry named `C:` with nested `Users/victim/evil.txt` (PoC builds Blob/Tree/Commit via dulwich.objects and sets `refs/heads/main`).
2. Serve or hand the repo to a Windows victim/CI runner.
3. Victim runs `dulwich clone <repo> /target/win/worktree`.
4. `validate_path_element_ntfs` accepts `C:`; `_tree_to_fs_path` calls `os.path.join(root, b"C:\\Users\\...")` and the drive-letter absolute path overrides root.
5. Payload is written to `C:\Users\victim\evil.txt` outside the worktree.
**How found:** Compared Dulwich's NTFS path validation against the C git client, noting git blocks drive prefixes via `has_dos_drive_prefix()` in `path.c` while Dulwich's checks cover only `.git`, ADS, short names and device names; then traced how the accepted `C:` element flows into `os.path.join`.
**Exploitation:** Attacker authors malicious repo on Linux (cross-platform trees) and waits for Windows clone. Arbitrary write escalates to RCE by overwriting `C:\Users\<victim>\.gitconfig` with `core.sshCommand` pointing at an executable, dropping a binary in the StartUp folder, overwriting `.ssh/authorized_keys`, or compromising a Windows CI runner that auto-clones malicious PRs.
**Escalation:** File write chained to RCE via gitconfig `core.sshCommand` poisoning, StartUp folder persistence, or CI runner compromise leaking secrets.
**Insight:** When auditing cross-platform archive/checkout extractors, diff the path-validation denylist against the reference implementation (here git's `path.c`) and specifically test Windows-only semantics like drive prefixes and UNC paths that Linux-authored trees can still carry.

