Michael Clark, Sysdig’s Senior Director of Threat Research, summarized it in nine words: “No password. No token. One header.”
He was describing CVE-2026-20896, a vulnerability in Gitea’s official Docker image that allows anyone on the internet to claim administrator access to your self-hosted Git server by sending a single HTTP header. No exploit chain required. No credential theft. No memory corruption. Just one header, and you’re in.
As of mid-July 2026, the flaw is being actively probed by automated scanners operating through ProtonVPN. If you’re running Gitea in Docker and haven’t explicitly hardened your configuration, you need to act now.
The vulnerability carries the identifier CVE-2026-20896 and affects all Gitea Docker images released before the July 2026 patch cycle. The issue was originally reported through Gitea’s responsible disclosure program and received a CVSS score of 9.8 — Critical. That’s the same severity tier as remote code execution, and for good reason: unrestricted admin access to a Git server gives an attacker control over source code, CI/CD configurations, deployment scripts, and any secrets embedded in repositories. For many self-hosted organizations, Gitea sits at the center of their development infrastructure. Compromising it compromises everything downstream.
What Makes This Vulnerability Dangerous
The vulnerability isn’t in Gitea’s code. It’s in the Docker image’s default configuration.
Gitea supports reverse proxy authentication — a feature that lets you delegate user authentication to an external proxy like NGINX or Traefik. When enabled via the setting ENABLE_REVERSE_PROXY_AUTHENTICATION = true, Gitea trusts the X-WEBAUTH-USER header to identify the authenticated user. This is a legitimate feature used by organizations that want centralized SSO through a reverse proxy.
The problem is in what Gitea trusts as a valid proxy source. In a properly configured deployment, the REVERSE_PROXY_TRUSTED_PROXIES setting should be restricted to local addresses:
REVERSE_PROXY_TRUSTED_PROXIES = 127.0.0.0/8,::1/128
This tells Gitea: “Only trust the X-WEBAUTH-USER header if it comes from localhost.” Any external request with that header gets ignored.
The Gitea Docker image ships with a different default:
REVERSE_PROXY_TRUSTED_PROXIES = *
That wildcard tells Gitea to trust the X-WEBAUTH-USER header from any IP address on the planet. Combined with reverse proxy authentication enabled, any HTTP client that can reach your container’s port can claim to be whoever it wants — including admin.
To be clear: the vulnerability requires that an administrator explicitly set ENABLE_REVERSE_PROXY_AUTHENTICATION = true. The dangerous Docker default doesn’t create the vulnerability on its own. But it removes the safety net. Most administrators who enable this feature do so believing the proxy trust model will protect them. The Docker image default silently breaks that assumption.
Is Your Deployment Affected?
Not every Gitea Docker instance running an unpatched image is exploitable. You’re only vulnerable if both conditions are true:
- You’ve set
ENABLE_REVERSE_PROXY_AUTHENTICATION = truein your Gitea configuration - You’re running a Gitea Docker image with the wildcard
REVERSE_PROXY_TRUSTED_PROXIES = *default
To check your configuration, inspect your Gitea app.ini file inside the container:
docker exec <container_name> cat /data/gitea/conf/app.ini | grep -A2 -E "ENABLE_REVERSE_PROXY|TRUSTED_PROXIES"
Look for these two settings. If you see both ENABLE_REVERSE_PROXY_AUTHENTICATION = true and either REVERSE_PROXY_TRUSTED_PROXIES = * or no explicit REVERSE_PROXY_TRUSTED_PROXIES line at all, you’re affected.
You can also test externally by sending a request with the spoofed header:
curl -H "X-WEBAUTH-USER: admin" https://your-gitea-instance.com/
If you get a response that suggests you’re authenticated as admin, the vulnerability is active. Do not run this test against a production system unless you understand the implications — you’re essentially testing whether an attacker can gain admin access, and logging that attempt may itself be a compliance concern.
The Fix
The fix takes five minutes. Three options, ordered by security preference:
Option 1: Update the Docker Image (Recommended)
Gitea has released patched Docker images that change the default REVERSE_PROXY_TRUSTED_PROXIES to the safe local-only value. Pull the latest:
docker pull gitea/gitea:latest
docker-compose down && docker-compose up -d
Check the release notes for your version to confirm the fix is included. The patched default is 127.0.0.0/8,::1/128.
Option 2: Override the Trusted Proxies Setting
If you can’t update immediately — and you should — override the dangerous default by mounting a custom configuration. Add this to your app.ini:
[security]
REVERSE_PROXY_TRUSTED_PROXIES = 127.0.0.0/8,::1/128
If you have a legitimate reverse proxy on a different host in your network, add its IP:
REVERSE_PROXY_TRUSTED_PROXIES = 127.0.0.0/8,::1/128,192.168.1.100/32
The key is that the list should be explicit, not a wildcard. Every IP in this list is an IP that can spoof any user identity on your Gitea instance. Treat it accordingly.
Option 3: Disable Reverse Proxy Authentication
If you’re not actually using reverse proxy authentication, disable it:
ENABLE_REVERSE_PROXY_AUTHENTICATION = false
This eliminates the attack surface entirely, regardless of the trusted proxies setting.
The Broader Lesson: Docker Image Defaults Are Not Your Friends
CVE-2026-20896 isn’t the first vulnerability caused by a Docker image shipping with insecure defaults, and it won’t be the last. The pattern is consistent: a piece of software has sensible defaults when installed natively, but the Docker image maintainer — often a third party, not the original project — changes those defaults to make the container “just work” in common deployment scenarios, inadvertently creating security holes.
This isn’t a Gitea problem. It’s a Docker ecosystem problem. When you run docker pull and docker run, you’re not just getting someone else’s code. You’re getting someone else’s configuration decisions, and those decisions might be optimized for convenience rather than security.
Think about what happens when a developer wants to try Gitea. They find the Docker Hub page, see the quick-start command, copy-paste it, and five minutes later they have a working Git server. That’s the Docker promise, and it’s genuinely valuable. But the quick-start command doesn’t include a security audit. It doesn’t inspect the default configuration. It doesn’t verify that the trusted proxies setting is locked down. The developer got convenience. The attacker got an admin account.
This dynamic plays out across the entire Docker ecosystem. MySQL images ship with empty root passwords in development configurations. Redis images bind to all interfaces by default. MongoDB images used to ship without authentication enabled. Each of these decisions was made by someone optimizing for “it works out of the box,” and each has been exploited at scale. CVE-2026-20896 is the latest entry in a long-running series, not an isolated incident.
The fix for any individual vulnerability is a configuration change or an image update. The fix for the pattern is a posture shift: treat every Docker image’s default configuration as suspect until you’ve personally verified it. The five extra minutes you spend inspecting an image’s defaults before deploying it will save you the hours or days you’d spend cleaning up after a compromise.
The NadMesh botnet, currently sweeping the internet for exposed Docker and AI services, has Gitea instances on its target list. Botnet operators know that default configurations are common and exploitation is easy. The gap between “vulnerability disclosed” and “actively exploited” continues to shrink — in this case, Sysdig observed automated reconnaissance within days of the CVE publication.
This isn’t a theoretical concern. Censys reported in May 2026 that exposed Docker APIs and containerized services were already being farmed for GPU mining, Monero mining, and proxy node resale. NadMesh represents an escalation: the April operators wanted compute resources. NadMesh wants what those compromised containers can authenticate to — cloud keys, Kubernetes tokens, internal services. A single Gitea instance with source code access can be the pivot point that turns a container compromise into a full infrastructure breach.
How to Audit Your Docker Images for Dangerous Defaults
CVE-2026-20896 is a specific vulnerability with a specific fix, but the underlying problem demands a broader response. Here’s a practical workflow for auditing the Docker images you’re already running:
First, list all running containers and their images:
docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}"
For each image, check whether it ships with configuration files that override upstream defaults. The Docker Hub page or GitHub repository for the image should document any configuration changes. If the documentation doesn’t explicitly list the defaults, assume they’ve been modified and verify:
docker run --rm <image> cat /path/to/config/file
Common configuration locations include /etc/<app>/, /data/<app>/conf/, and /opt/<app>/config/. For Gitea specifically, the relevant file is /data/gitea/conf/app.ini.
Second, audit which of your containers expose ports to anything other than localhost. A container bound to 127.0.0.1:3000:3000 is only accessible from the host. A container bound to 0.0.0.0:3000:3000 or simply 3000:3000 is accessible from any network interface:
docker ps --format "table {{.Names}}\t{{.Ports}}"
If you see ports bound to 0.0.0.0 that don’t need to be, your Docker Compose file or run command needs updating.
Third, implement a mandatory review step for any new Docker image before it reaches production. The five-minute check — pull the image, inspect its default config, verify its port bindings — catches the majority of insecure defaults before they become incidents.
Post-Remediation: What Else Should You Check?
If you found your Gitea instance was configured with the wildcard trusted proxies and reverse proxy auth enabled, assume that automated scanners may have probed your instance. Check your Gitea access logs for requests containing the X-WEBAUTH-USER header:
docker exec <container_name> cat /data/gitea/log/gitea.log | grep "X-WEBAUTH-USER"
Review the Gitea admin panel for any unrecognized users, repository creations, or configuration changes. Pay special attention to webhook configurations — a common post-compromise move is to add a webhook that exfiltrates code on every push. Check:
docker exec <container_name> gitea admin auth list
docker exec <container_name> gitea admin user list
If you find evidence of unauthorized access, rotate all credentials stored in the affected repositories immediately. This includes SSH keys, API tokens, database connection strings, cloud provider secrets, and CI/CD pipeline credentials. A Gitea instance with source code access is a pivot point for supply chain attacks. The attacker doesn’t need to steal data to cause damage — modifying a deployment script, a Dockerfile, or a CI pipeline configuration can be enough to inject malicious code into your production deployments.
Summary Checklist
- Check if
ENABLE_REVERSE_PROXY_AUTHENTICATION = truein your Gitea config - Verify
REVERSE_PROXY_TRUSTED_PROXIESis not set to* - Update Gitea Docker image to latest patched version
- Set
REVERSE_PROXY_TRUSTED_PROXIESto explicit IP list - Audit Gitea access logs for
X-WEBAUTH-USERprobes - Review admin panel for unauthorized users or changes
- Rotate all credentials if compromise suspected
- Repeat this audit process for every Docker image in your stack
Gitea is one of the most popular self-hosted Git platforms with over 100,000 Docker Hub pulls per week. If even 5% of those deployments have reverse proxy authentication enabled with the wildcard default, that’s thousands of instances currently accepting admin credentials from any IP on the internet. Check yours now.