Skip to content

Commit 063698a

Browse files
arpitjain099egibs
andauthored
Add YARA rule for CVE-2025-48384 (git submodule CR injection) (#1540)
* Add YARA rule for CVE-2025-48384 (git submodule CR injection) Detects a .gitmodules submodule path or url value that carries a smuggled carriage return, the exploitation primitive for CVE-2025-48384. git strips a trailing CR when reading a config value but does not quote it when writing, so a submodule whose path ends in CR is checked out to a different location than the one validated; paired with a symlink into .git/hooks this runs a post-checkout hook during a recursive clone. Placed under rules/impact/exploit/ alongside the existing CVE exploit rules. The rule matches an embedded CR mid-value on its own (zero false positives on benign LF or CRLF files) and a trailing CR only when the file also has bare-LF line endings, the on-disk fingerprint of a CR injected into an otherwise-LF .gitmodules, so a uniformly CRLF Windows checkout does not match. Refs: GHSA-vwqx-4fm8-6qc9 Signed-off-by: Arpit Jain <arpitjain099@gmail.com> * small rule tweaks * add newline --------- Signed-off-by: Arpit Jain <arpitjain099@gmail.com> Co-authored-by: Evan Gibler <20933572+egibs@users.noreply.github.com>
1 parent 306cb55 commit 063698a

1 file changed

Lines changed: 42 additions & 0 deletions

File tree

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
rule git_submodule_carriage_return: high {
2+
meta:
3+
description = "git .gitmodules submodule path with a smuggled carriage return (CVE-2025-48384)"
4+
details = "git strips a trailing CR when reading a config value but does not quote it when writing, so a submodule path ending in CR is checked out to a different location than the one validated; combined with a symlink into .git/hooks this runs a post-checkout hook during 'git clone --recursive'"
5+
cve = "CVE-2025-48384"
6+
reference = "https://github.blog/open-source/git/git-security-vulnerabilities-announced-9/"
7+
advisory = "https://github.com/git/git/security/advisories/GHSA-vwqx-4fm8-6qc9"
8+
repository = "https://github.com/vinieger/CVE-2025-48384"
9+
date = "2026-06-03"
10+
11+
strings:
12+
// git config section and variable names are case-insensitive, so every
13+
// pattern is matched nocase to defeat [Submodule "..."], Path =, URL =, etc.
14+
$submodule = "[submodule \"" nocase
15+
16+
// The strongest signal: a CR in the middle of a path/url value (CR followed
17+
// by more value text, not a line terminator) or a value that ends in a bare
18+
// CR at end-of-file (the trailing-CR primitive when the file has no final
19+
// newline). Neither can occur in a benign LF or CRLF .gitmodules, so each is
20+
// unambiguous on its own. $ here anchors end-of-data, not end-of-line, so it
21+
// does not fire on the \r of a normal \r\n terminator.
22+
$path_embedded_cr = /[\n\x00][ \t]*path[ \t]*=[ \t]*"?[^\r\n]*\r[^\n]/ nocase
23+
$url_embedded_cr = /[\n\x00][ \t]*url[ \t]*=[ \t]*"?[^\r\n]*\r[^\n]/ nocase
24+
$path_eof_cr = /[\n\x00][ \t]*path[ \t]*=[ \t]*"?[^\r\n]*\r$/ nocase
25+
$url_eof_cr = /[\n\x00][ \t]*url[ \t]*=[ \t]*"?[^\r\n]*\r$/ nocase
26+
27+
// A path/url value with a trailing CR (value ends \r\n). On its own this is
28+
// byte-identical to one line of a Windows CRLF file, so it is only trusted
29+
// when the submodule header itself is closed by a bare LF ("]\n), i.e. mixed
30+
// terminators, which is the on-disk fingerprint of a CR smuggled into an LF
31+
// .gitmodules. Anchoring on the header close keeps this a rare multi-byte
32+
// literal instead of a lone \n that would match every line of every file.
33+
$path_trailing_cr = /[\n\x00][ \t]*path[ \t]*=[ \t]*"?[^\r\n]*\r\n/ nocase
34+
$url_trailing_cr = /[\n\x00][ \t]*url[ \t]*=[ \t]*"?[^\r\n]*\r\n/ nocase
35+
$bare_lf = /"\]\n/
36+
37+
condition:
38+
filesize < 1MB and $submodule and (
39+
any of ($path_embedded_cr, $url_embedded_cr, $path_eof_cr, $url_eof_cr) or
40+
($bare_lf and any of ($path_trailing_cr, $url_trailing_cr))
41+
)
42+
}

0 commit comments

Comments
 (0)