CVE-2022-4886 - How Ingress-nginx `path` Sanitization Can Be Bypassed with `log_format` Directive
In December 2022, a critical vulnerability was discovered in the popular Kubernetes ingress-nginx controller: CVE-2022-4886. This vulnerability occurs when the log_format directive in the controller’s configuration can be abused to bypass the usual path sanitization checks. Attackers can craft specific requests that escape detection and potentially access restricted routes or inject malicious payloads.
In this post, you'll learn what caused the issue, see code examples, and understand how an exploit could work — all explained in straightforward, simple language.
What is ingress-nginx and Why Does Path Sanitization Matter?
Ingress-nginx is a Kubernetes component that manages external access to services in a cluster, commonly using HTTP(S) routes. The path in an ingress rule defines what part of a URL goes to which service.
Path sanitization is meant to prevent sneaky attackers from using funky URLs (/..//admin, /api/.%2e/.%2e/) to access stuff they shouldn’t be able to. Usually, ingress-nginx is strict about not passing dangerous paths through.
The Problem: How log_format Opens a Backdoor
The NGINX web server (which ingress-nginx uses under the hood) has a configuration option called log_format. This lets you customize how access logs are written. You might use variables like $request_uri, which is the incoming URL.
Here’s the core of the flaw: By intentionally referencing unsanitized variables in log_format, attackers’ original requests—including unsanitized or even malicious paths—can show up in access logs or be used in responses generated by custom error pages. If those logs are processed by automated systems, or if configs echo values from log_format, path sanitization loses its power.
Suppose someone configures NGINX in ingress-nginx with
log_format custom_log '$remote_addr - $request_uri';
Now, imagine an attacker sends a crafted request
GET /secret/../admin HTTP/1.1
Host: example.com
While the main request gets sanitized (/admin access is blocked), the raw $request_uri in the logs still shows /secret/../admin. Downstream log processors, SIEMs, or even app code might use that raw value thinking it’s safe; but the attacker has bypassed the normal defenses.
Path Sanitization:
- ingress-nginx usually sanitizes paths before routing, so /api/../admin is normalized.
`
GET /public/..;/admin HTTP/1.1
Code Snippet: Reproducing the Vulnerability
Let's see an example of a vulnerable ingress-nginx Helm configuration.
controller:
config:
log-format-upstream: '$remote_addr - $request_uri - $status'
Apply this, then send a dangerous request
curl -H "Host: myapp.example" "http://<ingress-nginx-ip>/api/..;/admin";
After this, check the NGINX pod's logs—the raw, unsanitized path appears
192..2.100 - /api/..;/admin - 404
References
- Official CVE-2022-4886 entry (Mitre)
- Ingress-nginx GitHub Security Advisory
- NGINX log_format Documentation
- Path traversal basics (OWASP)
How To Protect Yourself
- Avoid custom log_format that includes unsanitized variables like $request_uri. Instead, use sanitized alternatives like $uri.
- Upgrade ingress-nginx to a patched release (v1.7.+), which restricts how dangerous variables can be referenced.
Review error page templates: Make sure they don’t output raw request data.
- Sanitize logs: If you process access logs downstream, always sanitize and normalize before touching sensitive data.
Conclusion
CVE-2022-4886 highlights how a harmless-looking custom log format can break open the door for attackers, letting them side-step path sanitization in Kubernetes ingress-nginx. Always treat any unsanitized user input—even logs!—as dangerous, and be careful with logging configurations in sensitive environments.
Stay safe, and always subscribe to advisories for critical infrastructure like ingress-nginx!
For more details, check the Ingress-nginx GitHub advisory or follow their upstream security releases.
Timeline
Published on: 10/25/2023 20:15:09 UTC
Last modified on: 11/02/2023 18:05:23 UTC