"The club membership sub has been the biggest ROI I've ever had. Like, this is absolutely insane, seeing everything that's happened since I got wind of the club last Fall." — Dex Copeland

GRC Automation

Infrastructure as Code Compliance Scanning

Infrastructure as code (IaC) compliance scanning checks your Terraform, CloudFormation, and Kubernetes files against security rules before anything deploys. When you scan Terraform at the pull request, an unencrypted bucket or an open security group fails the build instead of landing in production. This guide shows how the scanning works and how to map every finding back to a control.

Key Takeaways

  • Infrastructure as code (IaC) compliance scanning reads Terraform, CloudFormation, and Kubernetes files and flags misconfigurations before they ever reach production.
  • It catches the failures that show up most in audits: unencrypted storage, public security groups, and missing logging.
  • Scanning in CI blocks bad configuration at the pull request. Runtime scanning catches drift and resources created outside of code. You want both.
  • Findings are only useful when they map to controls, so a scanner that crosswalks to SOC 2, the CIS Benchmarks, and NIST 800-53 Rev 5 saves the manual translation step.
  • Checkov, tfsec/Trivy, KICS, and Open Policy Agent are the real tools practitioners reach for, and they are all open source.
  • The claude-grc-engineering toolkit wraps this in /grc-engineer:scan-iac so a scan returns control-mapped findings and, optionally, a drafted fix.

What is infrastructure as code compliance scanning?

Infrastructure as code (IaC) is the practice of declaring your cloud resources in files instead of clicking through a console. A Terraform file says "make an S3 bucket with these settings." A CloudFormation template says the same thing in a different syntax. A Kubernetes manifest declares a pod, a service, or a network policy.

IaC compliance scanning reads those files and checks them against a library of rules. Each rule is a small statement of intent: storage must be encrypted at rest, security groups must not allow ingress from 0.0.0.0/0, logging must be enabled. The scanner parses the resource, evaluates every rule that applies, and returns a pass or a fail with the exact file and line number.

The value is timing. You are checking the declared state of your infrastructure before it exists, not auditing it months later after an incident. That is the whole point of doing this work as code, and it is a core idea in compliance as code.

How scanning catches misconfigurations before deploy

The same handful of misconfigurations cause most cloud findings, and a scanner catches all of them by reading the file. Here are the ones you will see most:

  • Unencrypted storage: An S3 bucket, an EBS volume, or an RDS instance declared without encryption at rest. The scanner flags the missing or false encryption attribute.
  • Open security groups: An ingress rule that allows 0.0.0.0/0 on a sensitive port like 22 or 3389. The scanner reads the CIDR block and the port and fails the rule.
  • Missing logging: A bucket without access logging, an account without CloudTrail, or a load balancer without access logs. The scanner checks for the logging block and flags its absence.
  • Public exposure: A storage bucket with a public-read ACL or a database with a public IP. The scanner reads the access setting and flags anything reachable from the internet.
  • Weak Kubernetes defaults: A pod running as root, a container without resource limits, or a missing network policy. The scanner reads the manifest spec the same way it reads Terraform.

Here is what a scan looks like in practice. You point Checkov at a directory of Terraform and it returns a result per resource:

$ checkov -d ./terraform

Check: CKV_AWS_18: "Ensure the S3 bucket has access logging enabled"
  FAILED for resource: aws_s3_bucket.data
  File: /main.tf:4-8

Check: CKV_AWS_19: "Ensure all data stored in S3 is encrypted at rest"
  FAILED for resource: aws_s3_bucket.data
  File: /main.tf:4-8

Two failures, both on the same bucket, both with a line number you can jump to. The fix is a few lines of HCL, and because you caught it at the file you fix it in seconds rather than filing a remediation ticket against a live resource.

Scanning in CI versus scanning at runtime

There are two places to scan, and they answer different questions.

Scanning in continuous integration (CI) checks the code before it deploys. You add the scanner as a required step on every pull request. If a rule fails, the check fails, and the merge is blocked until someone fixes the configuration. This is preventive. It stops the misconfiguration from ever reaching the cloud, and it puts the fix in front of the engineer who wrote the code while the context is fresh.

Scanning at runtime checks the live environment. It looks at what is actually running in your account, not what your code says should be running. Runtime scanning catches two things CI cannot: drift, where someone changed a resource by hand after it was deployed, and resources created entirely outside of your IaC. CI has no visibility into either, because neither one is in the files.

You want both. CI scanning is your front door and catches the bulk of issues cheaply. Runtime scanning is your backstop for everything that bypasses the front door. A program that only does one of these has a blind spot.

Mapping findings to controls

A raw scanner finding says "this bucket has no encryption." That is useful to an engineer. It is not yet useful to an auditor, who wants to know which control the finding affects. Mapping closes that gap.

