Report #66129
[bug\_fix] AWS IAM Session Policy creates implicit deny despite role having full permissions
Remove or expand the restrictive SessionPolicy JSON passed during the STS AssumeRole API call, or check that Service Control Policies \(SCPs\) attached to the account are not blocking the action. The root cause is that when assuming a role, the SessionPolicy acts as a permissions boundary that intersects with \(ANDs with\) the role's identity-based policies; if the SessionPolicy does not explicitly allow the required action, it creates an effective deny even if the role itself has full AdministratorAccess. Additionally, SCPs can block the action regardless of the session policy.
Journey Context:
You have a CI/CD pipeline running in GitHub Actions that uses OIDC to assume an IAM role in your AWS account to perform CloudFormation deployments. The role has the managed policy 'AdministratorAccess' attached. The pipeline starts failing with 'is not authorized to perform: cloudformation:CreateChangeSet on resource: arn:aws:cloudformation:us-east-1:123456789012:stack/MyStack/\* because no identity-based policy allows the action.' You examine the role's permissions—AdministratorAccess is definitely there. You check the Trust Policy—it allows the OIDC provider. You look at the error's RequestId and use the IAM Policy Simulator, which bizarrely shows that the role should be allowed to perform the action. You then notice in the AssumeRoleWithWebIdentity call in your workflow YAML that you are passing a session-policy inline JSON that restricts permissions to only 's3:GetObject' and 's3:PutObject' for security reasons \(a 'scoped' deployment role\). You realize that the SessionPolicy passed during AssumeRole acts as a filter; it restricts the effective permissions to the intersection of the role's policies AND the session policy. Even though the role has AdministratorAccess, the session policy only permits S3 actions, effectively creating an implicit deny for CloudFormation. You remove the restrictive session policy from the AssumeRole call \(or expand it to include cloudformation:\*\), and the deployment succeeds.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-20T17:28:35.549902+00:00— report_created — created