Safeguard
Application Security•

IaC scanning in CI/CD: the order to set it up

Set up IaC scanning in order: report only on pull requests, tune noise, scan the plan, then gate a short rule list. Plan file pitfalls included.

Safeguard Security Team
4 min read

Set up IaC scanning in four steps: scan the code on every pull request in report only mode, tune the noise, scan the rendered plan, then turn on blocking for a short list of rules. Adding a gate on day one is the usual way these rollouts get switched off.

The examples use Terraform because its docs are public and precise, but the order applies to any infrastructure as code tool.

Why does the order matter?

Static scanning of config files and scanning a plan answer different questions. The first reads what you wrote. The second reads what the tool will actually do after variables, modules and existing state are resolved. Starting with the first is cheap and safe. Starting with the second needs credentials and state access, which is a bigger decision.

Step 1: scan the files, report only

Run the scanner on pull requests against the directory with your infrastructure code. Do not fail the build yet. Output the results in a standard format such as SARIF so they appear next to the diff. Your goal this week is a baseline: how many findings, which rules fire most, which repositories are worst.

Also run the basic checks your tool provides. Terraform's validate command checks the syntax of the configuration files in a directory, which catches broken code before a scanner spends time on it.

Step 2: tune before you enforce

Look at the top five rules by count. For each, choose one of three outcomes: fix the code, change a shared module so every user benefits, or suppress with a written reason in a reviewed file. Suppressions that live in a reviewed file survive staff changes. Suppressions in a dashboard do not.

Wait until a typical pull request produces no findings the author calls wrong. That is your readiness test for blocking.

Step 3: scan the plan

terraform plan previews the changes without applying them. With -out it writes the plan to a file, which the docs describe as intended mainly for automation, so a later apply step executes exactly what was reviewed.

Two details from the documentation matter for CI.

  • A saved plan file holds your full configuration and variable values, and sensitive data is stored in cleartext even though terminal output hides it. The docs say to treat saved plans as potentially sensitive artifacts. So do not upload them as ordinary build artifacts with wide read access.
  • With -detailed-exitcode, exit code 0 means success with no changes, 1 means error, and 2 means success with changes present. A pipeline that treats any non-zero code as failure will break on every real change. Handle 2 explicitly.

Plan scanning finds things files cannot, such as a public setting that comes from a variable default in a module. Run it where credentials already exist, usually the deploy pipeline and not the pull request job from forks.

Step 4: gate on a short list

Pick rules where a hit is almost always real and expensive: storage open to the public, rules that allow all traffic from anywhere, unencrypted databases, hard coded secrets. Block merges on those only. Leave the rest as warnings with an owner and a date.

Where policy gates live depends on your tool. With Safeguard's CLI, for example, the docs state safeguard scan exits 0 whenever the scan ran and gating is a platform policy, not a CLI threshold flag. Check how your own scanner behaves before you wire a pipeline to its exit code.

What to do

  1. Add a report only IaC scan to pull requests, output as SARIF.
  2. Record the baseline and the five noisiest rules.
  3. Fix, fix in a shared module, or suppress with a reason in a reviewed file.
  4. Add plan scanning in the deploy pipeline, and protect saved plan files.
  5. Handle exit code 2 from the plan step explicitly.
  6. Block merges on three to five high confidence rules.
  7. Review the list monthly and promote one rule at a time.

Quick check

Should the first IaC scan block pull requests?

No. Run report only first, build a baseline, tune noise, then block a short list of high confidence rules.

Is a saved Terraform plan safe to store as a build artifact?

Treat it as sensitive. Per the Terraform docs it can contain sensitive values in cleartext, so restrict access and retention.

What does exit code 2 mean from terraform plan?

With the detailed exit code option, 2 means the plan succeeded and changes are present. It is not a failure.

Sources

Last reviewed: 18 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.