OIDC trust policy without sub condition
Check ID: aws-iam-007
AWS-IAM-007 is an AWS security check performed by cloud-audit, an open-source AWS security scanner. Checks IAM roles with OIDC federation (GitHub Actions, GitLab CI, etc.) for missing 'sub' condition. Without it, any repository on the platform can assume the role.
Why it matters
Without a sub condition, any repository on the CI/CD platform can assume your AWS role. Google documented threat actor UNC6426 exploiting this exact pattern to escalate from package compromise to full AWS admin access. Datadog Security Labs found over 500 vulnerable roles across their customer base in 2024. The attack is trivial - an attacker only needs to create a repository and trigger a workflow to assume any unconstrained OIDC role. Even the UK Government Digital Service was affected, demonstrating this is not limited to small organizations.
Common causes
OIDC roles without sub conditions appear when engineers follow basic tutorials that only show the audience claim setup. The AWS documentation for GitHub Actions OIDC initially did not emphasize the sub condition, leading to widespread misconfiguration. Teams sometimes intentionally omit the sub filter to allow multiple repositories to share one role, not realizing this opens access to every repository on the platform.
Detection
Run cloud-audit to detect this issue:
pip install cloud-audit
cloud-audit scan -R The -R flag includes remediation details for every finding, including this one.
Remediation: AWS CLI
aws iam get-role --role-name ROLE_NAME --query 'Role.AssumeRolePolicyDocument' > trust-policy.json
# Add to Condition.StringEquals:
# "token.actions.githubusercontent.com:sub": "repo:YOUR_ORG/YOUR_REPO:ref:refs/heads/main"
aws iam update-assume-role-policy --role-name ROLE_NAME --policy-document file://trust-policy.json Remediation: Terraform
resource "aws_iam_role" "ci_role" {
name = "ci-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = { Federated = "arn:aws:iam::ACCOUNT:oidc-provider/token.actions.githubusercontent.com" }
Action = "sts:AssumeRoleWithWebIdentity"
Condition = {
StringEquals = {
"token.actions.githubusercontent.com:aud" = "sts.amazonaws.com"
"token.actions.githubusercontent.com:sub" = "repo:YOUR_ORG/YOUR_REPO:ref:refs/heads/main"
}
}
}]
})
} This check is part of cloud-audit - install with pip install cloud-audit
Related article
GitHub Actions OIDC AWS Backdoor: 8 Out of 10 Accounts →