Skip to main content
emnode / learn
Compliance Medium severity

AWS Security Hub · CloudFormation

CloudFormation.4: Stacks deploy with user creds instead of a scoped role

Written and reviewed by Emnode · Last reviewed

What does AWS Security Hub CloudFormation.4 check?

CloudFormation.4 fails when a stack has no service role attached — it deploys with the calling user's or pipeline's credentials instead of a scoped IAM role. The control reads the stack's RoleARN.

Why does CloudFormation.4 matter?

Without a service role, the stack's effective permissions become whatever the deployer holds, which is usually far broader than the stack needs. Any path that compromises those credentials — an SSRF chained into a CI role, as in the Capital One breach — inherits the full power CloudFormation was wielding. A scoped service role caps the blast radius to exactly what the stack is allowed to create.

How do I fix CloudFormation.4?

  1. Inventory stacks deployed without a RoleARN.
  2. Design a least-privilege IAM role granting only the resource permissions the stack needs, with a trust policy for cloudformation.amazonaws.com.
  3. Switch a running stack to it with update-stack passing --role-arn, no template change required.
  4. Make the service role a required parameter in your deployment pipeline.

Remediation script · bash

# Replace a full-admin policy with a scoped version (keep the old one as rollback, then delete).
aws iam create-policy-version \
  --policy-arn arn:aws:iam::111122223333:policy/ci-deploy-policy \
  --policy-document file://ci-deploy-scoped.json --set-as-default
# ... verify a staging and a prod run, then ...
aws iam delete-policy-version \
  --policy-arn arn:aws:iam::111122223333:policy/ci-deploy-policy --version-id v3

# Attach a scoped service role to a CloudFormation stack with no resource churn.
aws cloudformation update-stack --stack-name payments-iam-prod \
  --use-previous-template \
  --role-arn arn:aws:iam::111122223333:role/cfn-payments-iam-deployer \
  --capabilities CAPABILITY_NAMED_IAM

# Attach a least-privilege resource policy to a custom event bus (one named account).
aws events put-permission --event-bus-name orders-bus \
  --statement-id AllowPartner444455556666 --action events:PutEvents --principal 444455556666

Full walkthrough (console steps, edge cases and verification) in the lesson Harden resource and service-role policies.

Part of the learning path Lock down access