Skip to main content

Gitea CVE-2026-58416

MEDIUM
Improper Handling of Insufficient Permissions or Privileges (CWE-280)
2026-07-21 https://github.com/go-gitea/gitea GHSA-fj8v-hjwv-qm88
6.3
CVSS 3.1 · GitHub Advisory
Share

Severity by source

GitHub Advisory PRIMARY
6.3 MEDIUM
AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:N/A:N
vuln.today AI
6.3 MEDIUM

Network vector via git-HTTP; AC:H for three simultaneous prerequisites; PR:L for fork contributor access; S:C and C:H for cross-repo private source disclosure; no integrity or availability impact.

3.1 AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:N/A:N
4.0 AV:N/AC:H/AT:P/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N

Primary rating from GitHub Advisory.

CVSS VectorGitHub Advisory

CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:N/A:N
Attack Vector
Network
Attack Complexity
High
Privileges Required
Low
User Interaction
None
Scope
Changed
Confidentiality
High
Integrity
None
Availability
None

Lifecycle Timeline

2
Source Code Evidence Fetched
Jul 21, 2026 - 21:18 vuln.today
Analysis Generated
Jul 21, 2026 - 21:18 vuln.today

DescriptionGitHub Advisory

Summary

GetActionsUserRepoPermission (models/perm/access/repo_permission.go) decides whether an Actions task token may access a target repo. Its cross-repo branches each enforce a fork-PR discriminator - except the collaborative-owner branch, which is missing the !task.IsForkPullRequest guard that its sibling has. As a result, when a private repo B lists owner A as a collaborative owner, an attacker-controlled fork pull-request workflow whose base repo is owned by A is granted code-read on B - i.e. the fork's YAML can clone a third private repository it has no rights to.

Details

go
// models/perm/access/repo_permission.go (v1.26.2), in GetActionsUserRepoPermission
if checkSameOwnerCrossRepoAccess(ctx, taskRepo, repo, task.IsForkPullRequest) { // passes isForkPR -> denies forks
    return maxPerm, nil
}
...
if taskRepo.IsPrivate {                                   // <-- NO IsForkPullRequest check here
    actionsUnit := repo.MustGetUnit(ctx, unit.TypeActions)
    if actionsUnit.ActionsConfig().IsCollaborativeOwner(taskRepo.OwnerID) {
        return maxPerm, nil                              // grants code-read to target repo B
    }
}

The sibling same-owner path correctly denies fork PRs:

go
func checkSameOwnerCrossRepoAccess(ctx, taskRepo, targetRepo, isForkPR bool) bool {
    if isForkPR {
        return false // Fork PRs are never allowed cross-repo access to other private repositories.
    }
    ...
}

taskRepo = the repo whose workflow is running (the PR's base repo A); repo = the target being cloned (B). IsCollaborativeOwner(taskRepo.OwnerID) asks "does target B's Actions config trust A's owner for cross-repo read?" When B trusts ownerA, the branch returns maxPerm (code-read) even when task.IsForkPullRequest is true - i.e. when the executing YAML is the fork's, not A's.

Every sibling enforces the fork-PR discriminator; except for this branch: checkSameOwnerCrossRepoAccess denies forks; ComputeTaskTokenPermissions (models/actions/token_permissions.go) only clamps the token *ceiling* to read-only for fork/cross-repo (its own comment notes the access *decision* is in GetActionsUserRepoPermission, so it does not neutralize the gap - it just makes the leak read-only); secrets (models/secret/secret.go) and the approval gate (services/actions/notifier_helper.go) both correctly key on IsForkPullRequest.

Reachability - the runner clones target repo B over git-HTTP with the task token: routers/web/repo/githttp.goGetDoerRepoPermission(ctx, repoB, ActionsUser)GetActionsUserRepoPermission(ctx, repoB, actionsUser, taskID) with IsForkPullRequest == true → collaborative-owner branch returns code-read → p.CanAccess(Read, code) passes → private clone of B succeeds. (CheckRepoScopedToken in githttp is a no-op for the Actions token.)

PoC

Setup: private base repo A (usera/repoA), private third repo B (userb/repoB) with a planted SECRET.txt, B's Actions config trusting usera as a collaborative owner, and a genuine running fork-PR task token (token_hash computed with Gitea's own HashToken) presented as HTTP Basic. Requesting GET /userb/repoB.git/info/refs?service=git-upload-pack:

Condition (same fork-PR token)HTTPMeaning
anonymous (no token)401auth required
token, A public, B trusts A404branch gated on taskRepo.IsPrivate ⇒ A public skips it
token, A private, B has no collab-owner config404no trust ⇒ denied
token, A private, B trusts A (collab-owner)200git clone of private B succeeds
config removed / restored404 / 200deterministic

In the 200 case, git clone of private repo B succeeded and yielded its SECRET.txt - the full source of a third private repo the fork-PR author has no rights to.

Impact

Read-only confidentiality breach: discloses the full source of a *third* private repository (B) to an untrusted external fork-PR author. Read-only, not write/RCE.

Preconditions (honest):

  1. B is deliberately configured with a collaborative owner - but that is exactly the feature's intended

use, so realistic for any deployment using it.

  1. The fork PR's base repo A is itself private (the branch is gated on taskRepo.IsPrivate). Forking a

private A already requires read on A, so this is a normal internal-contributor situation, not a weakening - the escalation is "read A (granted) → read a *different* private repo B (never granted)."

  1. The fork-PR workflow must actually run - most realistically via an attacker who had one earlier PR

approved (the "approved before" path in ifNeedApproval), after which fork PRs auto-run.

