# R-SEC-02 — the conformance CI trigger cannot escalate to arbitrary privileged execution. # # Each DENY case below is a real escalation path, not a style violation. The one that matters # most is `evil-command`: correct SA, correct image, arbitrary command. That is the attack the # whole model exists to stop, and RBAC alone cannot — Kubernetes places no `use` check on # serviceAccountName, so `create jobs` in this namespace IS the privileged identity without # this policy. # # user-info.yaml supplies the requesting identity. WITHOUT it the policy's `subjects` match # never fires and every case trivially passes — a test that proves nothing. apiVersion: cli.kyverno.io/v1alpha1 kind: Test metadata: name: conformance-trigger-job-shape policies: - ../../admission/conformance-trigger-job-shape.yaml resources: - resources.yaml userinfo: user-info.yaml results: # ---- the committed run is ADMITTED ---- # `real-template` is conformance/incluster/chainsaw-job.yaml as the CI trigger renders it: # init container + env-from-secretKeyRef credential + the two allowed volumes. It is here # so a template that drifts OUT of admission fails `make -C ci l0` rather than failing at # 2am against the live cluster. `good-run` remains the minimal shape. - policy: conformance-trigger-job-shape rule: trigger-may-create-only-the-committed-conformance-run kind: Job resources: [good-run, real-template] result: pass - policy: conformance-trigger-job-shape rule: trigger-volumes-must-be-workspace-or-results kind: Job resources: [good-run, real-template] result: pass - policy: conformance-trigger-job-shape rule: trigger-args-must-be-the-committed-flags kind: Job resources: [good-run, real-template] result: pass # `real-template` is the only fixture WITH an init container, so it is the only one this # rule reports on — a foreach over an absent list yields no result at all, which is why # `good-run` is not listed here. - policy: conformance-trigger-job-shape rule: trigger-initcontainers-must-be-the-committed-clone-step kind: Job resources: [real-template] result: pass - policy: conformance-trigger-job-shape rule: trigger-may-not-declare-ephemeral-containers kind: Job resources: [good-run, real-template] result: pass # Only `real-template` sets env, so it is the only fixture this rule reports a pass on. - policy: conformance-trigger-job-shape rule: trigger-env-names-must-be-the-committed-set kind: Job resources: [real-template] result: pass - policy: conformance-trigger-job-shape rule: trigger-may-not-use-envfrom kind: Job resources: [good-run, real-template] result: pass # ---- THE escalation: runner SA + arbitrary command ---- - policy: conformance-trigger-job-shape rule: trigger-may-create-only-the-committed-conformance-run kind: Job resources: [evil-command, evil-image, tag-not-digest, host-namespaces] result: fail # ---- an extra volume is the way out of a constrained pod ---- - policy: conformance-trigger-job-shape rule: trigger-volumes-must-be-workspace-or-results kind: Job resources: [extra-volume] result: fail # ---- args beyond the committed flags ---- - policy: conformance-trigger-job-shape rule: trigger-args-must-be-the-committed-flags kind: Job resources: [injected-args] result: fail # ---- THE SAME ESCALATION VIA `initContainers`, which the three rules above all miss ---- # Each of these has a fully compliant `containers[0]` and was ADMITTED (pass 3, fail 0) # before `trigger-initcontainers-must-be-the-committed-clone-step` existed. `evil-initcontainer` # is the coordinator's independent reproduction; keeping it here is what stops the hole # reopening. - policy: conformance-trigger-job-shape rule: trigger-initcontainers-must-be-the-committed-clone-step kind: Job resources: [evil-initcontainer, initcontainer-with-args, second-initcontainer] result: fail # ---- and via the third container list nobody was reading ---- - policy: conformance-trigger-job-shape rule: trigger-may-not-declare-ephemeral-containers kind: Job resources: [evil-ephemeral-container] result: fail # ---- and via `env`, the same mistake a third time ---- # `command` is pinned, so the injection moves to a variable the pinned command honours. # BASH_ENV is sourced by bash before a non-interactive script, so it alone is arbitrary code # execution as conformance-runner. Note `injected-initcontainer-env` PASSES the initContainer # rule — its container shape is perfect and only its env is hostile, which is exactly why the # env rule has to exist separately. - policy: conformance-trigger-job-shape rule: trigger-env-names-must-be-the-committed-set kind: Job resources: [injected-env, injected-initcontainer-env] result: fail - policy: conformance-trigger-job-shape rule: trigger-may-not-use-envfrom kind: Job resources: [envfrom-whole-secret] result: fail