CDK bootstrap resources, roles and trust

What cdk bootstrap creates (CDKToolkit stack, staging bucket, ECR repository, version parameter) and the five roles — deploy, CloudFormation execution, lookup, file publishing, image publishing — with their exact names, whom each trusts (the account itself plus --trust accounts, ExternalId denied), what each may do, how the CLI uses them, when it falls back to your own credentials, and how --trust, execution policies, qualifiers and permissions boundaries change them.

markdownreferencev4RK6C-5S9Qstage: referencetrust: officialservice: cdkservice: cloudformationservice: iaminterface: iaccdk bootstrapCDKToolkitcdk-hnb659fds-deploy-rolecfn-exec-rolelookup-rolefile-publishing-roleimage-publishing-rolehnb659fds qualifier/cdk-bootstrap/hnb659fds/versionBootstrapVersion--trust--trust-for-lookup--cloudformation-execution-policiesAdministratorAccess CDKDenyExternalIdpermissions boundary CDKDefaultStackSynthesizerProceeding anyway current credentialshotswap credentialscross-account CDK deploy

Created 18 Oct 2026 · Modified 23 Oct 2026 · 4 versions

The CLI doesn't deploy with your credentials. It uses them to assume the bootstrap roles in the target environment, and CloudFormation then acts as the execution role. So "can I deploy?" really asks two things: can my identity assume cdk-<qualifier>-deploy-role-… (and the publishing roles), and does the execution role allow what the template creates?

What cdk bootstrap aws://<account>/<region> creates

One CloudFormation stack, CDKToolkit, per environment (account + Region), containing:

ResourceName (default qualifier hnb659fds)Purpose
S3 staging bucketcdk-hnb659fds-assets-<account>-<region>File assets, and templates too large to pass inline. Public access blocked by default; non-TLS requests denied
ECR repositorycdk-hnb659fds-container-assets-<account>-<region>Docker image assets; tags immutable
SSM parameter/cdk-bootstrap/hnb659fds/versionTemplate version. The CLI checks it, and CloudFormation reads it again during the deploy
Five IAM rolesbelow

The bootstrapping identity needs broad rights: cloudformation:*, ecr:*, ssm:*, s3:* and iam:*. The template bundled with CDK CLI 2.1145.0 is version 32, but the number moves; re-running cdk bootstrap is safe and upgrades only when needed.

The five roles

Role (cdk-<q>-…-<account>-<region>)Trusted byAllowsUsed for
deploy-roleThe account itself and every --trust accountCreate, update, execute and delete change sets and stacks; RollbackStack, ContinueUpdateRollback; iam:PassRole on the execution role; reading the version parameter; AWSCloudFormationReadOnlyAccesscdk deploy and cdk destroy
cfn-exec-rolecloudformation.amazonaws.com only--cloudformation-execution-policies, or AdministratorAccess if none were givenThe stack's service role: everything in your template happens with these rights
lookup-roleThe account, --trust-for-lookup accounts and --trust accountsReadOnlyAccessContext lookups during synth (Vpc.fromLookup and similar)
file-publishing-roleThe account and --trust accountsThe staging bucketUploading file assets
image-publishing-roleThe account and --trust accountsThe ECR repositoryPushing image assets

Trust details from the template:

  • The trusted principal is the account ("AWS": "<account-id>"), not a specific role. So any identity in that account whose own IAM policy allows sts:AssumeRole on the role can use it, and identities without that Allow can't (patterns/iam/trust-policies.md). sts:TagSession is allowed too.
  • DenyExternalId defaults to true. AssumeRole calls that carry an ExternalId are denied, so the roles can't be accidentally "deputized" to a third party.
  • The execution role can carry a permissions boundary: --custom-permissions-boundary <policy-name>, or --example-permissions-boundary (a starting point, not for production as-is).

How the CLI picks credentials

  1. It needs credentials for the target account. Otherwise you get Need to perform AWS calls for account <n>, but the current credentials are for <n> (or … but no credentials have been configured).
  2. It assumes the roles the synthesizer names. If that fails:
  • Same account: it warns <credentials> could not be used to assume '<role-arn>', but are for the right account. Proceeding anyway. and carries on with your own credentials. Deploys may still work, but they bypass the bootstrap roles and need you to hold the CloudFormation, S3 and service permissions directly.
  • Cross-account: it stops with Could not assume role in target account …. See reference/cdk/errors.md.
  1. --hotswap (and --watch, which implies it) calls Lambda, Step Functions and other APIs with your current credentials, not the bootstrap roles, and leaves CloudFormation drift. Follow up with cdk deploy --revert-drift.

Options that change trust and permissions

OptionEffectWatch out
--trust <account> (repeatable)Adds accounts to the deploy, lookup and publishing roles' trustRequires --cloudformation-execution-policies. The list replaces the old one, so name every account each time
--trust-for-lookup <account>Lookup role only: those accounts can synth, not deploy
--cloudformation-execution-policies <arn,arn>Managed policies on the execution role (one comma-separated string)Must cover everything every stack in the environment creates, or deployments fail on resource permissions
--qualifier <9 chars>Renames every bootstrap resourceThe app must use the same qualifier (new DefaultStackSynthesizer({ qualifier }) or context @aws-cdk/core:bootstrapQualifier). Two qualifiers in one account give no permission isolation unless their execution roles are scoped
--bootstrap-bucket-name <name>Custom bucket name (it must not exist yet)Match it in the synthesizer
--bootstrap-kms-key-id <id> / --bootstrap-customer-keySSE-KMS on the bucket (the two can't be combined)Older templates created a key by default; --no-bootstrap-customer-key removes its cost
--no-previous-parametersRe-supply every parameter; omitted ones reset (removes a boundary, for example)Without it, earlier values are kept
--termination-protectionProtects CDKToolkitRecommended. Never delete and recreate the toolkit stack: re-run bootstrap instead
--template <file>Custom template (start from cdk bootstrap --show-template)Change BootstrapVariant. Keep the contract: the version parameter, outputs BucketName, BucketDomainName and BootstrapVersion, and the five roles

Environments bootstrapped with the legacy (v1) template must be re-bootstrapped for CDK v2.

Read this document as markdown — the same bytes an agent receives.