Skip to main content
emnode
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. Get this right up front: a service role can't be removed once the stack is created (only swapped on update or delete), and AWS lets any user with stack-operation permissions wield the role regardless of whether they hold iam:PassRole, so an over-broad role silently becomes an escalation path.
  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.

Is CloudFormation.4 a false positive?

Stacks created by service-managed StackSets always report FAILED here, and that's a documented quirk rather than a real gap. Service-managed StackSets authenticate through AWS Organizations trusted access using per-account execution roles, so the stack's own `roleARN` field is left empty: the control reads that empty field and fails the stack even though deployments are running under a scoped, least-privilege execution role the whole time. AWS calls this out explicitly in the control reference. For these stacks, confirm the StackSet is genuinely service-managed (not self-managed, where you really should attach a service role), then suppress the finding with a note pointing at the Organizations execution-role model so the exception is traceable.

Part of the learning path Lock down access