# External Authentication bypass in ingress-nginx

ingress-nginx passes unnormalized $request_uri in X-Auth-Request-Redirect, letting path traversal bypass external auth that trusts the path prefix.

- Payout: unconfirmed
- Severity: high
- Program: Kubernetes
- Credited: Niemiec Marcin
- Disclosed: 2022-05-29
- Write-up quality: 7/10
- Original: https://xvnpw.github.io/posts/external_authentication_bypass_in_ingress_nginx/
- Library page: https://bugbountylibrary.com/r/blog%3Axvnpw-github-io-posts-external-authentication-bypass-in-ingress-nginx
- Tags: domain:cloud impact:internal-access kind:bounty platform:blog sev:high tech:kubernetes tech:nginx technique:source-review vuln:access-control vuln:auth-bypass vuln:path-traversal

**Target:** Kubernetes ingress-nginx external auth (auth-url) header forwarding
**Root cause:** nginx $request_uri is not normalized, so ingress-nginx forwards raw paths containing ../ in X-Original-Url and X-Auth-Request-Redirect to the external auth service, which makes allow/deny decisions on the unnormalized path.
**Steps:**
1. Deploy ingress-nginx and a test app with /public-service/(.*) and /protected-service/(.*) paths, auth-url pointing to an auth service that allows paths starting with /public-service/.
2. Confirm /protected-service/protected returns 401 without X-Api-Key.
3. Send `curl --path-as-is http://host/public-service/../protected-service/protected -H 'Host: app.test'`.
4. Auth service sees X-Auth-Request-Redirect: /public-service/..%2Fprotected-service/protected, matches /public-service/ prefix, returns 204, and nginx serves protected data.
**How found:** Researcher asked what the X-Auth-Request-Redirect header contains and noticed it carried the raw, unnormalized $request_uri; hypothesized auth services making prefix-based decisions would be fooled by ../ traversal.
**Exploitation:** Attacker prepends an allowed path prefix followed by ../ traversal to reach a protected backend path; the external auth service authorizes based on the misleading prefix while nginx routes to the protected service, returning protected data without credentials.
**Insight:** When an ingress forwards the raw request URI to an external auth service, test whether the auth service does prefix matching on that unnormalized path; a leading allowed prefix plus ../ can satisfy the check while routing elsewhere. Compare $request_uri vs $uri/$service_name.
