#17797·kyverno

[Bug] Naming a subresource in matchConstraints silently disables autogen for pod controllers

Author: mashiofu-cafexCreated Sep 30, 2026Updated Sep 30, 2026

Kyverno Version

1.19.1 (chart kyverno 3.9.1), Kubernetes v1.26.1 on minikube.

Description

Naming a subresource in matchConstraints.resourceRules[].resources causes status.autogen to come back empty, so no rules are generated for pod controllers. The generated webhook then drops apps and batch entirely, and Deployments, Jobs, CronJobs, DaemonSets, StatefulSets and ReplicaSets stop being validated.

The loss is silent. With evaluation.background.enabled: false the policy reports ready: true with both conditions healthy, so nothing indicates that controller coverage has gone.

We hit this migrating a ClusterPolicy that restricted image registries. The legacy policy's webhook registered pods/ephemeralcontainers alongside the controller kinds, so kubectl debug was covered. Adding the subresource to the CEL policy to restore that silently removed Deployment coverage instead — strictly worse than the gap we were closing.

Steps to reproduce

Two policies, identical apart from resources:

yaml
apiVersion: policies.kyverno.io/v1beta1
kind: ValidatingPolicy
metadata:
  name: repro-pods-only
spec:
  validationActions: [Deny]
  matchConstraints:
    resourceRules:
    - apiGroups: [""]
      apiVersions: [v1]
      operations: [CREATE, UPDATE]
      resources: [pods]
  validations:
  - expression: "object.spec.containers.all(c, c.image.startsWith('example.com/'))"
    message: "bad registry"
---
apiVersion: policies.kyverno.io/v1beta1
kind: ValidatingPolicy
metadata:
  name: repro-subresource
spec:
  validationActions: [Deny]
  evaluation:
    background:
      enabled: false          # so the policy reports fully Ready, see below
  matchConstraints:
    resourceRules:
    - apiGroups: [""]
      apiVersions: [v1]
      operations: [CREATE, UPDATE]
      resources: [pods, pods/ephemeralcontainers]
  validations:
  - expression: "object.spec.containers.all(c, c.image.startsWith('example.com/'))"
    message: "bad registry"
$ kubectl get validatingpolicy repro-pods-only   -o jsonpath='{.status.autogen.configs}'
{"cronjobs":{...},"defaults":{...}}

$ kubectl get validatingpolicy repro-subresource -o jsonpath='{.status.autogen.configs}'
                                    # empty
$ kubectl get validatingpolicy repro-subresource -o jsonpath='{.status.conditionStatus.ready}'
true

Generated webhook rules, from the equivalent pair in our chart:

resources webhook registers
[pods] pods, daemonsets, deployments, replicasets, statefulsets, cronjobs, jobs
[pods, pods/ephemeralcontainers] pods, pods/ephemeralcontainers only

A Deployment whose pod template violates the policy is denied under the first and admitted under the second.

Putting the subresource in its own resourceRules entry, rather than alongside pods, behaves identically.

Expected behavior

The pods entry should still autogenerate rules for pod controllers regardless of any other entry naming a subresource. Failing that, the policy should report that autogen was skipped, rather than reporting ready: true with no controller coverage.

Note on the ready status

Without evaluation.background.enabled: false, the same policy reports ready: false with:

RBACPermissionsGranted  False  Policy is not ready for reporting, missing permissions:
                               get /v1, Resource=pods/ephemeralcontainers: ; list /v1

which at least signals that something is wrong, though it says nothing about autogen. With background scanning disabled that condition passes ("Background scanning disabled; reporting permissions not required"), WebhookConfigured is also true, and the missing autogen is then completely silent.

Possibly related

#16175 — autogen not generated when namespaceSelector is used. Different trigger, same symptom of autogen silently producing nothing when matchConstraints contains something it does not handle.

Workaround

Split into two policies: one scoped to pods that keeps its autogen, and a companion scoped to the subresource only.