IaC scanning before apply: catch misconfigurations in the PR

IaC scanning catches Terraform, Kubernetes and CloudFormation misconfigurations at pull-request time, while the fix is still a one-line change.

Examples in this article are illustrative, not customer case studies. Product availability and coverage are described on the linked capability pages.

A security group opened to the internet so a health check would pass, a wildcard IAM policy added so a deploy script would stop failing: most cloud misconfigurations begin as a quick fix in a Terraform diff. This post shows how infrastructure-as-code scanning catches them at pull-request time, where the fix is one line, and where the approach reaches its limits.

Infrastructure-as-code (IaC) scanning evaluates Terraform, CloudFormation, Kubernetes manifests and rendered Helm charts against security rules before anything is provisioned. Run on the pull request, it catches network exposure, over-broad IAM, unprotected storage and missing workload hardening while the change is still in review and its author still remembers why each line exists.

We will follow one change throughout: a pull request for a payments API that adds a Terraform module for its load balancer and database, plus a Helm chart for its settlement worker. Nothing in it is malicious; it was written by people who needed the service running before a release.

IaC scanning evaluates the resource as declared, not as deployed

An IaC scanner parses the files that describe your infrastructure before anything is provisioned: Terraform HCL and plan output, Kubernetes manifests, Helm charts and CloudFormation templates. It builds a model of each resource as it would exist once created, then checks that model against rules. For the payments API, the scanner sees the security group, the database encryption flag and the worker’s IAM role before terraform apply has created any of them. That early view is both the strength and the limit of the approach: it can stop a mistake being created, but it cannot see what happens to the resource afterwards.

Helm deserves particular care because it adds a templating layer. The payments team’s values.yaml looks harmless, yet one template sets hostNetwork: true whenever a debugging flag is enabled in the staging values. A scanner that reads chart source without rendering it misses exactly this, so render each chart with each environment’s values and evaluate what will actually reach the cluster.

The same misconfiguration classes recur in almost every IaC change

Across Terraform, Kubernetes and CloudFormation, the same classes of misconfiguration keep appearing, driven by pressure to ship and by templates copied from examples never meant for production. The payments pull request contains one of each.

Network exposure. The security group allows SSH from 0.0.0.0/0 because someone needed to debug a database migration. Unrestricted load balancers and ingress objects that expose admin routes belong to the same class.

Excessive IAM scope. The worker’s role grants every storage action on every resource, because the settlement bucket name was unknown when the policy was drafted. Service accounts bound to cluster-admin follow the same pattern.

Unprotected storage. The database is declared with encryption at rest disabled, copied from a local development example. Buckets without public-access blocks and secrets in plain environment variables are close relatives.

Missing workload hardening. The Helm chart runs the worker as root with no runAsNonRoot constraint. Privileged containers and host path mounts left over from debugging complete the set.

None of these is exotic. Each maps to a specific, checkable property of a declared resource, which is why rules catch them reliably.

Pull-request time is the cheapest point to fix a misconfiguration

The cost of a misconfiguration rises with every step it travels from the diff that introduced it. In the pull request, the open SSH rule is a one-line change and a re-review. After apply, it is a live resource that may already carry traffic, and removing it needs a change window and confidence that nothing now depends on it. Found by someone outside the organisation, it is an incident.

The pull request is also where context is richest. The engineer who added the rule can explain it in a sentence today, whereas long after the merge nobody will remember whether it was deliberate. A periodic sweep of the repository finds the same problem later, when it costs more and the reasoning behind it has gone.

IaC scanning needs both lint rules and organisation policy

Two different things are often bundled under “IaC scanning”. Lint rules check a property of the code in isolation: a bucket lacks encryption, a port is open to the world, a resource has no owner tag. They need no knowledge of your organisation, and a sensible default set applies almost everywhere.

Policy encodes decisions that belong to you. The payments team might rule that production accounts never expose a database publicly, that a sandbox may skip encryption during a prototype, and that one load balancer is exempt because a web application firewall sits in front of it. Policy needs an owner, a change process and a deliberate way to record exceptions, rather than a check that gets disabled when it becomes inconvenient.

Treat everything as lint and the scanner either blocks legitimate exceptions or gets switched off. Treat everything as policy and you rebuild well-understood checks from scratch. The policy layer is best enforced as code in the pipeline, as described in policy-as-code deployment gates with OPA, and it should fail closed when a required check has not run.

Drift and out-of-band change sit outside the repository

IaC scanning only knows the world as described in code. Suppose the payments database is provisioned correctly, then an engineer loosens a firewall rule in the console during an incident. The code still says the resource is safe, and re-scanning the repository will never say otherwise, because the repository never changed.

Resources that bypass the pipeline entirely are equally invisible. Hand-built resources, third-party integrations that provision on your behalf and emergency fixes never backported into a template have no code to scan.

Closing that gap means comparing what the code declares with what the account contains. IaC scanning tells you what should exist, and reconciliation confirms what does. The follow-on post, IaC drift and live resources, covers how to link the two and close findings on evidence.

Key takeaways

  • Render Helm charts with each environment’s values before scanning, because the rendered manifest is what reaches the cluster.
  • Gate IaC findings on the pull request, where the author can still explain every line.
  • Keep baseline lint rules separate from organisation policy, and record exceptions with an owner and a reason instead of disabling checks.
  • Reconcile declared configuration against live accounts continuously, because a clean repository says nothing about console changes.

How SecurityVault approaches this

SecurityVault runs supported IaC checks alongside application scanning and places the results in a shared review workflow. Rendering and static evaluation have limits: unresolved values and unsupported template constructs need plan or deployment validation. OPA gates can enforce the requirements your team defines, and cloud posture can help re-check the resulting live resources.

Evaluate a small template with a known issue and an environment-dependent setting. Inspect which values the scanner resolved, which remained unknown and whether the reported location gives the author enough context to make a change. Then compare the rendered or planned configuration with the actual deployment. Teams should leave the exercise knowing where automated checks are useful, where manual review is still needed and who maintains exceptions. A clear coverage boundary is more useful than a clean report whose inputs nobody can explain.

Explore IaC security or talk to our team about an evaluation with your engineering, security and compliance stakeholders.

Further reading

See it on your stack

Bring IaC scanning into one finding graph.

SecurityVault is the enterprise security operating system: one graph of findings, policy and evidence from code to cloud. Explore the IaC scanning workflow with your engineering, security and compliance teams. No repository access is needed for the initial demonstration.