Master IaC security with this 2026 cheat sheet for Terraform and Pulumi. Compare Checkov, tfsec, and CrossGuard with essential CLI commands. Full breakdown.

What static analysis catches in IaC

Infrastructure as Code defines networks, identities, storage, and runtime config before anything is applied. Static analysis reads those definitions and flags insecure defaults, over-broad permissions, public exposure, missing encryption, and weak logging without spinning up cloud resources. For Terraform and Pulumi, the goal is the same: fail fast on policy violations in pull requests, not after a plan is applied.

Treat scanners as policy compilers. They map resource attributes to rules (public S3-equivalent buckets, open security groups, root-equivalent roles, unencrypted disks) and report severity plus a fix hint. They do not replace design review, cost checks, or runtime monitoring—but they do make least-privilege and baseline hardening enforceable in CI.

Checkov, tfsec, and CrossGuard at a glance

Checkov is multi-IaC: Terraform, CloudFormation, Kubernetes manifests, and related formats under one CLI. It ships a large built-in rule set and supports custom policies when you need org-specific constraints. Reach for it when you want one scanner across mixed stacks and consistent report formats for CI gates.

tfsec is Terraform-focused and fast to wire into existing terraform workflows. It maps cleanly onto module layouts and is useful when the repo is pure HCL and you want low-noise, Terraform-native findings. CrossGuard is Pulumi’s policy engine: policies are code (same language model as your stacks), evaluated against resource graphs before or during preview. Prefer CrossGuard when Pulumi is the system of record and you want policies versioned next to the infrastructure code rather than as external YAML-only packs.

  • Checkov — broad multi-format coverage; good default for polyglot IaC monorepos.
  • tfsec — Terraform-first, lightweight CI step on HCL trees.
  • CrossGuard — Pulumi-native policies as code; tight preview/apply integration.

Essential CLI patterns

Run scanners where engineers already work: local pre-commit and the same command in CI. For Terraform, target the directory that contains root modules (or a monorepo path list). Typical flows: install the tool, point it at . or a module path, exit non-zero on high/critical findings, and publish SARIF or JSON for PR annotations. Example shapes (adjust paths and severity flags to your pipeline): checkov -d ., tfsec ., and for Pulumi policy packs, register and run the pack against a stack preview so violations block merge the same way unit tests do.

Keep configuration in-repo: skip lists only for justified exceptions with owners; pin policy pack versions; and fail the job on severity thresholds you actually enforce. Re-scan after terraform plan / Pulumi preview only if you need graph-aware rules—most misconfigs are visible from source alone.

Practical workflow for Terraform and Pulumi teams

Start with defaults, then tune. Week one: scan every change, triage false positives, and codify exceptions. Week two: encode hard rules (no public data stores, no wildcard principals, encryption required) as custom Checkov policies or CrossGuard policies so they cannot drift. For mixed shops, run Checkov on shared modules and CrossGuard on Pulumi apps—or standardize on one tool per language boundary to avoid duplicate noise.

Pair static analysis with plan review: scanners miss intent (why a port is open) and multi-account blast radius. Document remediation next to the finding (least-privilege IAM snippet, private networking pattern). The cheat sheet outcome is simple: every PR that changes IaC must pass the same CLI gates you run locally, with Checkov, tfsec, or CrossGuard chosen for format fit—not fashion—and with policies treated as product code that ships with the stack.

Automate Your Content with AI Video Generator

Try it Free →