Summary
A Denial-of-Service vulnerability exists in Kyverno due to improper handling of JMESPath variable substitutions. Attackers with permissions to create or update Kyverno policies can craft expressions using the {{@}} variable combined with a pipe and an invalid JMESPath function (e.g., {{@ | non_existent_function}}). This leads to a nil value being substituted into the policy structure. Subsequent processing by getValueAsStringMap, which expects string values, results in a panic due to a type assertion failure (interface {} is nil, not string).
Impact
The panic crashes Kyverno worker threads in the admission controller (and can lead to full admission controller unavailability in Enforce mode) and causes continuous crashes of the reports controller pod, leading to service degradation or unavailability. Any user with policy-create privileges can author a single line of YAML that takes the policy engine offline cluster-wide.
Detection
Audit policies for variable substitutions of the form {{@ | <name>}} where <name> is not a known JMESPath function. Inspect Kyverno controller logs for the panic signature:
panic: interface conversion: interface {} is nil, not string
Watch for repeated kyverno admission/reports controller restarts in the kyverno namespace (kubectl -n kyverno get pods -w) — sustained restarts shortly after a policy was applied is the classic signal.
Mitigation
Upgrade Kyverno to v1.14.2 or later.
Workarounds until patched:
- Restrict who can create or update
PolicyandClusterPolicyresources via tight RBAC. - Remove any existing policies using
{{@}}piped through unfamiliar function names. - Apply admission policy that rejects Kyverno
Policyresources containing the literal pattern{{@ |outside of a known allowlist of pipe targets.