Skip to main content
Vulnerability Database/CVE-2026-96594

CVE-2026-96594: Gitea API XSS Vulnerability

CVE-2026-96594 is a cross-site scripting flaw in Gitea API that allows attackers to execute malicious JavaScript in victim sessions. This post explains its impact, affected versions, and mitigation steps.

Published:

CVE-2026-96594 Overview

CVE-2026-96594 is a stored cross-site scripting (XSS) vulnerability in Gitea, the self-hosted Git service written in Go. The flaw exists in the media API endpoint GET /api/v1/repos/{owner}/{repo}/media/{filepath}. For files up to 1 KiB stored directly in Git (not in Git LFS), the endpoint returned responses without the content type and content disposition headers Gitea normally applies to user-supplied content. An HTML file committed to a repository was rendered by the browser on the Gitea origin, allowing JavaScript execution within a victim's authenticated session. The weakness is tracked under CWE-79.

Critical Impact

Any user with push access to a repository can execute arbitrary JavaScript in a victim's session on the Gitea origin and act with the victim's privileges.

Affected Products

  • Gitea self-hosted Git service
  • Gitea versions prior to v28.1.0
  • Deployments exposing the /api/v1/repos/{owner}/{repo}/media/{filepath} endpoint

Discovery Timeline

  • 2026-10-06 - CVE-2026-96594 published to NVD
  • 2026-10-07 - Last updated in NVD database
  • Gitea release v28.1.0 - Fix shipped via pull requests #39501 and #39507

Technical Details for CVE-2026-96594

Vulnerability Analysis

The Gitea media API endpoint serves raw repository content to authenticated users. For user-controlled content, Gitea normally sets a safe Content-Type and a Content-Disposition: attachment header so browsers download the file instead of rendering it on the Gitea origin. These protections were missing for small files stored directly in Git when they were below the 1 KiB threshold used to decide the response path. A browser receiving an HTML payload without those headers interprets the response as text/html and executes any inline or referenced JavaScript. Because the response originates from the Gitea domain, the attacker's script runs with the victim's session cookies and CSRF context, enabling actions against the Gitea API as that victim.

Root Cause

The root cause is a missing output-encoding and header-hardening path for a specific code branch. The media endpoint had two code paths: one for files stored in Git LFS and one for small files stored directly in Git. The non-LFS branch for files under 1 KiB did not emit the Content-Type override and Content-Disposition: attachment header applied elsewhere, leaving the content type to be inferred by the browser.

Attack Vector

An attacker needs push access to any repository the victim will visit via the media URL. The attacker commits a crafted HTML file smaller than 1 KiB. The attacker then convinces a victim to open the media URL for that file. The browser renders the HTML on the Gitea origin and executes the attacker's JavaScript. The script can call the Gitea API, modify repositories, change account settings, or exfiltrate data within the victim's permission set.

No verified public exploit code is available. See the GitHub Security Advisory GHSA-94rx-fqm6-q23v for upstream technical details.

Detection Methods for CVE-2026-96594

Indicators of Compromise

  • Commits that add small HTML, SVG, or XML files under 1 KiB containing <script> tags or inline event handlers
  • HTTP responses from /api/v1/repos/*/media/* lacking Content-Disposition: attachment or returning Content-Type: text/html
  • Unexpected API calls from user sessions immediately after a victim opened a media URL

Detection Strategies

  • Inspect reverse proxy and Gitea access logs for GET /api/v1/repos/*/media/* requests that returned HTML content types
  • Review repository histories for recently added small files with executable markup or obfuscated JavaScript
  • Correlate media URL access events with subsequent privileged API actions by the same session

Monitoring Recommendations

  • Alert on repository pushes that introduce HTML or SVG files to paths not previously containing them
  • Monitor for anomalous spikes in /api/v1/repos/*/media/* traffic preceded by sharing of raw media links in issues or pull requests
  • Forward Gitea audit logs to a centralized data lake for retention and correlation with endpoint telemetry

How to Mitigate CVE-2026-96594

Immediate Actions Required

  • Upgrade Gitea to v28.1.0 or later
  • Audit repositories for recently committed HTML, SVG, or XML files under 1 KiB and remove any unexpected content
  • Rotate session tokens and API keys for any user who may have opened a suspicious media URL
  • Restrict push access to trusted contributors on sensitive repositories

Patch Information

The fix shipped in Gitea v28.1.0. The patch adds the correct Content-Type and Content-Disposition headers to the small-file, non-LFS branch of the media API handler. Details are available in GitHub PR #39501, GitHub PR #39507, and the Gitea v28.1.0 release notes.

Workarounds

  • Place Gitea behind a reverse proxy that forces Content-Disposition: attachment and a safe Content-Type on /api/v1/repos/*/media/* responses
  • Serve user-generated content from a separate origin or subdomain isolated from the Gitea session cookie scope
  • Enforce a strict Content-Security-Policy that disallows inline script execution on the Gitea origin
  • Limit push permissions on shared repositories until the upgrade is deployed
bash
# Example nginx override to force attachment disposition on the media endpoint
location ~ ^/api/v1/repos/.+/media/.+$ {
    proxy_pass http://gitea_backend;
    proxy_hide_header Content-Disposition;
    proxy_hide_header Content-Type;
    add_header Content-Disposition "attachment" always;
    add_header Content-Type "application/octet-stream" always;
    add_header X-Content-Type-Options "nosniff" always;
}

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.