Skip to content

GHSA-q93q-v844-jrqp BIT-kyverno-2026-40868 CVE-2026-40868 GO-2026-5575

kyverno apicall servicecall implicit bearer token injection leaks kyverno serviceaccount token

High Go
Severity
8.1 / 10
High · CVSS 3.1
Exploit chance (EPSS)
0.29%
Chance of exploitation in the next 30 days. Higher than 21.55% of scored vulnerabilities.
Known exploited
No
Not in CISA's catalog
Weakness
CWE-441 Unintended Proxy or Intermediary ('Confused Deputy')
CWE-922 Insecure Storage of Sensitive Information
Fix
1.17.0
Upgrade github.com/kyverno/kyverno to this version or later

Description

kyverno’s apiCall servicecall helper implicitly injects Authorization: Bearer ... using the kyverno controller serviceaccount token when a policy does not explicitly set an Authorization header. because context.apiCall.service.url is policy-controlled, this can send the kyverno serviceaccount token to an attacker-controlled endpoint (confused deputy).

namespaced policies are blocked from servicecall usage by the namespaced urlPath gate in pkg/engine/apicall/apiCall.go, so this report is scoped to ClusterPolicy and global context usage.

attacker model

the attacker can create or update a ClusterPolicy (or create a GlobalContextEntry) which uses context.apiCall.service.url and can choose the request URL and headers. a cross-boundary framing for real deployments is gitops: if the policy repo/controller is compromised, the ClusterPolicy/global context entry becomes untrusted input to kyverno.

relevant links

root cause

in (*executor).addHTTPHeaders, kyverno reads the serviceaccount token from /var/run/secrets/kubernetes.io/serviceaccount/token and injects it when the outgoing request has no Authorization header:

if req.Header.Get("Authorization") == "" {
  token := a.getToken()
  if token != "" {
    req.Header.Add("Authorization", "Bearer "+token)
  }
}

proof of concept

the attached poc.zip is a reproducible cluster PoC. it uses an in-cluster HTTP receiver which logs the Authorization header it receives. the PoC does not print token bytes; it only checks that the received header is non-empty and not equal to the negative control.

run (one command):

unzip poc.zip -d poc
cd poc
make test

canonical (expected: implicit token injection):

unzip poc.zip -d poc
cd poc
make canonical

expected output includes:

[CALLSITE_HIT]: executor.addHTTPHeaders Authorization=="" -> read_serviceaccount_token=true
[PROOF_MARKER]: authorization_header_injected=true token_nonempty=true

control (expected: explicit Authorization header disables auto-injection):

unzip poc.zip -d poc
cd poc
make control

expected output includes:

[CALLSITE_HIT]: executor.addHTTPHeaders Authorization!="" -> autoinject_skipped=true
[NC_MARKER]: authorization_header_injected=false

optional: the canonical run may also print an [RBAC]: ... line using kubectl auth can-i with the exfiltrated token, to show concrete privileges without exposing the token.

impact

token exfiltration: the kyverno controller serviceaccount token is sent to a policy-controlled endpoint. impact depends on the rbac bound to that serviceaccount in the target deployment.

recommended fix

do not auto-inject the kyverno serviceaccount token into policy-controlled servicecall requests. require explicit Authorization configuration, or enforce a strict allowlist of destinations where credentials may be attached and document the behavior.

workarounds

  • avoid using servicecall to arbitrary urls in policies.
  • set an explicit Authorization header in servicecall policies to prevent implicit token injection.

poc.zip PR_DESCRIPTION.md

oleh

Affected versions

Go

PackageVulnerableFixed in
github.com/kyverno/kyverno
< 1.17.0
1.17.0

How to fix

Move to the fixed version or later with your package manager, update the lockfile, and run your tests. If the package only arrives through another dependency, upgrade that dependency first. If none of its releases pulls a fixed version yet, force the version with your package manager's override.

github.com/kyverno/kyverno Go → 1.17.0

go
go get github.com/kyverno/kyverno@v1.17.0 && go mod tidy

Severity breakdown

CVSS 3.1 8.1

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N

Attack vector
Network
Attack complexity
Low
Privileges required
Low
User interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
High
Availability
None

Weakness

CWE-441: Unintended Proxy or Intermediary ('Confused Deputy')

The product receives a request, message, or directive from an upstream component, but the product does not sufficiently preserve the original source of the request before forwarding the request to an external actor that is outside of the product's control sphere. This causes the product to appear to be the source of the request, leading it to act as a proxy or other intermediary between the upstream component and the external actor.

How to prevent it
  • Architecture and Design: Enforce the use of strong mutual authentication mechanism between the two parties.
  • Architecture and Design: Whenever a product is an intermediary or proxy for transactions between two other components, the proxy core should not drop the identity of the initiator of the transaction. The immutability of the identity of the initiator must be maintained and should be forwarded all the way to the target.

CWE-922: Insecure Storage of Sensitive Information

The product stores sensitive information without properly limiting read or write access by unauthorized actors.

References

Timeline

  1. Published
  2. Last updated by the source
  3. Latest EPSS score
AdvisorySeverityWhy it's related
GHSA-79gf-7frw-68m9
Kyverno's NamespacedGeneratingPolicy generator.apply() namespace argument unvalidated -- background controller creates RoleBindings in any namespace including kube-system
Critical Also affects github.com/kyverno/kyverno
GHSA-fpjq-c37h-cqcv
Kyverno Controller Denial of Service via forEach Mutation Panic
High Also affects github.com/kyverno/kyverno
GHSA-8wfp-579w-6r25
Kyverno apiCall automatically forwards ServiceAccount token to external endpoints (credential leak)
High Also affects github.com/kyverno/kyverno
GHSA-f9g8-6ppc-pqq4
Kyverno: ServiceAccount token leaked to external servers via apiCall service URL
Critical Also affects github.com/kyverno/kyverno
GHSA-cvq5-hhx3-f99p
Kyverno: Cross-Namespace Read Bypasses RBAC Isolation (CVE-2026-22039 Incomplete Fix)
High Also affects github.com/kyverno/kyverno
GHSA-fmqp-4wfc-w3v7
Kyverno APICall SSRF Vulnerability Leading to Multi-Tenant Isolation Breach
Medium Also affects github.com/kyverno/kyverno
GHSA-qr4g-8hrp-c4rw
Kyverno has unrestricted outbound requests in Kyverno apiCall enabling SSRF
High Also affects github.com/kyverno/kyverno
GHSA-rggm-jjmc-3394
Kyverno has SSRF via CEL http.Get/http.Post in NamespacedValidatingPolicy allows cross-namespace data access
Critical Also affects github.com/kyverno/kyverno
Is this in your code?

MergeHarbor checks every repository's dependencies against this database, ranks what matters by exploitability and reachability, routes it to the owning team and opens the fix pull request.

Check your repos with MergeHarbor