CVE-2026-20896 Elastic Security · Elastic

Detect Gitea Docker REVERSE_PROXY_TRUSTED_PROXIES Wildcard Allows X-WEBAUTH-USER Auth Bypass (CVE-2026-20896) in Elastic Security

The official Gitea Docker image ships with REVERSE_PROXY_TRUSTED_PROXIES set to * by default. Because Gitea's reverse-proxy authentication feature trusts the X-WEBAUTH-USER header from any source claiming to be a trusted proxy, an unauthenticated attacker with direct network access to the Gitea HTTP listener (bypassing any intended reverse proxy) can set this header to impersonate any username, including admin accounts, and obtain a fully authenticated session without credentials. Affects code.gitea.io/gitea < 1.26.3. This detection identifies HTTP requests to Gitea that carry X-WEBAUTH-USER (or similar reverse-proxy auth headers) originating from IP addresses outside the expected reverse-proxy/load-balancer CIDR, as well as anomalous successful authentications tied to reverse-proxy auth with no corresponding upstream proxy log entry.

MITRE ATT&CK

Tactic
Initial Access Privilege Escalation Defense Evasion

Elastic Detection Query

Elastic Security (Elastic)
eql
any where event.dataset == "gitea.access" and http.request.headers.x_webauth_user != null and not cidrmatch(source.ip, "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16")
critical severity medium confidence

Identifies HTTP requests to Gitea containing the X-WEBAUTH-USER header from IPs not within trusted internal proxy ranges.

Data Sources

Gitea access logs via Filebeat/Elastic AgentReverse proxy logs

Required Tables

logs-gitea.access-*

False Positives & Tuning

  • Untracked proxy/CDN IP added after last CIDR baseline update
  • NAT gateway obscuring true internal proxy source IP
  • Automated header-fuzzing security scanner from an allowed subnet misclassified

Other platforms for CVE-2026-20896


Testing Methodology

Validate this detection against 3 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.

  1. Test 1Direct X-WEBAUTH-USER header injection against Gitea container

    Expected signal: HTTP request log entry on the Gitea/reverse-proxy access log showing X-WEBAUTH-USER header with source IP of the test host

  2. Test 2Verify REVERSE_PROXY_TRUSTED_PROXIES wildcard misconfiguration

    Expected signal: Command execution logged in container audit/history; no network telemetry generated

  3. Test 3Impersonate arbitrary user and attempt privileged API call

    Expected signal: Gitea audit log entry for an admin API call sourced from an impersonated session; access log entry with X-WEBAUTH-USER header from untrusted source IP


Response Playbook

Triage

  1. Confirm the Gitea deployment is running the official Docker image and check REVERSE_PROXY_TRUSTED_PROXIES in app.ini/environment variables for a wildcard (*) value
  2. Identify all source IPs that sent X-WEBAUTH-USER headers directly to the Gitea container port, cross-referencing against the known reverse proxy/load balancer IP list
  3. Review Gitea audit/sign-in logs for sessions established via reverse-proxy auth correlated with the suspicious header traffic, noting impersonated usernames (especially admin accounts)
  4. Check for any newly created API tokens, SSH keys, OAuth apps, or admin users created shortly after suspicious X-WEBAUTH-USER activity

Containment

  1. Set REVERSE_PROXY_TRUSTED_PROXIES to the exact CIDR of the legitimate reverse proxy (never *) and restart the Gitea service/container
  2. Block direct network access to the Gitea application port from any source other than the trusted reverse proxy at the firewall/security-group/network-policy level, and rotate/revoke sessions and API tokens created during the suspected window

Evidence Collection

  1. Preserve reverse proxy and Gitea container access/application logs covering the suspected exploitation window, including full request headers
  2. Export the Gitea app.ini configuration, container environment variables, and Docker Compose/Kubernetes manifest showing the trusted proxy setting at time of incident, plus a list of user accounts and permission changes made during the window

