Blog

Securing infrastructure-as-code: Terraform, Pulumi, and beyond

At a glance
  • Securing infrastructure-as-code means treating Terraform, Pulumi, and similar tools as production code: scan, sign, gate, and remediate every dependency.
  • Most IaC risk lives in transitive providers, modules, and base images — the layers SCA scanners flag but cannot fix.
  • Back-porting security patches to the exact provider or library version you already run avoids breaking working Terraform state.
  • Seal Security commonly handles critical and high-rated open-source vulnerabilities within 72 hours of public disclosure, per seal.security.
  • Pair policy-as-code (OPA, Sentinel) with remediation-as-code so fixes ship at the same speed as the misconfigurations they address.

Securing Infrastructure-as-Code: Terraform, Pulumi, and Beyond

Securing infrastructure-as-code (IaC) — the practice of defining cloud infrastructure in declarative files using tools like HashiCorp Terraform, Pulumi, AWS CloudFormation, and Crossplane — requires treating those files and their dependency graphs with the same rigor you apply to production application code. That means static analysis of the configuration, policy-as-code gates in CI, signed modules and providers, and a concrete plan to remediate the open-source vulnerabilities that live inside the providers, modules, and container base images your stacks pull in. The hardest part is rarely the misconfiguration scan; it is fixing the vulnerable transitive dependency buried three layers down in a provider plugin you cannot easily upgrade without breaking working Terraform state or a Pulumi program in production. In 2026, with AI-assisted exploit generation compressing the window between disclosure and weaponization, application security and DevSecOps teams need a remediation path for IaC dependencies that does not depend on a risky version bump — and that is where back-porting (applying the security patch to the version you already run) becomes the pragmatic alternative to forced upgrades.

What does securing infrastructure-as-code actually mean?

Securing infrastructure-as-code (IaC) actually spans three distinct problem domains that teams routinely conflate, and untangling them is the first practical step. When practitioners say they want to harden Terraform, Pulumi, AWS CDK, or Crossplane definitions, they may mean any of the following — and the right tools, owners, and remediation paths differ for each.

Which interpretation of IaC security do you mean?

  • Misconfiguration scanning of the IaC code itself. Catching insecure defaults — public S3 buckets, permissive security groups, unencrypted RDS instances — before terraform apply. This is policy-as-code territory: Checkov, tfsec, Open Policy Agent, HashiCorp Sentinel, Pulumi CrossGuard.
  • Supply-chain security of the IaC toolchain and its dependencies. The Terraform providers, Pulumi SDKs, custom modules, and the Go, Python, JavaScript, or C# libraries they pull in all carry their own CVEs. A vulnerable provider or transitive dependency is an open-source vulnerability problem, not a misconfiguration problem — and Software Composition Analysis (SCA) scanners like Snyk, Checkmarx, or Black Duck typically surface these findings.
  • Runtime security of what the IaC provisions. Hardening the resulting Kubernetes clusters, VMs, container base images, and EOL (End-of-Life — software no longer patched by its vendor, such as CentOS 7) operating systems that the templates stand up.

Which interpretation should this article focus on?

Most teams have misconfiguration scanning reasonably well covered. The painful, under-served interpretations are the second and third: vulnerable dependencies inside providers and modules, and un-upgradeable packages on the legacy hosts your IaC keeps re-provisioning. Those are remediation problems, not detection problems — and they are where back-porting (applying a security fix to the version you already run, rather than forcing an upgrade) becomes the practical alternative. The rest of this 2026 guide concentrates there.

Which threats and misconfigurations target IaC pipelines today?

The threats and misconfigurations that target infrastructure-as-code (IaC) pipelines have shifted well beyond hardcoded credentials in a Terraform file. Today's attackers go after the pipeline itself, the modules it pulls, and the open-source libraries embedded inside provider plugins and custom providers — places where scanner findings often read "no fix available."

