Cloud Security Wire
AWS Azure GCP RSS
AWS Misconfiguration high

AWS CloudFormation StackSets: Cross-Account IAM Privilege Escalation Paths and Hardening

CloudFormation StackSets enable deploying infrastructure templates across dozens of AWS accounts simultaneously — which makes them a high-value lateral movement target when the execution role is over-permissioned. This guide covers the IAM escalation paths from a compromised StackSets administrator role, how self-managed and service-managed deployments differ in attack surface, and the hardening steps that break each path.

By Editorial Team · ·
#AWS#CloudFormation#StackSets#IAM#privilege escalation#cross-account#lateral movement#cloud security#Organizations#hardening#2026
High Severity

This issue has been assessed as high severity. Review affected configurations immediately.

CloudFormation StackSets extend CloudFormation to deploy stacks across multiple AWS accounts and regions from a single administrator account. That capability — pushing infrastructure changes to dozens of accounts simultaneously — is also what makes StackSets an attractive pivot point for attackers who gain access to the administrator account or its IAM roles. A single IAM action executed through StackSets can instantiate attacker-controlled resources across an entire AWS Organization.

This guide covers the two StackSets deployment models, the IAM privilege escalation paths specific to each, and the configuration hardening that breaks each path.

How StackSets Work: Two Deployment Models

CloudFormation StackSets operates in two distinct modes that have different IAM architectures and different attack surfaces.

Self-managed StackSets require you to manually create two IAM roles:

  • AWSCloudFormationStackSetAdministrationRole — in the administrator account. Grants the right to assume the execution role in target accounts.
  • AWSCloudFormationStackSetExecutionRole — in each target account. Grants CloudFormation the permissions to create and modify resources in that account.

The trust relationship on the execution role is typically set to trust cloudformation.amazonaws.com and the administration account ID. The execution role’s permission policies determine what resources StackSets can create in target accounts.

Service-managed StackSets use AWS Organizations integration. AWS manages the execution role (AWSCloudFormationStackSetExecutionRole) automatically, granting it administrative-equivalent permissions in each member account. You don’t create or manage the execution role — which also means you don’t control what it can do.

Attack Surface: Self-Managed StackSets

Escalation Path 1: Over-Permissioned Execution Role

The AWSCloudFormationStackSetExecutionRole in target accounts is the principal that creates resources when a stack set is deployed. AWS’s own documentation provides an example policy granting AdministratorAccess to this role — and many organisations use exactly that.

An attacker who can assume the administration role (or compromise an IAM principal with cloudformation:CreateStackInstances permission) can deploy a CloudFormation template that creates resources in target accounts. With an admin-permissioned execution role, that template can:

  • Create a new IAM user with administrator privileges and an access key
  • Create or modify IAM roles with permissive trust policies
  • Deploy a Lambda function that exfiltrates data or creates backdoor access
  • Modify security group rules across target account VPCs

The escalation requires only cloudformation:CreateStackInstances or cloudformation:UpdateStackSet in the administrator account, plus any existing rights to modify the stack set template.

# An attacker with cloudformation:CreateStackInstances creates a stack instance
# in a target account using a template that establishes backdoor IAM access
aws cloudformation create-stack-instances \
  --stack-set-name existing-infra-stackset \
  --accounts 123456789012 \
  --regions us-east-1 \
  --parameter-overrides ParameterKey=AdminEmail,[email protected]

If the stack set template accepts parameters that flow into IAM resource definitions without validation — or if an attacker can modify the template itself — the blast radius is the execution role’s permissions multiplied by the number of target accounts.

Escalation Path 2: Trust Policy on Administration Role

The AWSCloudFormationStackSetAdministrationRole must be able to assume the execution role in every target account. Its trust policy typically allows sts:AssumeRole for the execution role ARN pattern arn:aws:iam::*:role/AWSCloudFormationStackSetExecutionRole.

If the administration role itself is over-permissioned beyond the minimum needed for StackSets operation, or if its trust policy allows assumption by overly broad principals, an attacker who can assume the role gains cross-account reach through the execution role chain.

Check who can assume the administration role:

# List the trust policy of the StackSets administration role
aws iam get-role \
  --role-name AWSCloudFormationStackSetAdministrationRole \
  --query 'Role.AssumeRolePolicyDocument'

Principals listed in Principal that are not explicitly cloudformation.amazonaws.com or tightly scoped represent unnecessary exposure.

Escalation Path 3: Writable Stack Set Templates in S3

CloudFormation templates are stored in S3 before deployment. If the S3 bucket containing existing stack set templates allows write access to principals beyond the CloudFormation service, an attacker with s3:PutObject on that bucket can replace a template with a malicious version that will be deployed to all target accounts at the next update.

# Identify S3 buckets used by existing stack sets
aws cloudformation describe-stack-set \
  --stack-set-name your-stack-set-name \
  --query 'StackSet.TemplateURL'