Escalation Criteria

  • !Any successful impersonation of an administrator or owner-role account via X-WEBAUTH-USER from an untrusted source IP
  • !Evidence of repository exfiltration, new deploy keys/webhooks, CI/CD pipeline modification, or supply-chain-relevant changes made under an impersonated identity

Investigation Guide

Related Techniques

Forensic Artifacts

  • >Gitea application and reverse-proxy access logs showing X-WEBAUTH-USER header values and source IPs
  • >Gitea audit log entries (sign-in events, admin actions, token/SSH key creation) tied to the impersonated account session

Tuning Guidance

Maintain an accurate, tightly-scoped CIDR allowlist of legitimate reverse proxy/load balancer IPs and update all detections whenever proxy infrastructure changes (new CDN nodes, autoscaling proxy pools, IP rotation). In containerized/Kubernetes environments, prefer matching against the internal service network CIDR rather than public IPs. Suppress alerts for well-documented internal health-check or synthetic monitoring sources after validating they cannot reach Gitea directly from outside the trusted network.


Hunting Queries

Hunts for anomalous diversity in source IPs presenting X-WEBAUTH-USER headers within short time windows, which may indicate automated impersonation attempts across multiple identities.

Hunting — KQL
kql
W3CIISLog
| where isnotempty(cs(X-WEBAUTH-USER))
| summarize DistinctIPs=dcount(c_ip), Users=make_set(cs(X-WEBAUTH-USER)) by bin(TimeGenerated, 1h)
| where DistinctIPs > 3
Hunting — SPL
spl
index=web sourcetype=gitea:access "X-WEBAUTH-USER"
| rex field=_raw "X-WEBAUTH-USER:\s*(?<webauth_user>\S+)"
| stats dc(src_ip) as distinct_ips values(webauth_user) as users by _time span=1h
| where distinct_ips > 3

Atomic Red Team Tests

Test 1 Direct X-WEBAUTH-USER header injection against Gitea container
linux

Simulates an attacker with direct network access to the Gitea HTTP port sending a request with X-WEBAUTH-USER set to an administrative username to obtain an authenticated session.

Command

bash
curl -s -i -X GET "http://<gitea-host>:3000/" -H "X-WEBAUTH-USER: admin" -H "X-WEBAUTH-EMAIL: [email protected]"

Cleanup

bash
No persistent changes made by this GET request; verify no session cookie was persisted and clear any test cookie jar files used during the test

Expected Telemetry

HTTP request log entry on the Gitea/reverse-proxy access log showing X-WEBAUTH-USER header with source IP of the test host

Expected Detection

Detection rule fires if the test host IP falls outside the configured trusted proxy CIDR ranges

Test 2 Verify REVERSE_PROXY_TRUSTED_PROXIES wildcard misconfiguration
linux

Checks a lab Gitea Docker container's effective configuration for the vulnerable wildcard trusted-proxy setting.

Command

bash
docker exec <gitea-container> cat /data/gitea/conf/app.ini | grep -i REVERSE_PROXY_TRUSTED_PROXIES

Cleanup

bash
None; this is a read-only configuration check

Expected Telemetry

Command execution logged in container audit/history; no network telemetry generated

Expected Detection

Not directly detected by network-based rule; used as a config-validation companion check to confirm exploitability

Test 3 Impersonate arbitrary user and attempt privileged API call
linux

After establishing an impersonated session via X-WEBAUTH-USER, attempts a privileged admin API call (list users) to confirm full account takeover impact.

Command

bash
curl -s -i -X GET "http://<gitea-host>:3000/api/v1/admin/users" -H "X-WEBAUTH-USER: admin"

Cleanup

bash
No persistent server-side changes from a GET request; confirm no test admin objects were created and remove any lab-only API tokens generated during validation

Expected Telemetry

Gitea audit log entry for an admin API call sourced from an impersonated session; access log entry with X-WEBAUTH-USER header from untrusted source IP

Expected Detection

Detection rule fires on the untrusted-source X-WEBAUTH-USER header; correlate with Gitea audit log showing privileged API access under the impersonated identity

Related Detections