IngressNightmare: Kubernetes ingress-nginx Admission Controller Shared-Library Injection RCE (CVE-2025-1974)
by BoianEduard · 2026-07-06
- Severity
- Critical
- CVE
- CVE-2025-1974
- Category
- cloud
- Affected product
- Kubernetes ingress-nginx admission controller
- Affected versions
- All versions < 1.11.5, 1.11.0-1.11.4, and 1.12.0
- Disclosed
- 2026-07-06
- Patch status
- unpatched
Tags
References
Archive entry
intelseclab/poc-archiveMetadata
| Field | Value |
|---|---|
| Date Added | 2026-07-06 |
| Last Updated | 2026-07-06 |
| Author / Researcher | BoianEduard |
| CVE / Advisory | CVE-2025-1974 |
| Category | cloud |
| Severity | Critical |
| CVSS Score | 9.8 (per NVD) |
| Status | Weaponized |
| Tags | kubernetes, ingress-nginx, ingressnightmare, admission-controller, nginx, ssl-engine, shared-library-injection, cluster-secrets, docker, python, c, cwe-94 |
| Related | N/A |
Affected Target
| Field | Value |
|---|---|
| Software / System | Kubernetes ingress-nginx admission controller |
| Versions Affected | All versions < 1.11.5, 1.11.0-1.11.4, and 1.12.0 |
| Language / Platform | Kubernetes cluster (any provider), C (malicious .so payload), Python 3 (trigger script) |
| Authentication Required | No (unauthenticated access to the in-cluster admission webhook is sufficient — “IngressNightmare”) |
| Network Access Required | Yes (network access to the ingress-nginx controller pod’s admission webhook port, typically reachable from within the cluster or via a misconfigured exposure) |
Summary
The ingress-nginx admission controller validates incoming Ingress objects by rendering a temporary NGINX configuration and running nginx -t against it — but the validation webhook itself has no authentication and accepts attacker-controlled configuration snippet annotations. By injecting the annotation nginx.ingress.kubernetes.io/configuration-snippet with content that breaks out of its intended NGINX config context and adds an ssl_engine /path/to/payload.so; directive, an attacker can make nginx -t load an arbitrary shared library from a path they control (uploaded beforehand via a separate write primitive to the controller pod, e.g. /tmp/exploit.so). Because shared libraries execute constructor code as soon as they are mapped into memory, this achieves arbitrary code execution inside the ingress-nginx controller pod — which, under default RBAC, has read access to all Secrets in the cluster, making this a path to full cluster compromise. Publicly disclosed by Wiz Research as “IngressNightmare.”
Vulnerability Details
Root Cause
The admission webhook accepts and templates attacker-supplied annotation content into the NGINX configuration used for nginx -t validation without adequate sanitization, letting an attacker close the intended context and inject a raw ssl_engine directive:
| |
The malicious shared library uses a GCC constructor attribute so its payload runs the instant NGINX’s OpenSSL engine loader maps it into memory — no further trigger is needed:
| |
Attack Vector
- Attacker gets a malicious
.sopayload onto a path reachable by the ingress-nginx controller pod’s filesystem (e.g./tmp/exploit.so— in this lab, delivered by a companion “attacker” pod with access to the webhook). - Attacker sends a crafted
AdmissionReviewrequest directly to the admission controller’s validating webhook endpoint (e.g.https://<controller-pod-ip>:8443/networking/v1/ingresses), containing anIngressobject whoseconfiguration-snippetannotation breaks out of its NGINX config context and injectsssl_engine /tmp/exploit.so;. - The admission controller renders this into a temporary NGINX config and runs
nginx -tto validate it, which loads the OpenSSL engine at the injected path. - The shared library’s constructor function executes immediately upon load, inside the ingress-nginx controller pod.
- The payload uses the pod’s own Kubernetes service-account token (mounted by default) to call the Kubernetes API and dump all cluster Secrets, and/or drops a witness file (
/tmp/pwned).
Impact
Unauthenticated arbitrary code execution inside the ingress-nginx controller pod, with default RBAC granting that pod read access to all Secrets across the cluster — enabling full cluster compromise (credential theft, further lateral movement, persistence).
Environment / Lab Setup
Tools required: minikube, kubectl, helm (installed automatically by setup_cve_env.sh)
Lab: one-node minikube cluster with a vulnerable ingress-nginx controller
(v1.11.0-1.11.4 or v1.12.0) deployed via Helm, plus a companion "attacker"
pod (Dockerfile.attacker / attacker-pod.yaml) that delivers exploit.so and
runs exploit.py against the controller's admission webhook
Proof of Concept
PoC Script
See
exploit.py,exploit.c/exploit.so,setup_cve_env.sh,Dockerfile.attacker, andattacker-pod.yamlin this folder.
| |
Detection & Indicators of Compromise
POST https://<controller-ip>:8443/networking/v1/ingresses HTTP/1.1
Content-Type: application/json
{"kind":"AdmissionReview", ... "configuration-snippet": "}}} ssl_engine ..."}
Signs of compromise:
- ingress-nginx controller pod logs containing
RCE TRIGGEREDor unexplained stderr output aroundnginx -tvalidation Ingressresources (even ones that failed to apply) withconfiguration-snippetannotations containing}characters orssl_engine/other raw NGINX directives outside expected context- Unexpected outbound calls from the controller pod to
https://kubernetes.default.svc/api/v1/secretsusing the pod’s own service-account token - Presence of unexpected
.sofiles or witness files (e.g./tmp/pwned) inside the controller pod’s filesystem - Direct network connections to the admission webhook port (8443 by default) from outside expected API-server traffic
Remediation
| Action | Detail |
|---|---|
| Primary fix | Upgrade ingress-nginx to >= 1.11.5 or >= 1.12.1, which removes/restricts the ability for validating-webhook-rendered configuration to inject arbitrary NGINX directives via annotations |
| Interim mitigation | Restrict network access to the admission webhook port to only the Kubernetes API server (NetworkPolicy); disable/avoid the validationWebhook if not required; drop or tightly scope the ingress-nginx controller’s ServiceAccount RBAC so it cannot read all cluster Secrets; disable configuration-snippet support (allow-snippet-annotations: false) |
References
Notes
Mirrored from https://github.com/BoianEduard/CVE-2025-1974 on 2026-07-06. Full working chain (exploit.c/.so, exploit.py, Dockerfile, k8s pod manifest, and an automated setup script) reproducing the publicly disclosed “IngressNightmare” RCE end-to-end in a disposable minikube lab.
| |