If the TemplateURL points to an S3 path, verify the bucket policy restricts writes to the deployment pipeline principal only.

Attack Surface: Service-Managed StackSets

Service-managed StackSets use an automatically provisioned execution role in each member account. AWS grants this role AdministratorAccess — it is designed for complete infrastructure management. There is no option to scope this role’s permissions down.

The implication: any IAM principal in the management account that can create or update a service-managed stack set has indirect AdministratorAccess to every member account in the Organisation.

# An attacker with cloudformation:CreateStackInstances in the management account
# can deploy to ALL accounts in the org — the execution role is always AdministratorAccess
aws cloudformation create-stack-instances \
  --stack-set-name service-managed-stackset \
  --deployment-targets OrganizationalUnitIds=ou-xxxx-yyyyyyyy \
  --regions us-east-1

Audit who has these CloudFormation permissions in your management account:

# Find IAM entities with cloudformation:CreateStackInstances in the management account
aws iam get-account-authorization-details \
  --filter LocalManagedPolicy AWSManagedPolicy \
  | jq '.PolicyDetailList[] | select(.PolicyDocument.Statement[].Action | contains("cloudformation:CreateStackInstances"))'

Hardening Steps

1. Scope Execution Role Permissions Down

Replace AdministratorAccess on the execution role with a least-privilege policy matching what your stack set templates actually create. A stack set that only creates S3 buckets with specific configurations needs s3:CreateBucket, s3:PutBucketPolicy, and s3:PutBucketVersioning — not AdministratorAccess.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:CreateBucket",
        "s3:PutBucketPolicy",
        "s3:PutBucketVersioning",
        "s3:PutBucketTagging"
      ],
      "Resource": "arn:aws:s3:::*"
    }
  ]
}

Audit existing execution role policies quarterly as stack set templates evolve.

2. Restrict Who Can Assume the Administration Role

The administration role’s trust policy should be explicit:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "cloudformation.amazonaws.com"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "aws:SourceAccount": "YOUR_ADMIN_ACCOUNT_ID"
        }
      }
    }
  ]
}

Remove any human IAM users or roles from the trust policy. StackSets does not require human principals to directly assume this role.

3. Use AWS CloudFormation Hooks for Template Validation

CloudFormation Hooks intercept stack operations before resources are created, modified, or deleted. A Guard hook can enforce that templates do not create IAM resources without explicit approval:

# Register a CloudFormation hook that blocks IAM admin role creation
aws cloudformation register-type \
  --type HOOK \
  --type-name MyOrg::Security::BlockAdminIAM \
  --schema-handler-package s3://your-hook-bucket/block-admin-iam.zip

Apply the hook to the stack sets administrator account to catch malicious template modifications before they deploy to target accounts.

4. Enable CloudTrail for Cross-Account Visibility

Service-managed StackSets deployments appear in CloudTrail as events in the management account (CreateStackInstances, UpdateStackSet) and as resource creation events in target accounts. Ensure CloudTrail is enabled across all Organisation accounts and centralised to a log archive account.

# Verify CloudTrail is enabled across your organization
aws cloudtrail get-trail-status --name your-org-trail
aws cloudtrail describe-trails --include-shadow-trails

Alert on CreateStackInstances events originating from principals outside your approved CI/CD pipeline roles.

5. Apply SCPs to Limit StackSets Execution

Service Control Policies in AWS Organizations can restrict which accounts are allowed to create StackSets resources, and from which management accounts:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyUnauthorizedStackSetAdministration",
      "Effect": "Deny",
      "Action": [
        "cloudformation:CreateStackSet",
        "cloudformation:CreateStackInstances"
      ],
      "Resource": "*",
      "Condition": {
        "StringNotEquals": {
          "aws:PrincipalArn": "arn:aws:iam::ADMIN_ACCOUNT_ID:role/ApprovedDeploymentRole"
        }
      }
    }
  ]
}

Apply this SCP to the root OU so it covers all member accounts, preventing member accounts from creating stack sets that deploy back to the management account.

Detection

Monitor for the following CloudTrail events in the administrator account:

  • cloudformation:UpdateStackSet — especially changes to the template URL or execution role ARN
  • cloudformation:CreateStackInstances — from principals outside your expected CI/CD pipeline roles
  • iam:CreateRole or iam:AttachRolePolicy in target accounts originating from the CloudFormation execution role context, where the new role has broad permissions
  • sts:AssumeRole calls on the administration role from principals that are not cloudformation.amazonaws.com
# Pull recent StackSets administration role assume-role events from CloudTrail
aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=EventName,AttributeValue=AssumeRole \
  --start-time 2026-08-01 \
  | jq '.Events[] | select(.CloudTrailEvent | fromjson | .requestParameters.roleArn | contains("StackSetAdministrationRole"))'

References

← All Analysis Subscribe via RSS