Home/ Blog/ Security news/ Article
Blog · Security news

Gitea's Docker image trusts a login header from anyone, and probing has started

A default in Gitea's Docker image trusts the X-WEBAUTH-USER header from any IP, so anyone can log in as any user. Fixed in 1.26.3, and attackers are already

Open reinforced doorway standing alone on a plain with no walls beside it

The dangerous line is not in Gitea's code. It sits in the default configuration its official Docker image ships with. That image sets REVERSE_PROXY_TRUSTED_PROXIES to a wildcard, so the moment an operator turns on reverse-proxy login, the server will believe an identity header sent from any address that can reach it. Researchers reported the first attempt against this in the wild this week, 13 days after the flaw went public, and that gap is the reason to move now rather than at the next maintenance window.

The bug is tracked as CVE-2026-20896, rated 9.8, and credited to researcher Ali Mustafa. It affects Gitea's Docker images through 1.26.2 and is fixed in 1.26.3, released in late June. If you run the container and never enabled reverse-proxy authentication, this specific default does not expose you. Everyone who did enable it is a candidate for full account takeover, and admins are the obvious target.

How does a login header become a full authentication bypass?

Gitea can accept an already-authenticated username from a trusted front-end through the X-WEBAUTH-USER header. It is supposed to trust that header only when the request comes from the proxy in front of it. The Docker image trusts it from every source IP, so any caller who reaches the port directly can name any account and be logged in as that user, no password and no token required.

What makes this a shipped bug rather than an operator mistake is where the two defaults disagree. Gitea's documented sample config restricts the trusted range to loopback. The container image overrides that with a wildcard, and most operators never notice the difference until someone points it out.

SettingDocumented defaultOfficial Docker image (through 1.26.2)
REVERSE_PROXY_TRUSTED_PROXIESloopback only (localhost)* (every source IP)
Who can set X-WEBAUTH-USERthe local reverse proxy onlyanything that reaches the container port
Effect with reverse-proxy auth onheader honored from the front-endlog in as any user, no password
Sources: GitHub Security Advisory GHSA-f75j-4cw6-rmx4; The Hacker News.

This is the same own-goal we keep writing up: a self-hosted tool that optimizes the five-minute quickstart at the cost of the default security posture. Crawl4AI shipped its server unlocked in exactly this shape, and LangSmith trusted a client-supplied header it should have ignored. The lesson for anyone running Gitea alongside other self-hosted infrastructure is to treat the container's shipped defaults as untrusted, not as a hardened baseline.

Are you behind the proxy, or just standing next to it?

The quiet assumption in every reverse-proxy auth setup is that the backend is only reachable through the proxy. Docker breaks that assumption more often than people expect. A docker-compose.yml that publishes port 3000 to the host, or a bridge network another container can route to, means the Gitea port is reachable without ever passing the authenticating front-end. The header trust then applies to that direct path too.

So the real exposure question is not whether you run a proxy in front of Gitea, but whether anything else can reach the Gitea port. If the answer is yes, the wildcard turns every reachable network into an authentication bypass. Self-hosted Git servers are a recurring soft target for this class of mistake: we saw it with GitLab's no-login session flaw and with Gogs trusting its logged-in users too far. A code-hosting server holds your source, your CI secrets, and often your deploy keys, which is why ranking this kind of exposure ahead of a routine CVE is the right call.

How would you know if someone already tried?

Patching closes the hole. It does not tell you whether the two-week window before you patched was clean. According to reporting from Sysdig relayed by The Hacker News, the first observed probe came from a commercial VPN exit and stayed in reconnaissance, which reads as opportunistic mass-scanning rather than a targeted operation. That pattern means anyone with an exposed Gitea instance is in scope, not just high-value targets.

The detection that matters here is simple to describe: an inbound request carrying X-WEBAUTH-USER that did not transit your authenticating proxy is illegitimate by definition. If your front-end is the only thing meant to set that header, then the same header arriving on the direct container port, or from any source that is not your proxy address, is a probe or an exploit attempt. Feeding your proxy and container access logs into a place you can query them together lets you answer whether anyone tried this instead of guessing. A managed detection layer over your own logs is meant to surface exactly that mismatch and explain it in plain language rather than leaving you to spot a header anomaly by eye.

Upgrade to 1.26.3, then stop trusting the header blindly

Move to Gitea 1.26.3 or later. The patched image drops the wildcard, so the header is trusted only from where you tell it to be, matching what the documentation always described. If you cannot upgrade immediately, the interim control is to set REVERSE_PROXY_TRUSTED_PROXIES to your proxy's address only, and to have that proxy strip any client-supplied X-WEBAUTH-USER on inbound so a request can never carry its own identity claim.

The durable takeaway is broader than one CVE. A backend should never trust an identity header unless the only path to that backend is through the component that sets it, and that component clears the client's copy first. That rule holds for Gitea, for oauth2-proxy fronting a dashboard, for any app that reads X-Forwarded-User. Where a header can arrive from more than one path, header-based auth is not authentication. It is a suggestion the server chose to believe.

Topics

Frequently asked questions

What is CVE-2026-20896 in Gitea?

It is an authentication bypass in Gitea's official Docker image, rated CVSS 9.8. The image trusts the X-WEBAUTH-USER header from any source IP, so with reverse-proxy authentication enabled a caller can log in as any user, including an admin, without a password.

Which Gitea versions are affected and fixed?

The Gitea Docker images through 1.26.2 carry the unsafe wildcard default. The issue is fixed in 1.26.3, released in late June 2026, which drops the wildcard so the header is trusted only from the address you set.

Am I exposed if I never enabled reverse-proxy authentication?

Not by this specific default. The bypass only triggers when reverse-proxy login is turned on. If you never enabled it, the trusted-proxy setting has no effect. Upgrading to 1.26.3 is still recommended so the safe default is in place if you enable it later.

Is CVE-2026-20896 being exploited?

Researchers reported the first in-the-wild probe about 13 days after public disclosure, according to Sysdig as relayed by The Hacker News. The activity was described as reconnaissance from a commercial VPN exit, which points to opportunistic scanning rather than a targeted attack.

How can I detect exploitation attempts before I patch?

Watch for the X-WEBAUTH-USER header arriving on a path that did not pass your authenticating proxy. If only your front-end is meant to set that header, then the same header on the direct container port, or from any address that is not your proxy, is a probe or an exploit attempt.

What is the interim workaround if I cannot upgrade?

Set REVERSE_PROXY_TRUSTED_PROXIES to your proxy's address only, not a wildcard, and configure the proxy to strip any client-supplied X-WEBAUTH-USER on inbound requests. That prevents a caller from supplying their own identity claim while you schedule the upgrade to 1.26.3.

Ready to meet the Guardians?

Deploys fast - agentless for monitoring and cloud, a lightweight agent for deep endpoint security. Just Suriq, standing watch.