[Bug] [CLI] kyverno test mutates the trigger resource for MutatingPolicy targetMatchConstraints
Kyverno CLI version
Current main: c51c8f6fd10824a2560819553b78ac0d4f80a652.
Description
kyverno test evaluates a MutatingPolicy with active targetMatchConstraints against the trigger itself before evaluating its selected targets. This can apply the target mutation to the trigger, or produce a schema error when the mutation is valid only for the target kind.
The trigger should drive matching and evaluation; the selected target should receive the mutation. A trigger that is not selected as a target should remain unchanged.
Steps to reproduce
Save these files in one directory and run kyverno test ..
policy.yaml
apiVersion: policies.kyverno.io/v1beta1
kind: MutatingPolicy
metadata:
name: mutate-existing-deployment-from-secret
spec:
evaluation:
mutateExisting:
enabled: true
matchConstraints:
resourceRules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE"]
resources: ["secrets"]
targetMatchConstraints:
resourceRules:
- apiGroups: ["apps"]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["deployments"]
mutations:
- patchType: ApplyConfiguration
applyConfiguration:
expression: >
Object{
metadata: Object.metadata{
labels: Object.metadata.labels{
mutated: "true"
}
},
spec: Object.spec{
replicas: 3
}
}trigger.yaml
apiVersion: v1
kind: Secret
metadata:
name: test-secret
namespace: test-ns
type: Opaque
data:
key: dmFsdWU=target.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-deploy
namespace: test-ns
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginxkyverno-test.yaml
apiVersion: cli.kyverno.io/v1alpha1
kind: Test
metadata:
name: secret-trigger-deployment-target
policies:
- policy.yaml
resources:
- trigger.yaml
results:
- isMutatingPolicy: true
kind: Deployment
policy: mutate-existing-deployment-from-secret
resources:
- test-ns/test-deploy
result: pass
targetResources:
- target.yamlActual and expected behavior
The YAML result row checks the Deployment only, so kyverno test can report success even when the trigger also undergoes inline mutation evaluation. Inspecting the CLI engine responses is necessary to assert trigger immutability.
The intended Deployment target should receive the label and replicas change. The Secret should receive neither a patched resource nor a failed target-shaped mutation rule. Removing the spec part of the mutation leaves a metadata-only variant that exposes the illicit trigger label directly.
Root cause
cmd/cli/kubectl-kyverno/processor/policy_processor.go calls eng.Handle(context.TODO(), request, nil) for the trigger. Both MutatingPolicy admission handlers instead use NoTargetMatchConstraintPolicy(), which excludes policies with active target constraints from inline mutation. The CLI's subsequent target Evaluate loop is separate.
The same processor is shared by kyverno apply; this issue does not request adding mutate-existing target processing to apply.
Regression evidence
The direct runTest regression uses the checked-in test/cli/test-mutating-policy/mutate-existing fixture (Deployment trigger, ConfigMap target):
| Predicate | Trigger response | Target | Regression |
|---|---|---|---|
Current main's nil |
Two responses; the first patches Deployment test-ns/test-deploy with mutated=true |
ConfigMap test-ns/test-configmap receives mutated=true |
FAIL |
NoTargetMatchConstraintPolicy() |
One target-processing response; no inline trigger patch | Same target mutation succeeds | PASS |
| Restored fix after negative control | Same as fixed | Same target mutation succeeds | PASS |
For the Secret-to-Deployment manifests above, the YAML test reports Pass on both builds. A supplementary kyverno apply policy.yaml --resource trigger.yaml -o out.yaml exercise of the same processor on current main reports .spec: field not declared in schema because it attempts the Deployment-shaped patch on the Secret. Removing spec from the mutation produces an output Secret with metadata.labels.mutated: "true", despite Secrets not being selected as targets. These apply observations are separate from the direct runTest regression; they do not establish mutate-existing target support in apply.
This report is limited to the CLI path. Admission already excludes these policies from inline mutation.
Source: kyverno/kyverno