What are the dominant attack vectors?

  • Malicious or typo-squatted modules pulled from public Terraform Registry, Pulumi Registry, or Git sources, often with transitive dependencies on vulnerable Go, Python, or JavaScript libraries.
  • Compromised CI runners (GitHub Actions, GitLab CI, Jenkins) where stolen cloud credentials let attackers apply unreviewed plans.
  • State file exposure — Terraform state in misconfigured S3 buckets or unencrypted backends, leaking secrets and resource topology.
  • Vulnerable provider binaries and SDKs — CVE-laden dependencies inside the providers themselves, frequently flagged by SCA (software composition analysis) tools yet marked unfixable because no upstream upgrade exists.
  • Drift between code and runtime, which lets manually-introduced misconfigurations persist after the pipeline declares success.

Which misconfigurations recur most often?

Overly permissive IAM policies, public storage buckets, unencrypted volumes, open security groups, missing logging, and default service accounts dominate the recurring list. These show up commonly across regulated environments scanned with Checkov, tfsec, or Snyk IaC.

How should teams pair each action with its risk?

Recommended action Risk or tradeoff to watch Mitigation
Pin module versions and verify checksums Pinning freezes you on a vulnerable version when no upgrade exists Back-port the security fix to the pinned version instead of forcing a major upgrade
Scan IaC with SCA + policy-as-code (OPA, Sentinel) Generates alert volume your team cannot remediate Route findings to a remediation workflow, not just a ticket queue
Isolate CI runners and short-lived credentials Adds operational complexity, can break legacy jobs Stage rollout per pipeline; keep audit trails
Encrypt and lock remote state Key mismanagement can lock teams out Use managed KMS with documented break-glass procedures

The underappreciated angle: most IaC "fix" advice assumes you can upgrade. In regulated stacks running EOL providers or pinned modules, back-porting the patch is often the only path that closes the CVE without breaking the plan.

How do you secure Terraform code, state, and modules?

To secure Terraform code, state files, and reusable modules, treat each as a distinct attack surface with its own controls — the HCL source, the state backend, and the provider supply chain all need hardening before a single terraform apply runs in production.

What attributes should you harden in Terraform?

Think of Terraform security as a set of named attributes, each with allowed values and a clear reason to care:

  • Source control hygiene — Allowed: signed commits, branch protection, mandatory review on *.tf changes. Why: infrastructure-as-code (IaC) drift and rogue resources usually enter through unreviewed pull requests.
  • Static analysis of HCL — Allowed: Checkov, tfsec, Terrascan, or Snyk IaC wired into CI. Why: catches misconfigured S3 buckets, open security groups, and missing encryption before plan.
  • State backend — Allowed: remote backends such as Terraform Cloud, S3 with KMS + DynamoDB locking, or Azure Blob with customer-managed keys. Why: state files contain plaintext secrets and resource identifiers; a leaked terraform.tfstate is a credential dump.
  • State encryption + access — Allowed: encryption at rest, IAM least-privilege, MFA-delete on the bucket, audit logging. Why: read access to state equals read access to your cloud.
  • Provider pinning — Allowed: exact versions in required_providers, checksums in .terraform.lock.hcl. Why: an unpinned provider is a silent supply-chain risk.
  • Module provenance — Allowed: private registry, Git tags, signed releases. Why: public registry modules are transitive dependencies that can change underneath you.
  • Secrets handling — Allowed: Vault, AWS Secrets Manager, or SOPS — never plaintext variables.tf. Why: secrets in code outlive the commit that introduced them.
  • Plan/apply separation — Allowed: ephemeral CI runners with scoped, short-lived cloud credentials (OIDC). Why: long-lived admin keys on a laptop are the most common Terraform blast radius.

How do you handle vulnerable provider and module dependencies?

A subtler problem: providers and modules pull in their own open-source libraries, and many of those flag CVEs that Software Composition Analysis (SCA) scanners — Snyk, Checkmarx, Black Duck — mark "no fix available" or "upgrade required." When the upgrade would break a pinned provider chain, back-porting the security fix to the version you already run is a credible alternative to a destabilizing version bump. That keeps your Terraform pipeline reproducible while closing the underlying CVE — the same principle that applies to any legacy or end-of-life dependency elsewhere in your stack.

