A critical unauthenticated vulnerability in Gitea — the self-hosted Git service popular with developers, agencies, and small teams — allows an attacker with no account at all to read arbitrary files on the server, then chain that into full remote code execution. The flaw (CVE-2026-59774, GHSA-6v53-hr58-556r) lives in the repository markup rendering endpoint and was fixed in Gitea 1.27.1, released August 2, 2026. If your team runs a self-hosted Gitea instance and hasn’t updated it in the last few days, you are exposed.

What the Vulnerability Is

Gitea’s /markup endpoint — specifically POST /{owner}/{repo}/markup — accepts raw markup text and renders it as HTML. The endpoint does apply a basic repository check, but unauthenticated users can satisfy that check simply by targeting any public repository with the code unit enabled (the default for public repos). No login, no write access, no special permissions required.

The problem is the Org-mode renderer. When the rendering mode is set to file and the filename ends in .org, Gitea hands the content to the go-org library. In go-org 1.9.1, the library’s ReadFile callback defaults to ioutil.ReadFile — and Gitea 1.27.0 never restricts which paths that callback can reach.

Org-mode supports a #+INCLUDE directive that pulls in external files. An attacker crafts a POST body referencing an absolute path like /home/gitea/custom/conf/app.ini and the server reads and returns any file the Gitea process account can access. This is a textbook CWE-22 path traversal (Improper Limitation of a Pathname to a Restricted Directory).

Escalation to RCE. Reading app.ini exposes Gitea’s INTERNAL_TOKEN. With that token, an attacker can authenticate to Gitea’s internal API, inject a malicious Git hook via the internal logger endpoint, and trigger that hook by performing an anonymous clone of a repository. The hook runs as the Gitea service account on the host OS — arbitrary command execution, no credentials required at any step.

Why It Matters

Gitea is widely self-hosted on Linux servers, in Docker containers, and on VPS instances. A public-facing Gitea instance (port 3000 or proxied through NGINX) is fully exploitable by anyone on the internet who knows the address, without logging in.

The immediate risk is data theft: source code, .env files, SSH keys, deployment credentials, and anything else the Gitea process can read on the filesystem. The escalated risk is a complete server compromise via the Git hook injection chain.

No exploitation in the wild has been confirmed as of August 5, 2026, and the CVE is not yet on CISA’s Known Exploited Vulnerabilities catalog. But the vulnerability was publicly disclosed August 2 and received wide media coverage by August 5 — the window before opportunistic scanning begins is shrinking fast.

Am I Affected?

You are affected if all of the following are true:

  • You run a self-hosted Gitea instance (Gitea Cloud auto-upgraded)
  • Your version is anywhere in the range 1.22.1 – 1.27.0
  • You have at least one repository set to Public with the code unit enabled

To check your version, look at the footer of any Gitea page, or run gitea --version at the command line. If you are on 1.27.1 or later, you are patched. Private-only instances face lower immediate risk, but upgrading is still the right call.

What to Do About It: Step-by-Step

Step 1: Upgrade to Gitea 1.27.1

This is the only complete fix.

Binary install:

sudo systemctl stop gitea
wget -O /tmp/gitea https://dl.gitea.com/gitea/1.27.1/gitea-1.27.1-linux-amd64
# Verify sha256 checksum, then:
sudo cp /tmp/gitea /usr/local/bin/gitea
sudo chmod +x /usr/local/bin/gitea
sudo systemctl start gitea

Docker:

docker pull gitea/gitea:1.27.1
docker compose down && docker compose up -d

Confirm with gitea --version — output should say 1.27.1.

Step 2: Rotate Your INTERNAL_TOKEN

Even if you patch immediately, rotate the token if your instance was internet-accessible while vulnerable.

gitea generate secret INTERNAL_TOKEN

Paste the result into app.ini under [security], then restart Gitea.

Step 3: Audit Git Hooks for Tampering

find /home/gitea/repositories -name "pre-receive" -o -name "post-receive" -o -name "update" | xargs ls -la 2>/dev/null

Inspect any hooks with recent timestamps or unexpected content. The repository root path is set under [repository] ROOT in app.ini.

Step 4: Confirm Gitea Is Not Running as Root

id gitea   # should show a non-root UID
sudo -u gitea cat /etc/shadow   # should return: Permission denied

If Gitea runs as root, fix that regardless of this vulnerability.

Step 5: Check Access Logs for Exploitation Attempts

grep "POST.*markup" /var/log/nginx/access.log
grep -i "markup\|app.ini" /home/gitea/log/gitea.log

Unexpected POST requests to any */markup endpoint — especially those containing #+INCLUDE in the body — are red flags.

Quick-Win Checklist

  • ☐ Run gitea --version — confirm 1.27.1 or higher
  • ☐ If on 1.22.1–1.27.0: upgrade to 1.27.1 immediately (binary or Docker)
  • ☐ Rotate INTERNAL_TOKEN in app.ini and restart Gitea
  • ☐ Audit Git hooks across all repos for unexpected content
  • ☐ Verify Gitea is NOT running as root
  • ☐ Review access logs for POST requests to */markup endpoints
  • ☐ Consider temporarily blocking port 3000 at the firewall on unpatched public instances

Sources