Back to Blog
Kubernetes Ingress Security · Rewrite Engine

NGINX Rift
CVE-2026-42945

This is not an ingress-nginx annotation parser bug. It is a native NGINX C rewrite-engine memory-corruption bug that can become reachable through Kubernetes Ingress-generated NGINX configuration. The question is not “do we run ingress-nginx?” The question is “does our generated NGINX config contain the vulnerable rewrite shape on a vulnerable NGINX binary?”

Riad DAHMANIk8sec Security ResearchMay 202620 min readIngress NGINXCVE-2026-42945
Minimalist NGINX Rift CVE-2026-42945 article hero image

The Uncomfortable Truth

NGINX Rift matters because the vulnerable code path sits below your Kubernetes abstraction. The Ingress object, the annotation, the Helm chart, and the controller are only the delivery chain. The dangerous instruction is executed later by the NGINX worker process inside the native rewrite engine.

The bug lives in src/http/ngx_http_script.c, inside the native C implementation used by ngx_http_rewrite_module. It is not Lua. It is not the ingress-nginx Go controller. It is not an annotation parser issue.

The public NGINX Rift repository describes CVE-2026-42945 as a heap buffer overflow in ngx_http_rewrite_module affecting configurations that use rewrite and set directives. The same public write-up states that NGINX Open Source versions 0.6.27 through 1.30.0 are affected and that 1.30.1 / 1.31.0 contain fixes.

Where the Bug Actually Lives

The vulnerable path is inside NGINX’s script engine. NGINX processes rewrite logic in two conceptual phases: first it calculates how large the output buffer must be; then it copies transformed URI data into that buffer.

1. Parse configNGINX loads a rewrite rule containing unnamed captures such as $1.
2. Length passA zeroed sub-engine computes the required output length.
3. Copy passMain engine sees ? behavior and escapes URI bytes differently.
4. Heap corruptionThe copy can write past the undersized heap buffer.

That mismatch is the important engineering lesson. The vulnerable state is not “NGINX exists.” The vulnerable state is “a vulnerable NGINX binary executes a rewrite configuration shape that triggers inconsistent buffer sizing and copy behavior.”

When You Are Affected

Vulnerable NGINX binary
The controller image contains NGINX Open Source 0.6.27–1.30.0 or vulnerable NGINX Plus builds.
Rewrite directive exists
Rendered nginx.conf contains rewrite logic using unnamed captures such as $1 or $2.
Replacement contains ?
The replacement string includes a query delimiter and causes argument escaping behavior.
Followed by rewrite / if / set
The advisory pattern includes a rewrite directive followed by rewrite, if, or set in the same context.

When You Are Probably Not Affected

StateRiskReason
NGINX 1.30.1+ stable or 1.31.0+ mainlineLowFixed according to NGINX advisory data.
No rewrite directives in rendered configLowThe vulnerable module path is not exercised by that config.
Named captures instead of $1/$2LowerConfiguration mitigation guidance points to replacing unnamed captures.
Lua rewrite logic onlyNot this bugLua rewrite code is not the vulnerable native C ngx_http_rewrite_module path.
ASLR enabledReduces RCE reliability, not a fixASLR can make exploitation harder; it does not remove overflow or DoS risk.

Commands: Check Your Kubernetes Context

1. Find ingress-nginx controller pods
kubectl get pods -A \
  -l app.kubernetes.io/name=ingress-nginx \
  -o wide
2. Set namespace and pod variables
NS=$(kubectl get pods -A -l app.kubernetes.io/name=ingress-nginx \
  -o jsonpath='{.items[0].metadata.namespace}')

POD=$(kubectl -n "$NS" get pods -l app.kubernetes.io/component=controller \
  -o jsonpath='{.items[0].metadata.name}')

echo "namespace=$NS pod=$POD"
3. Check embedded NGINX version
kubectl -n "$NS" exec "$POD" -c controller -- nginx -v
kubectl -n "$NS" exec "$POD" -c controller -- nginx -V 2>&1 | tr ' ' '\n' | egrep 'nginx/|rewrite|lua|pcre|http_rewrite'
4. Dump rendered nginx.conf and search risky rewrite shape
kubectl -n "$NS" exec "$POD" -c controller -- nginx -T > nginx-rendered.conf 2>&1

grep -nE 'rewrite[[:space:]].*\$[0-9]+.*\?' nginx-rendered.conf

grep -nE 'rewrite[[:space:]].*\$[0-9]+.*\?' nginx-rendered.conf | cut -d: -f1 | while read n; do
  sed -n "$((n-5)),$((n+8))p" nginx-rendered.conf
  echo "-----"
