πŸ“šBook Signing at KubeCon EU 2026Meet us at Booking.com HQ (Mon 18:30-21:00) & vCluster booth #521 (Tue 24 Mar, 12:30-1:30pm) β€” free book giveaway!RSVP Booking.com Event
Security intermediate ⏱ 15 minutes K8s 1.28+

CVE-2026-4342: ingress-nginx Code Execution...

Patch CVE-2026-4342 in ingress-nginx β€” a CVSS 8.8 configuration injection vulnerability enabling arbitrary code execution. Upgrade to v1.13.9, v1.14.

By Luca Berton β€’ β€’ πŸ“– 6 min read

πŸ’‘ Quick Answer: CVE-2026-4342 is a CVSS 8.8 vulnerability in ingress-nginx that allows configuration injection and arbitrary code execution via crafted Ingress annotations. Upgrade to v1.13.9, v1.14.5, or v1.15.1 immediately. ingress-nginx is now EOL β€” migrate to Gateway API.

The Problem

A critical security vulnerability (CVE-2026-4342) was disclosed in ingress-nginx on 2026-03-19. A combination of Ingress annotations can inject arbitrary nginx configuration, leading to:

  • Arbitrary code execution in the ingress-nginx controller context
  • Cluster-wide Secret disclosure β€” by default, the controller can access ALL Secrets in the cluster
  • Full cluster compromise via stolen ServiceAccount tokens

CVSS Score: 8.8 (High) β€” Network-accessible, low complexity, low privilege required.

Am I Vulnerable?

# Check if ingress-nginx is installed
kubectl get pods --all-namespaces --selector app.kubernetes.io/name=ingress-nginx

# Check your version
kubectl exec -n ingress-nginx \
  $(kubectl get pods -n ingress-nginx -l app.kubernetes.io/component=controller -o jsonpath='{.items[0].metadata.name}') \
  -- /nginx-ingress-controller --version

# Affected: ALL versions below v1.13.9, v1.14.5, and v1.15.1

Detect Exploitation Attempts

# Look for suspicious Ingress annotations
kubectl get ingress -A -o json | jq -r '
  .items[] |
  select(.metadata.annotations != null) |
  select(
    (.metadata.annotations | to_entries[] |
     .value | test("\\\\n|#|\\{|load_module|lua_|proxy_pass")) // false
  ) |
  "\(.metadata.namespace)/\(.metadata.name): SUSPICIOUS"
'

# Check for unusual characters in Ingress paths
kubectl get ingress -A -o json | jq -r '
  .items[] |
  .metadata as $meta |
  .spec.rules[]? |
  .http.paths[]? |
  select(.path | test("[;#{}\\\\]")) |
  "\($meta.namespace)/\($meta.name): suspicious path: \(.path)"
'

The Solution

Option 1: Upgrade ingress-nginx (Immediate Fix)

# Upgrade via Helm
helm repo update
helm upgrade ingress-nginx ingress-nginx/ingress-nginx \
  --namespace ingress-nginx \
  --version 4.13.9 \
  --set controller.image.tag=v1.13.9

# Or for the 1.14.x branch
helm upgrade ingress-nginx ingress-nginx/ingress-nginx \
  --namespace ingress-nginx \
  --set controller.image.tag=v1.14.5

# Or for the 1.15.x branch
helm upgrade ingress-nginx ingress-nginx/ingress-nginx \
  --namespace ingress-nginx \
  --set controller.image.tag=v1.15.1

# Verify the upgrade
kubectl rollout status deployment/ingress-nginx-controller -n ingress-nginx
kubectl exec -n ingress-nginx \
  $(kubectl get pods -n ingress-nginx -l app.kubernetes.io/component=controller -o jsonpath='{.items[0].metadata.name}') \
  -- /nginx-ingress-controller --version

Option 2: Restrict Controller Permissions (Mitigation)

If you can’t upgrade immediately, limit the blast radius:

# Restrict the controller's RBAC β€” don't let it read all Secrets
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: ingress-nginx-restricted
rules:
  - apiGroups: [""]
    resources: ["services", "endpoints", "configmaps"]
    verbs: ["get", "list", "watch"]
  - apiGroups: ["networking.k8s.io"]
    resources: ["ingresses", "ingressclasses"]
    verbs: ["get", "list", "watch"]
  # Only allow Secrets in the ingress-nginx namespace
  # NOT cluster-wide
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: ["get", "list", "watch"]
    # Use namespace-scoped Role instead of ClusterRole for secrets
---
# Namespace-scoped secret access only
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: ingress-nginx-secrets
  namespace: ingress-nginx
rules:
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: ["get", "list", "watch"]
# Network Policy β€” restrict controller egress
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: ingress-nginx-restrict
  namespace: ingress-nginx
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/name: ingress-nginx
  policyTypes:
    - Egress
  egress:
    - to:
        - namespaceSelector: {}
      ports:
        - port: 443     # API server
        - port: 6443
    - to:
        - podSelector: {}
      ports:
        - port: 80      # Backend services
        - port: 443
        - port: 8080
        - port: 8443

ingress-nginx is EOL (End of Life). The recommended path forward is Kubernetes Gateway API:

# Gateway API equivalent of Ingress
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: main-gateway
  namespace: gateway-system
