
VFS for Git ab95cf51 - High - Remote - RCE - core.virtualfilesystem single-quote wrap
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · vfs-quote-breakout
Class: RCE Reach: Remote
VFS for Git master ab95cf51 (tag v2.0.26259.1) - Microsoft
CloneVerb.GetCloneRoot takes the last URL path segment as the default enlistment folder and does not strip a quote. RequiredGitConfig then writes core.virtualfilesystem as a naive single-quoted hook path. microsoft/git runs that value with use_shell=1. The product comment even names bash.
A clone URL whose last segment is pwn';witness;' becomes 'C:/temp/pwn';witness;'/src/.git/hooks/GVFS.VirtualFileSystemHook.exe'. bash sees three commands. The middle one runs as the user who cloned.
| ID | no CVE yet |
| Class | RCE (single-quote wrap of core.virtualfilesystem) |
| Reach | Remote (UI:R clone of an attacker URL, or local git worktree add under a crafted dir) |
| CWE | CWE-78, CWE-116 |
| CVSS | High: 8.8 CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H |
| Product | VFS for Git (needs microsoft/git) |
| Affected | master ab95cf51d6ffd0ee0e2feae7180078fe9ecbbb3a (tag v2.0.26259.1). Windows only. |
| Auth | Victim clones an attacker URL (or git worktree add under a crafted dir) |
| License | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1 only. how=gadget (no Windows VM / live ProjFS). |
Host code as the user who cloned or ran git. Not SYSTEM. Not unauthenticated RCE that skips "victim clones this URL."
| Privilege | Method / sink | What it grants | Recon / integrity / availability | Lab-proven or inferred |
|---|---|---|---|---|
| Choose the enlistment folder name | Last path segment of gvfs clone <url> with no dest (CloneVerb.GetCloneRoot) | Directory name is attacker-chosen. Windows allows ' and ; | Integrity of dest path | Lab-proven on the copied dest helper. URL .../pwn';witness;' becomes C:\temp\pwn';witness;' |
Break out of core.virtualfilesystem | RequiredGitConfig wrap "'" + ConvertPathToGitFormat(hook) + "'" | Config value is three shell tokens, not one path | Integrity of git config | Lab-proven. Wrap is 'C:/temp/pwn';witness;'/src/.git/hooks/GVFS.VirtualFileSystemHook.exe' |
| Run an extra shell command as the cloner | microsoft/git virtualfilesystem.c use_shell=1 (bash -c of the config value) | Arbitrary host command as the cloner UID | Integrity / availability of the cloner session | Lab-proven on the gadget. witness wrote VFS-VFS-QUOTE-WITNESS. First and third tokens are missing paths (rc 127) |
| Same wrap on worktree | Program.Worktree.cs -c core.virtualfilesystem="'<path>'" | Same breakout without a clone URL | Integrity | Inferred from pin source. Not executed |
Repeat on later git status / mount | InProcessMount.TrySetRequiredGitConfigSettings re-applies the wrap | Later git also shells the hostile value | Integrity | Inferred. Not executed |
Closed on this leftover: live ProjFS / Microsoft git / gvfs clone (this host is macOS; how=gadget). SYSTEM. Unauthenticated RCE that skips "victim clones this URL". A dest whose name has no ', and the same hostile path wrapped with '\'', do not run witness.
Same pin leftovers: vfs-mount-dehydrate, vfs-clone-acl, vfs-service-sid, vfs-hook-impersonate, vfs-install-cwd.
I pinned VFS for Git master ab95cf51 after the 2026-09-28 merge. Microsoft recommends Scalar for new deployments. The tree is still tagged v2.0.26259.1. The skip list is CVE-2021-47874 (quoted binPath on this pin). Ten hunts. ProjFS hydration, GPRE parsers, cache URLs, FastFetch, and gvfs upgrade came back empty in this bar.
Then I sat on RequiredGitConfig. The comment documents bash. The wrap does not escape '. CloneVerb uses the last URL segment as the dest. That is the leftover.
Wrong turns already recorded: treating a dest with no quote as the bug (it is not); claiming SYSTEM; a reverse shell. Theatre. Native Windows was missing, so the lab is a gadget of that wrap plus bash -c.
python3 vfs-quote-breakout-Abraxas-Labs.py
or
cd lab
./run.sh
Gadget HTTP on 127.0.0.1:19630. Copies the wrap and dest helpers, then /bin/bash -c with PATH limited to a witness helper that writes the oracle. Native Windows VM was not available. Last line uses how=gadget.
SUCCESS vfs-quote-breakout how=gadget who=cloner naive-breakout=yes escaped-hold=yes VFS-VFS-QUOTE-WITNESS
Escape ' as '\'' before wrapping, or stop using use_shell and pass the hook as argv[0]. Reject clone and worktree paths that contain '.
ab95cf51d6ffd0ee0e2feae7180078fe9ecbbb3a (tag v2.0.26259.1)CloneVerb.cs default destRequiredGitConfig.cs wrap that does not escape 'virtualfilesystem.c use_shell=1ImagePathGNU Affero GPL v3.0. See LICENSE. Loopback lab only. No warranty.