Why ingress-nginx configuration validation enabled code execution
CVE-2025-1974 lets unauthenticated network access reach dangerous configuration processing. The March patches address the execution path and related injection vulnerabilities.
An admission webhook is supposed to examine a proposed object before Kubernetes accepts it. In ingress-nginx, that examination included generating an NGINX configuration and asking the NGINX binary to test it. Configuration testing proved capable of loading executable code, and the network endpoint performing that test did not establish that its caller was the Kubernetes API server.
The March 24 Kubernetes disclosure explains the resulting escalation. CVE-2025-1974 allows an unauthenticated attacker with access to the Pod network to exploit configuration injection through the ingress-nginx validating admission controller. Combined with the related injection vulnerabilities disclosed today, this can produce code execution in the controller's context. The default controller permissions include access to Secrets across the cluster.
I value the Kubernetes API as a framework for controllers, but that framework also gives an extension consequential responsibilities. Here, a component translating API objects into another program's configuration exposed a privileged processing path through a separate network listener. Protecting the main API did not protect every way of reaching that processing code.
A direct request changes the permission requirement
Ordinary Ingress creation goes through the Kubernetes API. Creating the object requires permission, and admission participates in that request path. In the researchers' attack, a constructed AdmissionReview goes directly to the ingress-nginx admission endpoint. Network reachability to that endpoint replaces the need for Kubernetes credentials that authorize Ingress creation.
That difference explains the severity of the disclosure. Configuration injection available only to an Ingress author already crosses a serious trust boundary. Making the same processing reachable by an unauthenticated network peer expands the set of possible attackers to workloads and other systems with the necessary connectivity.
The official security issue assigns a CVSS score of 9.8 and describes arbitrary code execution under certain conditions. It identifies ingress-nginx as the affected component. The existence of a Kubernetes Ingress object or an NGINX process elsewhere does not establish that this particular vulnerable implementation is installed.
The Kubernetes announcement also warns that Pod network access can extend beyond Pods. Some environments permit access from other workloads in the cloud network or from a corporate network. That is a deployment property, so the relevant question is which systems can reach the admission endpoint. The word internal does not answer it.
Testing configuration invokes more than a parser
The Wiz researchers' technical account follows the admission code into generation of a temporary NGINX configuration. Next, the controller invokes the binary with the configuration-test option. This is intended to reject invalid configuration before it affects the serving process.
The input-to-configuration translation contains several injection opportunities. The report describes an authentication URL annotation, a certificate common-name matching annotation, and a mirror-related UID value. Each reaches a different position in generated configuration. The UID case matters because validation aimed at annotations alone does not cover a field outside the annotation set.
The report also distinguishes the affected cases across versions. Its auth-url injection does not apply to v1.12.0 under the default annotation validation behavior it describes. That does not make v1.12.0 safe from the whole disclosure. Different injection paths have different constraints, and the execution path remains the reason to install the fixed release.
An injected configuration directive does not automatically execute arbitrary application code. The researchers needed a directive that could load code while NGINX tested the configuration. They report that an initial module-loading approach failed because of where the directive could appear. An OpenSSL engine-related directive provided a usable path under the constraints of the generated configuration.
That distinction is central to the failure. The unsafe effect occurred during the check, before the controller applied a new configuration to the serving NGINX process. Rejecting an object later would not undo code already loaded by the validation invocation. A validation operation has to be evaluated according to its actual effects, including the modules and libraries it can initialize.
The serving process contributes to the chain
The researchers describe a second interaction with the NGINX process handling application traffic. NGINX can buffer request bodies in temporary files. Their chain used this behavior to place shared-library content in the controller Pod's filesystem context, then referenced that content during configuration validation.
The report explains that a file descriptor can remain accessible after its temporary file has been removed. That allows the chain to connect a buffered request body to a later library load. The important operational point is the composition of two interfaces in the same Pod, each doing something that appears narrower when examined alone.
Serving application traffic handles untrusted bytes. Testing generated configuration invokes a program with access to local files. Combining those behaviors with injectable directives and unauthenticated admission access provides a route to code execution. Reviewing the admission handler only as a JSON endpoint would miss the downstream behavior of the program it launches.
This also explains why application routing and admission exposure are distinct parts of remediation. The public NGINX listener exists to serve applications. The admission listener exists for API-server interaction. A legitimate need for external access to one does not establish a need for external access to the other.
Controller permissions determine the consequences
The official announcement says ingress-nginx can access all Secrets cluster-wide in its default installation. Code running as that controller can therefore gain access to material beyond the Ingress object used in the attack. The announcement describes complete cluster takeover as a possible consequence of that access.
It is more precise to identify that chain than to say every network request automatically becomes cluster administrator. Reachability enables interaction with the vulnerable handler. The injection and validation behavior can provide execution, and the controller's permissions determine what that execution can access. The default permission set makes the result especially serious.
I consider this a strong reason to review admission components as privileged services. A webhook may have a small role in an API request while the process implementing it has broad permissions. Its network exposure needs to be judged against the permissions of that process and the behavior of every parser it invokes.
The official issue states that there are no known indicators of compromise that prove exploitation. That statement does not establish that a cluster has remained uncompromised. It describes a limit in detection evidence at disclosure time. The availability of a patch and the absence of a definitive detection signal answer different questions.
The patch and the temporary mitigation have different scopes
The fixed controller releases announced today are ingress-nginx v1.12.1 and v1.11.5. The Kubernetes post says these releases fix all five vulnerabilities in the batch. Those are controller version numbers, so they should not be confused with a Helm chart version that packages the controller.
The standard discovery command from the announcement searches for ingress-nginx Pods across namespaces. Here it includes an explicit context placeholder that must be replaced with the intended cluster context.
kubectl --context YOUR_CONTEXT get pods --all-namespaces \
--selector app.kubernetes.io/name=ingress-nginx
If upgrading immediately is impossible, the official mitigation is to disable the ingress-nginx validating admission controller. For a Helm-managed installation, the announcement identifies this value. It belongs in the installation's existing values and upgrade workflow.
controller:
admissionWebhooks:
enabled: false
For a manual installation, the announcement requires both deleting the ingress-nginx admission ValidatingWebhookConfiguration and removing the validating-webhook argument from the controller Deployment or DaemonSet. Removing only the registration would stop normal API-server calls without necessarily stopping the listener that direct network requests target.
Disabling admission is a temporary reduction in exposure. It does not repair each configuration injection vulnerability, and it removes pre-acceptance checks that help users catch incorrect Ingress configuration. The announcement explicitly tells operators to restore admission after upgrading.
The researchers also recommend restricting admission access to the API server and avoiding external exposure. That addresses the direct network path, while the patch repairs the vulnerable implementation. The distinction remains relevant after this incident because a webhook's intended caller and its permitted network callers are separate properties of a cluster deployment.
The disclosure history records why fixing the combined behavior required more than an initial sanitization change. Wiz reported bypasses for proposed repairs during the private coordination period. Its published timeline says the eventual CVE-2025-1974 resolution removed NGINX configuration validation from the admission controller. That changes the dangerous execution path itself. The accompanying injection fixes address the translation of individual input fields, which remains a separate responsibility wherever those fields contribute to generated configuration.