spec:
  gatewayClassName: nginx   # or envoy, istio, cilium
  listeners:
    - name: http
      protocol: HTTP
      port: 80
    - name: https
      protocol: HTTPS
      port: 443
      tls:
        mode: Terminate
        certificateRefs:
          - name: wildcard-tls
            namespace: gateway-system
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: my-app
  namespace: production
spec:
  parentRefs:
    - name: main-gateway
      namespace: gateway-system
  hostnames:
    - "app.example.com"
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /api
      backendRefs:
        - name: api-service
          port: 8080
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: frontend-service
          port: 80

Migration Path: Ingress β†’ Gateway API

# 1. Install a Gateway API implementation
# Envoy Gateway
helm install envoy-gateway oci://docker.io/envoyproxy/gateway-helm \
  --version v1.2.0 -n envoy-gateway-system --create-namespace

# Or Cilium (if already using Cilium CNI)
cilium install --set gatewayAPI.enabled=true

# Or NGINX Gateway Fabric (NGINX's Gateway API implementation)
helm install ngf oci://ghcr.io/nginx/charts/nginx-gateway-fabric \
  --version 1.5.0 -n nginx-gateway --create-namespace

# 2. Create Gateway
kubectl apply -f gateway.yaml

# 3. Convert Ingress resources to HTTPRoute
# For each Ingress, create an equivalent HTTPRoute

# 4. Test with canary traffic
# Point a subset of DNS to the new Gateway

# 5. Cut over DNS
# Update DNS records to point to Gateway's external IP

# 6. Remove ingress-nginx
helm uninstall ingress-nginx -n ingress-nginx
kubectl delete namespace ingress-nginx

Scan for All Ingress Resources to Migrate

# List all Ingress resources that need migration
kubectl get ingress -A -o custom-columns=\
'NAMESPACE:.metadata.namespace,NAME:.metadata.name,HOSTS:.spec.rules[*].host,CLASS:.spec.ingressClassName'

# Export as HTTPRoute templates
kubectl get ingress -A -o json | jq -r '
  .items[] |
  "---\napiVersion: gateway.networking.k8s.io/v1\nkind: HTTPRoute\nmetadata:\n  name: \(.metadata.name)\n  namespace: \(.metadata.namespace)\nspec:\n  parentRefs:\n    - name: main-gateway\n      namespace: gateway-system\n  hostnames:\n    - \"\(.spec.rules[0].host // "example.com")\"\n  rules:\n    - backendRefs:\n        - name: \(.spec.rules[0].http.paths[0].backend.service.name)\n          port: \(.spec.rules[0].http.paths[0].backend.service.port.number)"
'
graph TD
    A[CVE-2026-4342 Disclosed] --> B{ingress-nginx installed?}
    B -->|No| C[Not affected βœ…]
    B -->|Yes| D{Can upgrade now?}
    D -->|Yes| E[Upgrade to v1.13.9 / v1.14.5 / v1.15.1]
    D -->|No| F[Apply RBAC restrictions + NetworkPolicy]
    E --> G{Plan migration}
    F --> G
    G --> H[Install Gateway API implementation]
    H --> I[Convert Ingress β†’ HTTPRoute]
    I --> J[Remove ingress-nginx]
    J --> K[Secure + Future-proof βœ…]

Common Issues

IssueCauseFix
Upgrade breaks custom annotationsDeprecated annotations removedCheck migration guide for replacements
TLS not working after Gateway migrationCertificate ref namespaceUse ReferenceGrant for cross-namespace
Backend 502 after migrationService port mismatchVerify backendRefs port matches Service
Gateway not getting external IPMissing LoadBalancer supportCheck cloud provider or use MetalLB

Best Practices

  • Upgrade immediately β€” CVSS 8.8 with network access means active exploitation is likely
  • Restrict controller RBAC β€” never give cluster-wide Secret access in production
  • Monitor Ingress annotations β€” use OPA/Gatekeeper to block dangerous annotation patterns
  • Plan Gateway API migration β€” ingress-nginx is EOL, no more security patches coming
  • Report exploitation to security@kubernetes.io if you find evidence of compromise

Key Takeaways

  • CVE-2026-4342 enables code execution and cluster-wide Secret theft via ingress-nginx
  • Upgrade to v1.13.9, v1.14.5, or v1.15.1 immediately
  • ingress-nginx is EOL β€” migrate to Gateway API (Envoy Gateway, Cilium, NGINX Gateway Fabric)
  • Restrict controller RBAC as defense-in-depth β€” it should never need cluster-wide Secret access
  • Gateway API is the future of Kubernetes ingress β€” start migrating now
#cve #ingress-nginx #security #vulnerability #nginx
Luca Berton
Written by Luca Berton

Principal Solutions Architect specializing in Kubernetes, AI/GPU infrastructure, and cloud-native platforms. Author of Kubernetes Recipes and creator of CopyPasteLearn courses.

Kubernetes Recipes book cover

Want More Kubernetes Recipes?

This recipe is from Kubernetes Recipes, our 750-page practical guide with hundreds of production-ready patterns.

Luca Berton Ansible Pilot Ansible by Example Open Empower K8s Recipes Terraform Pilot CopyPasteLearn ProteinLens