This blog will contain a host of informations about various vulnerabilities and thoughts related to vulnerability management.
2025-03-26
Before we dive into the core of the subject, please note that this blog post slightly deviates from my usual style. At the time of writing, my analysis is not complete, but I believe the insights I've gathered so far can help defenders better understand the vulnerability resulting in more informed decision-making.
To view older blog posts, please visit the archives section.
Also, I want to clarify that I am not a Kubernetes expert, nor a Go developer. This is a "best effort with the available time I have" kind of approach, written with the sole intention of being helpful, especially since very little technical information is currently available about this vulnerability.
It’s also important to acknowledge that the release notes for ingress-nginx v1.12.1 (the version that fixes CVE-2025-1974) mention that several vulnerabilities were addressed:
• CVE-2025-1097
• CVE-2025-1098
• CVE-2025-1974
• CVE-2025-24513
• CVE-2025-24514
A closer look at the descriptions of these vulnerabilities suggests they might be related. This raises, though unconfirmed in this analysis, the possibility of a recurring pattern or systemic issue in the ingress-nginx codebase. I currently suspect that CVE-2025-1974 received more attention than the others primarily because it does not require authentication.
The official description of CVE-2025-1974 states:
A security issue was discovered in Kubernetes where, under certain conditions, an unauthenticated attacker with access to the pod network can achieve arbitrary code execution in the context of the ingress-nginx controller. This can lead to disclosure of Secrets accessible to the controller. (Note that in the default installation, the controller can access all Secrets cluster-wide.)
For those unfamiliar with Kubernetes, this description may raise several questions. Below are a few key questions along with short answers and documentation links:
What is the “pod network”?
The pod network is the internal network within a Kubernetes cluster that allows all pods to communicate with each other. This network is not directly exposed to the outside world. To allow external traffic into the cluster, a Gateway API (or Ingress, in older setups) must be configured.
More information: Kubernetes Networking
What is the ingress-nginx controller?
The ingress-nginx controller is an Ingress controller built on top of NGINX. It provides reverse proxy and load balancing services, enabling external users to access internal Kubernetes services.
More information: ingress-nginx GitHub
What does "in the context of ingress-nginx" mean?
This means any code execution that results from the vulnerability will run with the same privileges as the ingress-nginx controller which, by default, runs with relatively high privileges.
To exploit this vulnerability, the attacker must be able to send network traffic from within the pod network. This can typically be achieved by:
• Having legitimate access to a pod.
• Exploiting a misconfigured network policy.
• Exploiting a vulnerable service inside the cluster that allows arbitrary network egress.
The CVSS analysis lists the attack vector as “network.” However, in many real-world environments, the appropriate classification might be “adjacent,” since the pod network is not publicly accessible by default.
Similarly, while the CVSS metric lists "no privileges required," this is also highly dependent on your environment. In most clusters, some minimal privilege is required to reach the pod network. Therefore, depending on your context, the true CVSS score could range from 8 to 10 using CVSS 3.1.
The vulnerability was addressed in this pull request.
A close inspection of the PR reveals the following snippet in the CheckIngress function:
if err != nil {
n.metricCollector.IncCheckErrorCount(ing.ObjectMeta.Namespace, ing.Name)
return err
}
/* Deactivated to mitigate CVE-2025-1974
// TODO: Implement sandboxing so this test can be done safely
err = n.testTemplate(content)
if err != nil {
n.metricCollector.IncCheckErrorCount(ing.ObjectMeta.Namespace, ing.Name)
return err
}
*/
As shown above (and as partially stated in the v1.12.1 changelog), the patch simply disables template validation at least for unauthenticated input. This is likely a temporary mitigation, not a complete fix. It is reasonable to expect a follow-up patch in the future.
Note that this change does reduce functionality: previously, the controller would test incoming configuration using NGINX itself. This capability is now disabled to avoid exploitation.
Here’s the call chain that allowed unauthenticated users to trigger it before the patch:
• Test
And here’s the end of the call chain where the attacker-supplied configuration is tested via nginx -t:
// Test checks if config file is a syntax valid nginx configuration
func (nc NginxCommand) Test(cfg string) ([]byte, error) {
//nolint:gosec // Ignore G204 error
return exec.Command(nc.Binary, "-c", cfg, "-t").CombinedOutput()
}
This could be triggered simply by posting to the webhook endpoint (which requires no authentication):
curl -k -X POST https://victim.com:8443/validate \
-H "Content-Type: application/json" \
--data admission-review.json
The -t flag tells NGINX to test the configuration file. From the official documentation:
nginx checks the configuration for correct syntax, and then tries to open files referred to in the configuration.
This implies a deeper level of system interaction than many people realize especially if the configuration is user-controlled. While I haven’t fully audited the internals of this flag, its behavior suggests that it should not be used with untrusted input.
I began reviewing the NGINX codebase for deeper insights but paused the effort due to time constraints.
This is a serious vulnerability.
If you are using ingress-nginx and the admission controller is exposed beyond the pod network, you are in immediate danger and should update to the latest version as soon as possible.
If the controller is only listening internally, you're in a better position but don't let your guard down. Attackers can use low-complexity vulnerabilities (e.g., SSRF) to pivot into the pod network and reach the admission controller. Update regardless.