Kyverno has unrestricted outbound requests in Kyverno apiCall enabling SSRFGHSA-qr4g-8hrp-c4rw
HIGHGHSA-qr4g-8hrp-c4rw is a high-severity (CVSS 7.7) Server-Side Request Forgery (SSRF) vulnerability in github.com/kyverno/kyverno. The records list no fixed version yet; check the vendor advisory below and apply the mitigations in the meantime.
Exploitation Status
No confirmed exploitation observed yet
- CISA’s own triage has not observed active exploitation or public proof-of-concept code for this CVE as of its last assessment.
Exploitation and automatability from CISA’s SSVC triage for GHSA-qr4g-8hrp-c4rw.
EPSS Exploitation Probability
Probability of exploitation in the next 30 days, from FIRST.org EPSS.
How urgent is this, really
Where this sits among everything scored
Real-World Exposure
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, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Remediation status
The records we use list no patched version of github.com/kyverno/kyverno for GHSA-qr4g-8hrp-c4rw. Check the maintainer's advisory, and where your build allows, override or pin the dependency away from the vulnerable range.
Mitigate without a patch
Restrict outbound requests from the affected component to an allowlist of hosts, block access to link-local and internal address ranges at the network layer, and require authentication on internal services so a forged request cannot reach them unauthenticated.
Fixing This On Your OS
If you run this on a Linux distribution, patch through your package manager against the distro's own security advisory below — it tracks the exact backported fix for your release, which can ship on a different timeline (and sometimes a different severity) than the upstream project.
This vulnerability is rated Important because authenticated users can exploit a Server-Side Request Forgery (SSRF) in Kyverno's apiCall.service.url via variable substitution. This allows attackers to make arbitrary HTTP requests to internal services, cloud metadata endpoints, and loopback addresses, leading to…
Ensure that no policy interpolates request-controlled data into apiCall.service.url. Audit all Policy, ClusterPolicy, and GlobalContextEntry resources for {{ }} expressions in that field and replace them with static URLs. Where a dynamic value is genuinely required, move it into the request body or a header rather than the URL, or constrain it to a fixed allowlist of permitted values before substitution. Enforce this going forward with a ValidatingAdmissionPolicy that rejects policies containing variable substitution in apiCall.service.url.Source: Red Hat security advisory for GHSA-qr4g-8hrp-c4rw (CC BY 4.0)
Frequently Asked Questions
Is GHSA-qr4g-8hrp-c4rw in your dependencies?
Find it across Go, including transitive dependencies.