How does securing Pulumi differ from securing Terraform?

Securing Pulumi differs from securing Terraform primarily in the threat surface introduced by general-purpose programming languages: Pulumi programs are real TypeScript, Python, Go, or C# code with full access to package registries, native modules, and arbitrary runtime behavior, while Terraform's HCL is a constrained declarative DSL. That distinction reshapes how you weigh secrets handling, supply-chain exposure, and policy enforcement.

Which criteria matter when comparing them?

Before any side-by-side, fix the evaluation lens. The criteria that typically drive AppSec decisions here are: (1) language-runtime risk — can the IaC program execute arbitrary code at plan time? (2) dependency surface — what third-party packages enter the blast radius? (3) secrets model — where are secrets resolved and encrypted? (4) policy enforcement — how is policy-as-code expressed and gated? (5) state security — where does state live and who can read it? Weight language-runtime and dependency surface highest for Pulumi shops, because those are the dimensions where the declarative model of Terraform offers a structurally smaller attack surface.

How do Terraform and Pulumi compare across those criteria?

Criterion Terraform (HCL) Pulumi (TS/Python/Go/.NET)
Language-runtime risk Declarative DSL; limited execution Full runtime; npm/PyPI code runs at pulumi up
Dependency surface Providers only Providers plus every transitive npm/PyPI/NuGet package
Secrets model Variables, Vault, backend encryption Native per-stack encrypted config; KMS/Vault providers
Policy-as-code Sentinel, OPA/Conftest CrossGuard (in-language) or OPA
State security Backend-managed (S3, TFC, etc.) Pulumi Service or self-managed backend

Verdict: Pulumi's expressiveness is its strength and its risk — you inherit your application language's entire software composition analysis (the discipline of scanning open-source dependencies for known CVEs) problem inside your IaC pipeline.

What does this mean for vulnerability remediation?

Because Pulumi programs pull in real npm or PyPI dependencies, a CVE in a transitive package — say, a logging library buried three levels deep — now lives in your control plane. Scanners flag it; upgrading often breaks the provider graph. Back-porting the fix to the exact version you already run, rather than chasing a major upgrade, keeps your stack deployable while closing the CVE.

What about CloudFormation, CDK, Crossplane, and other IaC tools?

Beyond Terraform and Pulumi, the same security principles apply to AWS CloudFormation, AWS CDK, Crossplane, Bicep, Ansible, and Helm — but the implementation details, blast radius, and supply-chain exposure differ meaningfully across each tool. Treating "infrastructure-as-code security" as a single discipline obscures these differences; a CloudFormation stack policy is not equivalent to a Crossplane RBAC rule.

Which IaC tools deserve attention beyond Terraform?

Tool Primary runtime Key security attributes to evaluate Notable supply-chain surface
AWS CloudFormation AWS-managed Stack policies, IAM service roles, drift detection, change sets AWS::Include transforms, public registry extensions
AWS CDK TypeScript/Python → CFN Construct library versions, synth-time code execution, aspects for policy npm/PyPI transitive dependencies in constructs
Pulumi General-purpose languages Stack references, secret providers, policy-as-code (CrossGuard) Language-ecosystem packages (npm, PyPI, NuGet)
Crossplane Kubernetes controllers Provider RBAC, Composition functions, package signatures xpkg images, upstream provider CRDs
Bicep Azure Resource Manager Module registries, deployment scopes, what-if analysis Public Bicep registry modules
Ansible SSH/WinRM agents Vault secrets, become privileges, collection signing Ansible Galaxy collections
Helm Kubernetes Chart provenance, values templating, RBAC manifests Public chart repositories, OCI artifacts

