> ## Documentation Index
> Fetch the complete documentation index at: https://help.onetsolutions.net/llms.txt
> Use this file to discover all available pages before exploring further.

# Ingress Nightmare: Unauthenticated RCE on Kubernetes Clusters (Ingress NGINX)

> Four chained CVEs in the Ingress NGINX controller let an unauthenticated attacker run code and ultimately take over the cluster.

*Published on March 26, 2025*

<Warning>
  **Ingress Nightmare — CVE-2025-1097, CVE-2025-1098, CVE-2025-24514, CVE-2025-1974.** On a Kubernetes cluster using Ingress NGINX, an attacker who can reach the admission webhook can execute arbitrary code and, by cascade, take over the cluster.
</Warning>

## Scope

The flaw affects **Ingress NGINX Controller** (not to be confused with NGINX Ingress Controller, the F5/NGINX-maintained project, which is a different product). Vulnerable versions:

* all versions `< v1.11.0`
* `v1.11.0` to `v1.11.4`
* `v1.12.0`

Quick check:

```bash theme={null}
kubectl get pods --all-namespaces \
  --selector app.kubernetes.io/name=ingress-nginx \
  -o jsonpath='{.items[*].spec.containers[*].image}'
```

## How the attack works

When you install Ingress NGINX, an **admission controller** is deployed inside the cluster. Its job: validate `Ingress` objects before they are applied to NGINX. The problem: this webhook is reachable **on the cluster network, without authentication**, by default.

An attacker who can reach the webhook (from a compromised pod, a poorly-isolated internal service, or sometimes directly from outside if the `Service` is exposed) sends a malicious `Ingress` object. The webhook processes the object, builds an NGINX configuration from it, and validates it by running the NGINX binary… which at that point interprets the injected payload. **RCE in the controller pod.**

Then comes the cascade. The controller pod typically has rights to read `Secrets` across all namespaces (because it mounts TLS certificates). Once RCE is achieved, the attacker reads every secret in the cluster — internal credentials, cloud tokens, API keys. **Cluster takeover.**

## Patching

Upgrade Ingress NGINX Controller to the latest stable version available — past anything listed as vulnerable. Follow your usual Helm/manifest procedure depending on your install.

## If you cannot patch right away

Two surface-reduction measures to apply in the meantime:

### 1. Restrict network access to the webhook

A `NetworkPolicy` that only lets the Kubernetes API server talk to the admission webhook:

```yaml theme={null}
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: ingress-nginx-admission-only-apiserver
  namespace: ingress-nginx
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/name: ingress-nginx
      app.kubernetes.io/component: admission-webhook
  policyTypes:
    - Ingress
  ingress:
    - from:
        - ipBlock:
            cidr: <API server CIDR>
      ports:
        - port: 8443
          protocol: TCP
```

Tune the CIDR to your cluster.

### 2. Temporarily disable the admission webhook

If the `NetworkPolicy` is not workable and you intend to patch right after, you can disable the admission component. With Helm:

```bash theme={null}
helm upgrade ingress-nginx ingress-nginx/ingress-nginx \
  --reuse-values \
  --set controller.admissionWebhooks.enabled=false
```

You lose admission-time validation of `Ingress` objects — so preventive safety on malformed configs — but you close the attack path until the patch is in.

## Wrap-up

This is an RCE → secret theft → takeover chain that requires no authentication, on a component many clusters expose by default. A PoC is public. Patch, and use the moment to double-check the `NetworkPolicy` around every one of your admission webhooks.

For questions, open a ticket from your [OnetSolutions client area](https://onetsolutions.net).
