diff --git a/rules/impact/exploit/cve-2025-48384.yara b/rules/impact/exploit/cve-2025-48384.yara new file mode 100644 index 000000000..0ad870ea0 --- /dev/null +++ b/rules/impact/exploit/cve-2025-48384.yara @@ -0,0 +1,33 @@ +rule git_submodule_carriage_return: high { + meta: + description = "git .gitmodules submodule path with a smuggled carriage return (CVE-2025-48384)" + 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'" + cve = "CVE-2025-48384" + reference = "https://github.blog/open-source/git/git-security-vulnerabilities-announced-9/" + advisory = "https://github.com/git/git/security/advisories/GHSA-vwqx-4fm8-6qc9" + repository = "https://github.com/vinieger/CVE-2025-48384" + date = "2026-06-03" + + strings: + $submodule = "[submodule \"" + + // The strongest signal: a CR embedded in the middle of a path/url value + // (CR followed by more value text, not the line terminator). This cannot + // occur in a benign LF or CRLF .gitmodules and is unambiguous on its own. + $path_embedded_cr = /[\n\x00][ \t]*path[ \t]*=[ \t]*"?[^\r\n]*\r[^\n]/ + $url_embedded_cr = /[\n\x00][ \t]*url[ \t]*=[ \t]*"?[^\r\n]*\r[^\n]/ + + // A path/url value with a trailing CR (value ends \r\n). On its own this is + // byte-identical to one line of a Windows CRLF file, so it is only trusted + // when the file also contains a bare-LF line ending, i.e. mixed terminators, + // which is the on-disk fingerprint of a CR smuggled into an LF .gitmodules. + $path_trailing_cr = /[\n\x00][ \t]*path[ \t]*=[ \t]*"?[^\r\n]*\r\n/ + $url_trailing_cr = /[\n\x00][ \t]*url[ \t]*=[ \t]*"?[^\r\n]*\r\n/ + $bare_lf = /[^\r]\n/ + + condition: + filesize < 64KB and $submodule and ( + any of ($path_embedded_cr, $url_embedded_cr) or + ($bare_lf and any of ($path_trailing_cr, $url_trailing_cr)) + ) +}