Suggested remediation

Add the same fork-PR guard the sibling path has (one line):

go
if taskRepo.IsPrivate && !task.IsForkPullRequest {
    actionsUnit := repo.MustGetUnit(ctx, unit.TypeActions)
    if actionsUnit.ActionsConfig().IsCollaborativeOwner(taskRepo.OwnerID) {
        return maxPerm, nil
    }
}

This flips Vuln_ForkPR_LeaksThirdPrivateRepo to PASS, keeps Control_NonFork_Allowed PASS (legitimate collaborative-owner sharing still works), and leaves the existing TestGetActionsUserRepoPermission suite all green.

AnalysisAI

Gitea's Actions permission system (v1.26.2 and earlier) exposes full source code of third private repositories to untrusted fork-PR authors due to a missing fork-PR guard in the collaborative-owner permission branch of GetActionsUserRepoPermission. When a private target repo B configures a collaborative owner pointing to org/user A, an attacker with read access to any private repo under A can submit a fork PR, trigger the Actions workflow, and clone repo B's source code without authorization. …

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

Recon
Fork private repo A with contributor read access
Delivery
Submit one PR to A and get it approved for auto-run
Exploit
Craft workflow YAML targeting repo B clone via task token
Install
Submit new fork PR to trigger Gitea Actions workflow
C2
Missing IsForkPullRequest guard grants code-read on B via collaborative-owner branch
Execute
Git-HTTP clone of private repo B succeeds
Impact
Full source code of repo B exfiltrated

Vulnerability AssessmentAI

Exploitation Exploitation requires three simultaneous conditions to align: (1) the target private repo B must have the Gitea Actions collaborative-owner feature explicitly configured to trust A's owner - this is an opt-in configuration set in B's Actions unit config via IsCollaborativeOwner, not a default, but is the intended normal use of the feature; (2) the fork-PR's base repo A must itself be private, because the vulnerable branch is gated on taskRepo.IsPrivate - if A is public, this code path is not reached and exploitation is blocked; (3) the attacker's fork-PR workflow must auto-run, which requires having had at least one prior PR approved on repo A (via the 'approved before' path in ifNeedApproval in services/actions/notifier_helper.go). … Additional conditions and limiting factors are described in the full assessment.
Risk Assessment The vendor-assigned CVSS score of 6.3 (CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:N/A:N) accurately reflects the multi-condition exploitation path (AC:H) and high confidentiality impact across a changed scope (S:C/C:H). … Full risk analysis with EPSS, KEV, and SSVC signal comparison available after sign-in.
Exploit Scenario An attacker with read access to a private repo under org A forks it, submits one PR that gets approved (enabling future fork-PR auto-runs), then crafts a workflow YAML file that executes git clone against private repo B using the Actions task token provided at runtime. When the next fork PR triggers the workflow, GetActionsUserRepoPermission incorrectly grants code-read on repo B - because the collaborative-owner branch lacks the IsForkPullRequest check - and the full private source of repo B is cloned and accessible to the attacker. …
Remediation Upgrade to Gitea v1.27.0, which contains the one-line fix adding the missing fork-PR guard (commit 1d43b736b5a16c5f80cfdcd9a9448a9c983ddaa0, PR #38214: https://github.com/go-gitea/gitea/pull/38214). … Detailed patch versions, workarounds, and compensating controls in full report.

Threat intelligence, references, and detailed analysis are available after sign-in.

More in Gitea

View all
CVE-2026-27771 HIGH POC
8.2 Jul 03

Broken access control in Gitea's Composer package registry (versions up to and including 1.26.1) lets remote attackers r

CVE-2022-30781 HIGH POC
7.5 May 16

Gitea before 1.16.7 does not escape git fetch remote. Rated high severity (CVSS 7.5), this vulnerability is remotely exp

CVE-2020-14144 HIGH POC
7.2 Oct 16

The git hook feature in Gitea 1.1.0 through 1.12.5 might allow for authenticated remote code execution in customer envir

CVE-2024-6886 CRITICAL POC
10.0 Aug 06

Improper Neutralization of Input During Web Page Generation (XSS or 'Cross-site Scripting') vulnerability in Gitea Gitea

CVE-2026-58053 CRITICAL POC
9.4 Jun 28

Container escape in Gitea act_runner (Docker backend, through act 0.262.0) lets an authenticated user with workflow-exec

CVE-2019-11229 HIGH POC
8.8 Apr 15

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

CVE-2020-13246 HIGH POC
7.5 May 20

An issue was discovered in Gitea through 1.11.5. Rated high severity (CVSS 7.5), this vulnerability is remotely exploita

CVE-2022-0905 HIGH POC
7.1 Mar 10

Missing Authorization in GitHub repository go-gitea/gitea prior to 1.16.4. Rated high severity (CVSS 7.1), this vulnerab

CVE-2022-1058 MEDIUM POC
6.1 Mar 24

Open Redirect on login in GitHub repository go-gitea/gitea prior to 1.16.5. Rated medium severity (CVSS 6.1), this vulne

CVE-2026-20896 CRITICAL POC
9.8 Jul 03

Reverse-proxy authentication bypass in the official Gitea Docker image (versions up to and including 1.26.2) allows any

CVE-2026-27780 CRITICAL
9.8 Jul 03

Branch-protection bypass in Gitea's self-hosted Git server (all versions before 1.26.0) allows a user with push access t

CVE-2026-26292 CRITICAL
9.8 Jul 03

Migration transport protections in Gitea are bypassed for Git LFS operations, affecting all self-hosted instances before

Share

CVE-2026-58416 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy