Add YARA rule for CVE-2025-48384 (git submodule CR injection)#1540
Open
arpitjain099 wants to merge 1 commit into
Open
Add YARA rule for CVE-2025-48384 (git submodule CR injection)#1540arpitjain099 wants to merge 1 commit into
arpitjain099 wants to merge 1 commit into
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a YARA rule that detects the
.gitmodulesexploitation primitive for CVE-2025-48384 (GHSA-vwqx-4fm8-6qc9), the recent git submodule carriage-return vulnerability.git strips a trailing CR (
0x0D) when reading a config value, but does not quote that CR when writing the value back. Because of this asymmetry a submodule whosepathends in a CR is checked out to a different location than the one git validated. Combined with a symlink pointing into.git/hooks, an attacker can land apost-checkouthook that executes duringgit clone --recursiveof an untrusted repository. The rule flags the malicious config artifact rather than the runtime behavior, which is what malcontent sees when it scans a repo's.gitmodules.Fixes #1127.
Placement and convention
I followed the existing exploit-rule convention. The rule lives at
rules/impact/exploit/cve-2025-48384.yara, next to the other CVE/exploit rules in that directory (cve.yara,pwnkit.yara, and so on), and uses the samerule name: <severity>tag form the repo uses elsewhere. Severity ishigh, matching the advisory's CVSS 8.0 / High rating. Metadata mirrors the style already in the tree (description,cve,reference,advisory,repository,date).The issue pointed at a Yara-Rules basis for this CVE. I used the same idea (a submodule path/url value carrying a CR) but reworked the strings and condition to be tighter on false positives and to fix a couple of escaping issues in the original regex.
Detection logic
The rule requires a
[submodule "section and then one of two signals:path/urlvalue (a CR followed by more value text rather than a line terminator). This is the unambiguous smuggling shape and cannot occur in a benign LF or CRLF file, so it stands on its own.path/urlvalue with a trailing CR, but only when the file also contains at least one bare-LF line ending. Mixed line endings are the on-disk fingerprint of a CR injected into an otherwise-LF.gitmodules. This guard is what keeps a uniformly CRLF (Windows).gitmodulesfrom matching, which a naive trailing-CR check gets wrong.There is a
filesize < 64KBbound since.gitmodulesfiles are small.False-positive considerations
.gitmodulesdoes not match..gitmodules(Windows checkout, every line ends\r\n) does not match, thanks to the bare-LF guard on the trailing-CR branch.path = ...\rthat is not inside a submodule section does not match..gitmodulesthat also contains a stray bare-LF line (for example a blank line saved as LF) can still trip the trailing-CR branch. A singlepath = x\r\nline is byte-identical between the malicious lone-CR case and one line of a CRLF file, so this ambiguity is inherent to detecting the trailing-CR variant from file bytes alone. I kept the trailing-CR branch because the advisory describes the primitive as a trailing CR, and the embedded-CR branch alone would miss it; the bare-LF guard reduces the FP surface to this narrow mixed-ending case. Open to dropping the trailing-CR branch and detecting only the embedded-CR shape if you would prefer zero residual FPs over completeness.Validation
I did not add an integration test under
tests/, because that path needs a sample committed tochainguard-sandbox/malcontent-samplesplusmake refresh-sample-testdatato generate the authoritative.simpleexpectation, which I cannot do from a fork. Happy to follow up with a sample PR to the samples repo if you want the rule covered there.What I did run locally with the repo's pinned yara-x (v1.17.0, the
yrbinary the Makefile downloads):make yara-x-compilepasses with the rule added (wholerules/tree, warnings enabled).make yara-x-fmtproduces no diff, so the rule is already in canonical format.yr scanagainst hand-built samples: the rule fires on the PoC-style quoted trailing-CR path, an unquoted trailing-CR path, a trailing-CR url, an embedded mid-value CR, and a multi-submodule mixed-ending file; and it does not fire on a clean LF file, a single-line CRLF file, a realistic multi-submodule CRLF file, or a non-.gitmodulesfile containingpath = ...\r.References