Intelligence
highVulnerabilityActive

Gitea Token Scope Bypass: Public-Only Restrictions Not Enforced on Private PR Head Repositories

A scope-validation bypass in Gitea allows attackers with public-only repository tokens to write to private pull request head branches via the public base repository API route. This circumvents intended token restrictions and enables unauthorized repository modifications.

S
Sebastion

CVE References

Affected

Gitea/Gitea

Vulnerability Description

This is an authorization scope-enforcement vulnerability stemming from inconsistent token restriction validation across repository contexts. Gitea's token model includes a public-only flag that should restrict API operations to public repositories. However, the PR update endpoint (POST /api/v1/repos/{public-owner}/{public-repo}/pulls/{index}/update) validates the public-only restriction only against the base repository (which is public), but then proceeds to update the head repository without re-validating the token's scope restrictions. If the head repository is private, the token bypass succeeds because the authorization check uses standard RBAC against the user account rather than re-enforcing the token's public-only constraint.

Root Cause & Impact

The root cause is a context-switch vulnerability: scope restrictions are enforced at the route layer (ctx.Repo.Repository = base repo), but the business logic (UpdatePullRequest()) operates across two repositories without re-validating token constraints for secondary contexts. An attacker with a leaked or intentionally-scoped public-only token can exploit cross-repository operations to inject commits into private repositories, compromising repository integrity and enabling supply-chain attacks.

Detection Guidance

Log Indicators:

  • POST /api/v1/repos/*/pulls/*/update requests from tokens with public_only=true scope followed by write operations to private repositories
  • Token activity logs showing public-only tokens performing write operations outside public repos
  • PR update operations where base repo is public but head repo is private

Audit Checks:

  • Monitor API audit logs for mismatches between token scope and repository visibility
  • Correlate token creation scope with actual repository write operations
  • Flag any public-only token with write activity against private repositories

Mitigation Steps

  1. Immediate: Update Gitea to a patched version (check official advisories for version number)
  2. Workaround: Restrict token issuance—avoid granting write:repository scopes with public_only flag to untrusted principals
  3. Configuration: Review existing public-only tokens with write access; audit their activity logs
  4. Code-level fix: Re-validate token scope restrictions in UpdatePullRequest() before operating on the head repository; enforce scope checks at both repository contexts, not just the route layer

Risk Assessment

Likelihood: Medium-High — The vulnerability requires a legitimate but scoped token (public-only + write access), which is a realistic configuration for CI/CD or bot workflows. Attackers with insider access or leaked tokens can exploit this reliably.

Threat Actor Interest: High — This enables supply-chain compromise if exploited against CI/CD systems with scoped bot tokens. DevOps/security teams often create public-only tokens to limit blast radius, making this a high-value target for post-compromise privilege escalation.