done
5. Find Ingress objects likely to generate rewrite logic
kubectl get ingress -A -o json | jq -r '
  .items[]
  | select(
      (.metadata.annotations["nginx.ingress.kubernetes.io/rewrite-target"] // "" | test("\\$[0-9]")) or
      (.metadata.annotations["nginx.ingress.kubernetes.io/use-regex"] // "" | ascii_downcase == "true") or
      (.metadata.annotations["nginx.ingress.kubernetes.io/configuration-snippet"] // "" | test("rewrite|set|if")) or
      (.metadata.annotations["nginx.ingress.kubernetes.io/server-snippet"] // "" | test("rewrite|set|if"))
    )
  | [.metadata.namespace, .metadata.name,
     (.metadata.annotations["nginx.ingress.kubernetes.io/use-regex"] // "-"),
     (.metadata.annotations["nginx.ingress.kubernetes.io/rewrite-target"] // "-")]
  | @tsv'
6. Check snippet risk switch
kubectl -n "$NS" get configmap -l app.kubernetes.io/component=controller -o yaml \
  | egrep -n 'allow-snippet-annotations|annotations-risk-level|enable-annotation-validation|strict-validate-path-type'

Kubernetes Configuration That Creates Risk

The danger is not the annotation alone. The danger is the generated NGINX directive chain.

Ingress pattern to review
metadata:
  annotations:
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/rewrite-target: "/backend/$1?tenant=$2"
spec:
  rules:
  - http:
      paths:
      - path: /api/(.*)/(.*)
        pathType: ImplementationSpecific

If that input produces a rendered rewrite directive with unnamed capture variables and a ? in the replacement, treat it as vulnerable until version and final rendered config prove otherwise.

Mitigation Path

PriorityActionWhy
1Upgrade NGINX to 1.30.1+ or 1.31.0+Removes the native rewrite engine bug.
2Replace unnamed captures $1, $2 with named capturesConfiguration-level mitigation when immediate patching is blocked.
3Disable snippets unless explicitly requiredPrevents raw user-supplied NGINX directives from entering config.
4Block risky rewrite-target patterns at admissionStops recurrence through Ingress changes.
5Keep ASLR enabledReduces exploit reliability but does not fix the bug.

Kyverno Admission Mitigation

kyverno-nginx-rift-mitigation.yaml
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: block-nginx-rift-rewrite-patterns
spec:
  validationFailureAction: Enforce
  background: true
  rules:
    - name: block-rewrite-target-unnamed-capture-query
      match:
        any:
          - resources:
              kinds:
                - networking.k8s.io/v1/Ingress
      validate:
        message: "NGINX Rift mitigation: rewrite-target must not combine $1/$2 with '?'."
        deny:
          conditions:
            any:
              - key: "{{ regex_match('.*\\\\$[0-9]+.*\\\\?.*', request.object.metadata.annotations.\\"nginx.ingress.kubernetes.io/rewrite-target\\" || '') }}"
                operator: Equals
                value: true
              - key: "{{ regex_match('.*\\\\?.*\\\\$[0-9]+.*', request.object.metadata.annotations.\\"nginx.ingress.kubernetes.io/rewrite-target\\" || '') }}"
                operator: Equals
                value: true

    - name: block-raw-snippet-rewrite-unnamed-capture-query
      match:
        any:
          - resources:
              kinds:
                - networking.k8s.io/v1/Ingress
      validate:
        message: "NGINX Rift mitigation: snippets must not define rewrite directives with unnamed captures and '?'."
        deny:
          conditions:
            any:
              - key: "{{ regex_match('(?s).*rewrite\\\\s+.*\\\\$[0-9]+.*\\\\?.*', request.object.metadata.annotations.\\"nginx.ingress.kubernetes.io/configuration-snippet\\" || '') }}"
                operator: Equals
                value: true
              - key: "{{ regex_match('(?s).*rewrite\\\\s+.*\\\\$[0-9]+.*\\\\?.*', request.object.metadata.annotations.\\"nginx.ingress.kubernetes.io/server-snippet\\" || '') }}"
                operator: Equals
                value: true

Runtime Signals to Watch

Worker restarts
Unexpected ingress-nginx pod restarts, worker crashes, or repeated reloads.
Request bursts
High-entropy URI requests hitting endpoints with rewrite rules.
Config drift
New Ingress annotations introducing regex rewrite behavior.
Post-crash execution
Unexpected shell, outbound connection, or process anomaly inside ingress controller container.

Final Word

Do not reduce this vulnerability to “upgrade ingress-nginx.” The real exposure question is sharper: which NGINX binary is inside the controller image, and what exact NGINX configuration did the Kubernetes controller render from your Ingress objects?

My view: every Kubernetes platform team should audit the generated nginx.conf, not only the Ingress YAML. The YAML is intent. The rendered NGINX configuration is what actually executes.

— Riad DAHMANI, k8sec.io

Find dangerous ingress patterns before they become attack paths.

K8SEC correlates Kubernetes objects, generated exposure, RBAC, and runtime signals so defenders can see exploitable paths before attackers do.

Explore K8SEC