| Package | Affected versions | Patched versions |
|---|---|---|
| github.com/kyverno/kyverno | ≤ 1.17.1all versions |
A Server-Side Request Forgery (SSRF) vulnerability in Kyverno allows authenticated users to induce the admission controller to send arbitrary HTTP requests to attacker-controlled endpoints.
When a ClusterPolicy uses apiCall.service.url with variable substitution (e.g. {{request.object.*}}), user-controlled input can influence the request target. The Kyverno admission controller executes these requests from its privileged network position without enforcing any validation or network restrictions.
The issue becomes non-blind SSRF, as response data from internal services can be reflected back to the user via admission error messages.
Kyverno supports variable substitution in apiCall.service.url, a documented feature intended to enable dynamic external lookups during admission control.
However, the current implementation lacks fundamental safeguards in the HTTP execution path:
No URL validation
User-controlled input is directly embedded into the request URL without validation or normalization.
No IP filtering
Requests can target:
127.0.0.1)169.254.0.0/16)Redirect handling not restricted
The Go HTTP client uses default redirect behavior (CheckRedirect == nil), allowing up to 10 redirects without re-validation of the target.
Response data reflection in admission errors
Response bodies are propagated back to the user in admission responses under certain conditions.
The vulnerability is non-blind through two mechanisms:
Non-2xx responses
Response body is returned in admission error messages (e.g. executor.go:98-101)
2xx responses with non-JSON content
Parsing failures (JSON/JMESPath) include response snippets in error output
This allows attackers to retrieve data from internal services directly via kubectl output.
Running one of these products? Scan your site to see whether it exposes a vulnerable version.
Scan my site freeClusterPolicy using:apiCall:
service:
url: "http://{{ request.object.metadata.annotations.target }}"
apiVersion: v1
kind: Pod
metadata:
name: ssrf-test
annotations:
target: "169.254.169.254/latest/meta-data/iam/security-credentials/"
spec:
containers:
- name: test
image: nginx
kubectl apply -f pod.yaml
Example output:
Error from server: admission webhook "kyverno" denied the request:
failed to process apiCall: <response body from metadata service>
apiCall.service.url and variable substitutionThis issue can be combined with automatic ServiceAccount token forwarding (reported separately) to form a critical attack chain.