Skip to content

Gitea AddReleaseAttachments missing IssueID check allows issue attachment metadata exposure and deletion via releases

Moderate
bircni published GHSA-cwq7-782w-pxcc Oct 18, 2026

Package

gomod gitea.dev (Go)

Affected versions

<= 28.1.0

Patched versions

28.2.0

Description

Summary

Gitea's AddReleaseAttachments function accepts attachment UUIDs without verifying that each attachment is not already linked to an issue. An authenticated user with release write permission can re-link an issue-bound attachment to a release they control, exposing attachment metadata (filename, size, download count) through the release page and API, and enabling permanent deletion or renaming of the targeted issue attachment.

Root Cause

The CVE-2026-57886 fix introduced validateAttachmentForIssue to reject attachments already linked to another issue or to a release. This validation is applied to UpdateIssueAttachments and UpdateCommentAttachments, but the release counterpart AddReleaseAttachments was not updated with a symmetric IssueID check.

Affected function: AddReleaseAttachments
Location: models/repo/release.go (line 181)

The function checks:
  - attachments[i].RepoID != rel.RepoID  (rejects cross-repo)
  - attachments[i].ReleaseID != 0        (rejects already-linked-to-release)

Missing check:
  - attachments[i].IssueID != 0          (does NOT reject already-linked-to-issue)

Compare with validateAttachmentForIssue (models/issues/issue_update.go:269):
  - attachment.RepoID != issue.RepoID     (rejects cross-repo)
  - attachment.IssueID != 0 && ...        (rejects already-linked-to-another-issue)
  - attachment.ReleaseID != 0             (rejects already-linked-to-release)

Impact

An authenticated attacker with write access to the Releases unit in a repository can target any issue attachment in the same repository whose UUID is known. Gitea's unit-level team permissions support granting release write without issue access; this is a non-default but supported configuration. The attack requires knowledge of a target attachment UUID, which may leak through notification emails, webhook payloads, RSS/Atom feeds, browser history, or Markdown content viewed before permission changes. UUID enumeration is infeasible (v4, 128-bit random).

After re-linking, the attacker can:

  • Disclose metadata: The attachment's filename, UUID, size, and download count appear in the release's attachment list (web page and API endpoint GET /api/v1/repos/{owner}/{repo}/releases/{id}/assets). Filenames may contain sensitive information.
  • Rename the attachment: The release edit interface allows changing the attachment's display name.
  • Permanently delete the attachment: The release edit interface can remove the attachment, deleting both the database record and the physical file from storage. The re-link and deletion can occur in a single HTTP request.

File content download is independently protected: GetAttachmentLinkedTypeAndRepoID checks IssueID before ReleaseID, so the download handler verifies issue-level read permission on the original repository. An attacker without issue read access cannot download the file content.

Affected Versions

  • Ecosystem: Go
  • Package: code.gitea.io/gitea
  • Confirmed affected range: <= 1.27.3
  • Latest release checked: v1.27.3 (GitHub Releases, published 2026-08-29)
  • Fix status: not fixed in any published version

The AddReleaseAttachments function has contained the same validation gap since before the CVE-2026-57886 fix was applied. The introduction boundary predates the available git history and cannot be precisely determined. The current go.mod module path is gitea.dev, but the established advisory package coordinate is code.gitea.io/gitea.

Suggested Fix

Add an IssueID check to AddReleaseAttachments in models/repo/release.go, symmetric with the existing ReleaseID check in validateAttachmentForIssue. Specifically, after the existing ReleaseID != 0 check, reject any attachment where IssueID != 0:

if attachments[i].IssueID != 0 {
    return util.NewPermissionDeniedErrorf("attachment is already linked to an issue")
}

This prevents issue-bound attachments from being re-linked to releases. The same check should be added to any future attachment linking function. Consider also verifying that the attachment was uploaded by the current user or belongs to the current session.

No interim mitigation is available beyond restricting the Releases write permission to users who also hold issue access in the same repository.


Reported by zx (GitHub: @manus-pi).

Severity

Moderate

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
Low
Privileges required
Low
User interaction
None
Scope
Unchanged
Confidentiality
Low
Integrity
Low
Availability
Low

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L

CVE ID

CVE-2026-110494

Weaknesses

Authorization Bypass Through User-Controlled Key

The system's authorization functionality does not prevent one user from gaining access to another user's data or record by modifying the key value identifying the data. Learn more on MITRE.

Credits