Pin the IRSA sub Condition, or Any Pod Can Assume the Role

An IRSA trust policy without an exact sub condition trusts every service account in the cluster.

  • Kubernetes
  • EKS
  • IAM

IAM Roles for Service Accounts (IRSA) lets a pod on Amazon EKS assume an IAM role by exchanging its service account token through the cluster's OIDC provider. The role's trust policy decides which service accounts are allowed to do that.

The mistake: a trust policy that names the cluster's OIDC provider but leaves out the sub condition, or matches it with a wildcard such as system:serviceaccount:*:*. That trusts every service account in the cluster, so any pod that can obtain a token for the sts.amazonaws.com audience can assume the role.

Pin both claims exactly:

"Condition": {
  "StringEquals": {
    "oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:sub": "system:serviceaccount:payments:payments-api",
    "oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:aud": "sts.amazonaws.com"
  }
}

Also:

  • Use StringEquals, not StringLike, unless you genuinely need a pattern, and then keep the pattern to one namespace.
  • Give each workload its own role. A role shared across service accounts shares its permissions too.
  • Audit existing roles: look for trust policies that reference the cluster's OIDC provider without a :sub condition.
  • EKS Pod Identity, the newer alternative, scopes roles through pod identity associations (namespace plus service account) rather than trust-policy conditions, which removes this particular mistake.

More context: Kubernetes and container security guardrails

Get in touch