CVE-2026-49987: repomix Argument Injection via --remote-branch (RCE)
A crafted branch name passed to repomix's --remote-branch flag is forwarded to git subprocesses without sanitization, letting an attacker inject git options like --upload-pack and execute arbitrary co
The problem
In src/core/git/gitCommand.ts, the execGitShallowClone function appends the user-supplied remoteBranch value directly into the argument arrays for git fetch and git checkout calls made via child_process.execFileAsync.
Because no -- positional delimiter separates the ref from the option list, git interprets a value such as --upload-pack=/tmp/payload as a legitimate flag. The existing dangerousParams blocklist inside validateGitUrl() is applied only to the remote URL, leaving remoteBranch completely unguarded.
An attacker who controls this value achieves arbitrary command execution with the privileges of the process.
Proof of concept
A working proof-of-concept for CVE-2026-49987 in repomix, with the exact payload below.
# Step 1: write the payload binary
cat > /tmp/malicious-pack << 'EOF'
#!/bin/bash
echo '=== RCE EXECUTED ===' > /tmp/repomix-pwned.txt
id >> /tmp/repomix-pwned.txt
EOF
chmod +x /tmp/malicious-pack
# Step 2: trigger via repomix (git invokes /tmp/malicious-pack as the upload-pack helper)
repomix --remote git@github.com:yamadashy/repomix.git --remote-branch '--upload-pack=/tmp/malicious-pack'
# Step 3: confirm execution
cat /tmp/repomix-pwned.txt
# => uid=1000(kakashi) gid=1000(kakashi) ...The root cause is CWE-88: git fetch and git checkout both support --upload-pack, which instructs git to invoke an arbitrary binary as the transport helper. Because execFileAsync prevents shell word-splitting, classic command injection is blocked, but argument injection is not.
Passing --upload-pack=/tmp/malicious-pack as the branch name causes git to exec the payload before any protocol-level validation occurs. The fix in 1.14.1 inserts the -- end-of-options sentinel immediately before the remoteBranch value in every affected git subprocess call (fetch and checkout), so the string is always treated as a ref name regardless of its contents.
A ref-format validation step was also added as defense in depth.
The fix
Upgrade repomix to version 1.14.1 or later (npm install -g repomix@latest). The patch inserts --end-of-options before the user-supplied branch ref in both the git fetch and git checkout subprocess calls, and adds ref-format validation to reject values that begin with -- or otherwise fail git's ref-name rules.
Reported by Abhijith S (@kakashi-kx).
Related research
- high · 7.5CVE-2026-48815CVE-2026-48815: sigstore certificateOIDs Verification Constraint Silently Dropped
- high · 7.4CVE-2026-49857CVE-2026-49857: auth-fetch-mcp SSRF Protection Bypass via IPv4-mapped IPv6 Loopback
- highCVE-2026-49864CVE-2026-49864: wetty DOM XSS via File-Download Filename
- high · 8.8CVE-2026-49473CVE-2026-49473: @cedar-policy/authorization-for-expressjs Authorization Bypass via Query String