The Infrastructure from Code Execution Model
When you run pulumi up or cdk deploy, the framework executes your infrastructure program β a TypeScript, Python, or Go application β in a local or CI process that has cloud provider credentials. During execution, your program calls framework APIs that construct a resource graph, which the framework then reconciles against the cloud provider's actual state using those credentials.
The critical difference from YAML-based IaC (Terraform, CloudFormation) is that your program can import arbitrary third-party libraries that execute alongside the framework code. In Terraform, the execution surface is limited to provider plugins with well-defined interfaces. In Pulumi, any npm or PyPI package you import runs arbitrary code in a process that holds your AWS or GCP provisioning credentials.
The package execution problem: A malicious or compromised npm package with a postinstall script β or one that simply executes code at import time β can read environment variables containing cloud credentials, query the cloud metadata endpoint, or make outbound HTTPS calls during a pulumi up run. The infrastructure deployment process itself becomes a supply chain attack surface.
State File Secrets Exposure
Pulumi stores infrastructure state in a state file (local backend) or in Pulumi Cloud. This state file contains the full configuration of every managed resource β including resource properties that happen to contain sensitive values. A database resource's connection string, a secret manager ARN with its current value, a generated password stored in a resource output β all of these can end up in the Pulumi state file as plain text unless explicitly marked as secrets.
Developers who do not use pulumi.secret() wrappers for sensitive resource outputs will find those values stored in plaintext in their state file. If the state backend is Pulumi Cloud, those values are visible to anyone with stack read access. If the state backend is an S3 bucket without encryption or fine-grained access controls, the state file becomes a credential store accessible to anyone with bucket read access.
AWS CDK outputs in CloudFormation: CDK synthesises to CloudFormation, and CloudFormation stack outputs are accessible to anyone with cloudformation:DescribeStacks permissions. Sensitive values exported as stack outputs β database endpoints, generated credentials β are readable by any IAM principal with that permission across the account.
Supply Chain Attack Surface
IfC introduces a supply chain risk that traditional IaC tools avoid. The Pulumi SDK itself is an npm package, and infrastructure programs typically import dozens of provider packages and utility libraries. Any of these packages executing during pulumi up has access to the cloud provider environment β AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, the EC2 metadata endpoint β depending on how credentials are configured for the run.
The attack pattern is identical to other npm supply chain attacks: typosquatting a popular Pulumi provider package, compromising a widely-used utility library with a malicious update, or injecting code into a transitive dependency. The difference is the target environment: instead of developer tooling, the attack runs in the cloud provisioning pipeline with account-level cloud credentials.
Dynamic Policy Bypass
A core security benefit claimed for IaC is that infrastructure must conform to codified policies. Pulumi CrossGuard and CDK Aspects provide policy-as-code frameworks that check resource configurations against security rules. However, both frameworks run their policies as code β in the same general-purpose language as the infrastructure program. A sufficiently sophisticated attack that compromises the infrastructure program itself (not just its dependencies) can potentially manipulate the policy evaluation to produce compliant-looking results while deploying non-compliant resources.
More practically, policies that check resource properties may be bypassed through dynamic generation of resource names or configurations that the static policy checks do not anticipate. YAML-based IaC tools' limited expressiveness is also their security advantage: the policy checks can be more exhaustive because the configuration space is bounded.
CDK Bootstrap Account Permissions
AWS CDK requires bootstrapping an account/region pair before deploying CDK apps β this creates a CloudFormation stack that provisions the CDK Toolkit including an S3 bucket for assets, ECR repositories for container assets, and IAM roles for deployment. The bootstrapped IAM roles are broad by default: the deployment role has AdministratorAccess in the bootstrapped account. Any CI system that can assume this role can deploy arbitrary CloudFormation stacks with full account permissions.
Narrow the CDK bootstrap role: Use custom bootstrap templates that restrict the deployment role to only the services and regions your CDK apps actually use. The default AdministratorAccess bootstrap is appropriate for development environments but should never be used in production accounts where the deployment role can be assumed by CI systems.
Hardening IfC Pipelines
- Run SCA scanning on infrastructure program dependencies: Apply the same dependency vulnerability scanning to Pulumi and CDK programs that you apply to application code. Infrastructure programs import many packages; treat each as a potential attack vector.
- Use OIDC-based short-lived credentials for cloud authentication: Never store long-lived cloud credentials in CI secrets for IfC pipelines. Use OIDC federation (GitHub Actions OIDC to AWS IAM role) to obtain short-lived credentials that expire after the deployment run.
- Always wrap sensitive outputs with
pulumi.secret(): Audit all Pulumi stack outputs and resource property assignments for sensitive values. Use SAST rules to detect unprotected sensitive assignments in Pulumi programs. - Protect CDK bootstrap roles with condition policies: Add IAM condition keys to the CDK deployment role trust policy to restrict assumption to specific CI systems, IP ranges, or OIDC claim values. Log all role assumptions via CloudTrail.
- Pin Pulumi provider package versions to digests: Do not use floating version ranges for Pulumi provider packages. Pin to exact versions in
package.jsonand verify package integrity against known-good checksums. - Review IfC diffs as carefully as application code diffs: A Pulumi or CDK diff that shows IAM policy changes, security group modifications, or new resource additions in production accounts requires security review β not just platform team review.