kyverno: [BUG] Kyverno is updating quotes and backslashes on unrelated fields in unrelated list items

Software version numbers

  • Kubernetes version: n/a
  • Kubernetes platform (if applicable; ex., EKS, GKE, OpenShift): n/a
  • Kyverno version: v.1.5.8

Describe the bug Kyverno is changing quotes and backslashes in fields that should not be mutated, even in list items that should be filtered out of the mutation entirely.

Also, all tests pass when the patchedResource contains the original contents of the string that should not change.

To Reproduce Steps to reproduce the behaviour:

  1. Test resource:
apiVersion: v1
kind: Pod
metadata:
  name: pod-1
spec:
  containers:
    - command:
        - sh
        - -c
        - trap "exit 0" INT; while true; do sleep 30; done;
      image: alpine
      name: container-1-a
    - args:
        - "hadoop fs -count s3a://test/run_date_2021-01-01__* | grep run_date | jq --raw-input 'capture(\"\\\\s*[0-9]+\\\\s*[0-9]+\\\\s*(?<size>[0-9]+).*__date_(?<date>[0-9-]{10}+)-(?<hour>[0-9]{2}).*$\")' | jq -n -c '{\"listings\": [inputs]}' > return.json"
      command:
        - bash
        - -c
      image: apache/hadoop:3
      imagePullPolicy: IfNotPresent
      name: container-1-b
  restartPolicy: Never
  1. Policy

Tried with both these versions of a policy, to see if using foreach skipped the item entirely without changing it, but the result is the same

Version 1

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: set-alpine-version-policy-1
spec:
  failurePolicy: Ignore
  rules:
    - name: set-alpine-version-tag
      match:
        resources:
          kinds:
          - Pod
      mutate:
        patchStrategicMerge:
          spec:
            containers:
              - (name): "*"
                (image): "alpine | alpine:latest"
                image: "alpine:3.15.0"
                imagePullPolicy: IfNotPresent

Version 2

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: set-alpine-version-policy-2
spec:
  failurePolicy: Ignore
  rules:
    - name: set-alpine-version-tag
      match:
        resources:
          kinds:
          - Pod
      mutate:
        foreach:
          - list: "request.object.spec.containers[?image == 'alpine' || image == 'alpine:latest']"
            patchStrategicMerge:
              spec:
                containers:
                  - name: "{{element.name}}"
                    image: "alpine:3.15.0"
                    imagePullPolicy: IfNotPresent

  1. Run kyverno apply for each policy on the resource

  2. The content of the args field on container container-1-b gets changed when it shouldn’t (some quotes changed and added, some backslashes removed). The result from running kyverno apply is as follows:

apiVersion: v1
kind: Pod
metadata:
  name: pod-1
  namespace: default
spec:
  containers:
  - command:
    - sh
    - -c
    - trap "exit 0" INT; while true; do sleep 30; done;
    image: alpine:3.15.0
    imagePullPolicy: IfNotPresent
    name: container-1-a
  - args:
    - 'hadoop fs -count s3a://test/run_date_2021-01-01__* | grep run_date | jq --raw-input
      ''capture("\\s*[0-9]+\\s*[0-9]+\\s*(?<size>[0-9]+).*__date_(?<date>[0-9-]{10}+)-(?<hour>[0-9]{2}).*$")''
      | jq -n -c ''{"listings": [inputs]}'' > return.json'
    command:
    - bash
    - -c
    image: apache/hadoop:3
    imagePullPolicy: IfNotPresent
    name: container-1-b
  restartPolicy: Never
  1. Running kyverno testwith the patchedResource from the expected behaviour pass for both policy versions, and should fail

Expected behavior

The mutated resource should look like this (and tests should fail if this is the content of the patchedResource):

apiVersion: v1
kind: Pod
metadata:
  name: pod-1
spec:
  containers:
    - command:
        - sh
        - -c
        - trap "exit 0" INT; while true; do sleep 30; done;
      image: alpine:3.15.0
      imagePullPolicy: IfNotPresent
      name: container-1-a
    - args:
        - "hadoop fs -count s3a://test/run_date_2021-01-01__* | grep run_date | jq --raw-input 'capture(\"\\\\s*[0-9]+\\\\s*[0-9]+\\\\s*(?<size>[0-9]+).*__date_(?<date>[0-9-]{10}+)-(?<hour>[0-9]{2}).*$\")' | jq -n -c '{\"listings\": [inputs]}' > return.json"
      command:
        - bash
        - -c
      image: apache/hadoop:3
      imagePullPolicy: IfNotPresent
      name: container-1-b

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 17 (14 by maintainers)

Most upvoted comments

EDIT: sorry, this is the Kubernetes API, it happens even without Kyverno running (although running it through Kyverno CLI apply produces the same result)

@chipzoller I narrowed the problem down to a string like a: b, this alone is causing the error. If you remove the single : from that string, or even just the space after the colon, the problem disappears.

So, to make your test easier, you can replace the problematic string above with just

"echo 'foo: bar'"

and Kyverno CLI apply changes it to

'echo ''a: b'''

It actually duplicates all single quotes, in another example, the string

"echo 'foo: bar' | echo 'baz'"

generates

'echo ''foo: bar'' | echo ''baz'''

Right, I understand, I just put the previous reply together to illustrate where the problem is from Kyverno’s side, and it’s not the replacement of the angle brackets. This is just to clarify where we need to look.

Kubernetes API server is “sanitizing” the arg with the jq command string because of the double single quotes. So this isn’t a Kyverno issue.