Securing these tools pulls in adjacent disciplines that share root causes with open-source vulnerability management:

  • Container base images — CDK and Crossplane often pull base layers from EOL distributions like CentOS, where upstream patches have stopped. Back-porting fixes to the existing image, rather than forcing a rebase, keeps deployments stable.
  • Policy-as-code — Open Policy Agent, Checkov, and Pulumi CrossGuard enforce guardrails at synth or plan time; they complement, rather than replace, dependency-level remediation.
  • SBOM generation — CycloneDX and SPDX outputs from IaC pipelines feed the same scanners (Snyk, Checkmarx, Black Duck) used for application code.
  • Transitive provider dependencies — Crossplane providers and CDK constructs commonly carry deep dependency trees where scanners flag CVEs with "no fix available" upstream. This is precisely where back-porting a vetted patch matters more than chasing an upgrade that may never ship.

Readers focused on a single ecosystem should still map these cross-cutting concerns; the attacker rarely respects tool boundaries.

Frequently Asked Questions

What is the difference between IaC scanning and runtime open-source remediation?

Infrastructure-as-code (IaC) scanning — using tools like Checkov, tfsec, or Snyk IaC — inspects Terraform, Pulumi, and CloudFormation files for misconfigurations such as open security groups or unencrypted buckets. Open-source remediation, by contrast, addresses vulnerable libraries baked into the container images, AMIs, and base operating systems that your IaC deploys. You need both: one secures the blueprint, the other secures the bricks.

Can I patch a vulnerable library without rebuilding my Terraform-managed image?

Yes. Back-porting — applying a security fix to the exact version you already run rather than upgrading — lets you remediate the vulnerable package inside an existing image without changing your Terraform module, version pins, or downstream dependencies. The Terraform plan stays identical; only the patched artifact changes. This is especially valuable for End-of-Life (EOL) base images such as CentOS 7 or older RHEL releases that no longer receive upstream patches.

How does Pulumi's policy-as-code compare to Terraform's Sentinel for security gating?

Both enforce guardrails at plan time, but they differ in language and ecosystem. Pulumi CrossGuard supports TypeScript, Python, and Go policies — useful for teams already writing Pulumi in those languages. HashiCorp Sentinel uses a purpose-built policy language tightly integrated with Terraform Cloud and Enterprise. Open Policy Agent (OPA) with Conftest is the language-neutral alternative that works across both, plus Kubernetes manifests and CI pipelines.

Do SBOMs generated from IaC pipelines cover open-source vulnerabilities in deployed workloads?

Partially. An SBOM in SPDX or CycloneDX format produced during build captures direct and transitive dependencies at that moment, which feeds Software Composition Analysis (SCA) — the scanning of open-source dependencies for known CVEs. However, SBOMs are snapshots; they do not remediate. Pairing SBOM generation with a remediation workflow ensures that newly disclosed CVEs against components already deployed get a patched version, not just a fresh alert.

How should regulated enterprises handle un-upgradeable legacy infrastructure under DORA or PCI DSS 4.0?

Frameworks like DORA and PCI DSS 4.0 expect timely remediation regardless of whether a vendor patch exists upstream. For legacy systems that cannot be upgraded — older Java runtimes, EOL Linux distributions, or proprietary forks — back-ported fixes provide a defensible path: the vulnerability is closed on the exact running version, evidence is auditable, and no rewrite is required. A dedicated remediation platform such as Seal Security provides human-vetted back-ported fixes for the exact library and OS versions already in production, so security teams can close CVEs without waiting on developers or risky upgrades.

Which IaC tools should AppSec teams integrate with their vulnerability management workflow in 2026?

A practical 2026 stack typically combines Terraform or Pulumi for provisioning, Checkov or tfsec for IaC misconfiguration scanning, an SCA tool such as Snyk, Checkmarx, or Black Duck for dependency scanning, an SBOM generator emitting CycloneDX or SPDX, and a dedicated remediation layer for back-ported fixes on libraries and OS packages. The integration point that matters most is the handoff from scanner finding to applied fix — that is where most backlogs stall.

Last updated: 2026-06-22

Ready to get started?

See how Seal Security can help.

Get in Touch