#17142·kyverno

[Bug] Empty arrays bypass pattern-based validation — Enforce policies silently pass

Author: amartyatatspandeyCreated Aug 14, 2026Updated Sep 19, 2026
Labelsbugvalidationtriagetype_legacy

Kyverno Version

1.16.4

Kubernetes Version

1.28.x

Kubernetes Platform

EKS

Kyverno Rule Type

Validate

Description

When a resource field is an empty array, Kyverno's pattern validation treats the pattern as satisfied without ever checking it. This applies both to scalar patterns (replicas: 3 vs replicas: []) and to object patterns inside arrays (containers: [{securityContext: {runAsNonRoot: true}}] vs containers: []). An Enforce validation rule intended to require a value is silently satisfied by an empty array — an enforcement bypass for any field that can legitimately be empty (initContainers, volumes, env, args, imagePullSecrets, or any unconstrained CRD field).

This is inconsistent with a missing field: a non-optional pattern key that is absent fails validation, but the same key set to [] passes.

Root cause: pkg/engine/validate/validate.govalidateResourceElement and validateArray / validateArrayOfMaps.

  • Scalar pattern vs array resource: the elementary-values branch (case string, float64, int, int64, bool, nil, lines 92–107) ranges over the resource array and returns nil if the loop never runs.
  • Object pattern vs empty resource array: validateArray (line 205) dispatches to validateArrayOfMaps (lines 260–288), which likewise iterates zero times and returns "" , nil (pass).

Execution path: MatchPatternvalidateResourceElementfor _, res := range resource { ... } / for i, resourceElement := range resourceMapArray → empty loop → return "", nilRulePass.

Verified behavior (engine-level, via MatchPattern):

scalar pattern vs empty array:        err=<nil>  → PASS
map pattern vs empty array:           err=<nil>  → PASS
scalar pattern vs non-empty mismatch: err=...    → FAIL
missing (omitted) field vs map pattern:          → FAIL

Actual behavior

The engine records Pass; the intended requirement is silently unenforced whenever the empty array is present on the object the engine sees.

Additional context

  • Existing tests never exercise the empty-array case: validate_test.go array cases (TestValidateMap_*, TestValidateMapElement_*) all use non-empty arrays.
  • Suggested fix: in the elementary-values []interface{} resource branch of validateResourceElement, return an error when len(resource) == 0 (or only pass for wildcard patterns); likewise treat an empty resource array as a pattern failure in validateArrayOfMaps when the pattern is not purely anchor-based.
  • Suggested regression test: TestValidateMap_EmptyArrayFails with the pattern/resource above, asserting MatchPattern returns an error.

Steps to reproduce

Steps to reproduce

Use kyverno apply (or a unit test calling MatchPattern). Do not rely on kubectl apply of a native Pod: the API server typically omits empty slices (json:",omitempty"), so initContainers: [] becomes a missing field and the pattern fails (blocked) instead of bypassing. The bypass is the empty-array case the engine actually sees.

  1. Save the policy and resource below.
  2. Run kyverno apply policy.yaml --resource pod.yaml.
  3. Observe that the resource passes even though the rule requires every initContainer to set runAsNonRoot: true.
yaml
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-initcontainer-nonroot
spec:
  validationFailureAction: Enforce
  rules:
    - name: initcontainers-nonroot
      match:
        any:
          - resources:
              kinds:
                - Pod
      validate:
        message: "Every initContainer must set runAsNonRoot: true"
        pattern:
          spec:
            initContainers:
              - securityContext:
                  runAsNonRoot: true
yaml
apiVersion: v1
kind: Pod
metadata:
  name: demo
spec:
  initContainers: []   # empty array — bypasses the pattern in the engine
  containers:
    - name: app
      image: nginx

The same bypass applies to scalar patterns on CRDs with a permissive/absent schema, e.g. pattern spec.replicas: 3 vs. a resource with spec.replicas: [] (MatchPattern returns no error). Native Kubernetes integer fields like Deployment spec.replicas reject [] at schema validation, so that variant is CRD-only.

Expected behavior

Expected behavior

An empty array must not satisfy a pattern that requires elements with specific properties, and must not satisfy a scalar value pattern. The rule should record a failure and block admission under Enforce.

Screenshots

No response

Kyverno logs

bash
$ kyverno apply policy.yaml --resource pod.yaml --table --detailed-results --remove-color

Applying 3 policy rule(s) to 1 resource(s)...
│────│───────────────────────────────│────────────────────────│──────────────────│────────│────────│──────────────────────────────────────────────────│
│ ID │ POLICY                        │ RULE                   │ RESOURCE         │ RESULT │ REASON │ MESSAGE                                          │
│────│───────────────────────────────│────────────────────────│──────────────────│────────│────────│──────────────────────────────────────────────────│
│ 1  │ require-initcontainer-nonroot │ initcontainers-nonroot │ default/Pod/demo │ Pass   │        │ validation rule 'initcontainers-nonroot' passed. │
│────│───────────────────────────────│────────────────────────│──────────────────│────────│────────│──────────────────────────────────────────────────│

Slack discussion

No response

Troubleshooting

  • I have read and followed the documentation AND the troubleshooting guide.
  • I have searched other issues in this repository and mine is not recorded.