The same finding usually touches several frameworks at once. An unencrypted storage finding maps to the encryption expectations in SOC 2's Confidentiality criteria, to a CIS Benchmarks recommendation for that storage service, and to the protection family in NIST 800-53 Rev 5, where data-at-rest protection lives under the System and Communications Protection (SC) family. Map once, satisfy many.

  • SOC 2: Findings crosswalk to the Trust Services Criteria. Encryption and access findings land in the Security and Confidentiality criteria.
  • CIS Benchmarks: Many scanner rules are written directly against CIS recommendations, so the mapping is often one to one with a benchmark item.
  • NIST 800-53 Rev 5: Findings map to control families like Access Control (AC), Audit and Accountability (AU), and System and Communications Protection (SC).

When the mapping is automated, a single scan produces a finding that already speaks the language of every framework you report against. That is the difference between a security tool and a compliance tool, and it is what makes IaC scanning part of a GRC program rather than just a developer linter.

The tools that scan infrastructure as code

These are the open-source scanners practitioners actually use. You do not need all of them. Pick one with a strong policy library and add a custom engine later if you need rules of your own.

Checkov

Bridgecrew/Prisma Cloud scanner with a large built-in policy library for Terraform, CloudFormation, Kubernetes, and more. A common default for CI.

tfsec / Trivy

tfsec was a popular Terraform-focused scanner and has been merged into Aqua Security's Trivy, which now scans IaC alongside images and dependencies.

KICS

Checkmarx's open-source scanner ("Keeping Infrastructure as Code Secure") with broad coverage across Terraform, CloudFormation, Kubernetes, and Helm.

Open Policy Agent (OPA)

A general policy engine. You write rules in the Rego language and run them with Conftest. Reach for OPA when you need custom policy the prebuilt scanners do not cover.

Checkov, Trivy, and KICS ship hundreds of prewritten policies, so you get value the moment you run them. OPA is the one you grow into when your policy needs outrun what comes in the box.

Where the claude-grc-engineering toolkit fits

The open-source claude-grc-engineering toolkit, built by the GRC Engineering Club, wraps this workflow in a single command. It runs the underlying scanners and then does the part those scanners leave to you: the control mapping.

/grc-engineer:scan-iac ./terraform --frameworks=SOC2,CIS,NIST-800-53

That returns the misconfigurations a scanner would find, already crosswalked to SOC 2, the CIS Benchmarks, and NIST 800-53 Rev 5, in the same structured finding format the rest of the toolkit uses. So an IaC violation reads the same way as a finding from your cloud account or your GitHub configuration, and it slots straight into a gap report.

The toolkit can also draft the remediation. With the optional auto-fix, it proposes the Terraform or manifest change that clears the finding, for example adding the encryption block or tightening the security group. Treat that the way you would treat a junior engineer's pull request: useful and fast, and subject to your review before it ships. For the broader picture of automating these checks across your program, see GRC automation, and for how this connects to audit, read auditing infrastructure as code.

Frequently Asked Questions

What is IaC compliance scanning?

Infrastructure as code (IaC) compliance scanning is the practice of analyzing IaC files, like Terraform, CloudFormation, and Kubernetes manifests, against security and compliance rules before they deploy. The scanner reads the declared configuration, flags violations such as unencrypted storage or open security groups, and maps each finding back to controls in frameworks like SOC 2, the CIS Benchmarks, or NIST 800-53 Rev 5.

How do you scan Terraform for compliance?

Point a policy scanner at your Terraform directory or plan output. Tools like Checkov, Trivy, and KICS ship hundreds of built-in policies that parse the HCL, evaluate each resource, and return pass or fail with the file and line number. Run the scan locally while you write the code, then run it again as a required step in your continuous integration (CI) pipeline so a failing check blocks the merge.

What tools scan infrastructure as code?

The most common open-source IaC scanners are Checkov, tfsec (now merged into Trivy), KICS, and Open Policy Agent (OPA) with its Conftest runner. Checkov, Trivy, and KICS ship large libraries of prewritten policies for Terraform, CloudFormation, and Kubernetes. OPA is a general policy engine you use when you need to write custom rules in the Rego language.

When should IaC scanning run?

Run it in two places. First, locally or as a pre-commit hook so engineers see violations while they write the code. Second, in CI as a required check on every pull request so nothing merges with an open finding. Scanning IaC in CI catches misconfigurations before deploy. Pair it with runtime scanning of the live environment to catch drift and resources created outside of code.

Scan your IaC against real controls

You learned what IaC compliance scanning is, how it catches misconfigurations before deploy, the difference between CI and runtime, and how findings map to SOC 2, the CIS Benchmarks, and NIST 800-53 Rev 5. The toolkit turns all of that into one command.