Terraform IaC Security Scanning in 2025: Checkov, tfsec, Semgrep Rules and Drift Detection
Cloud Security
Misconfigured infrastructure-as-code is the most common source of cloud security findings in 2025. This post covers the scanning toolchain — Checkov, tfsec, Semgrep — how to write custom rules for your environment, and how to detect drift between your Terraform state and what is actually running in cloud.
By Arjun Raghavan, Security & Systems Lead, BIPI · September 13, 2025 · 10 min read
Infrastructure-as-code is the dominant cloud provisioning model. It is also one of the most reliable sources of security debt. A Terraform module that provisions an S3 bucket with public ACLs, a security group with 0.0.0.0/0 ingress on port 22, or an IAM role with AdministratorAccess gets deployed hundreds of times across environments before anyone notices. The fix is shifting security left into the IaC pipeline — scanning before apply, not after incident.
In 2025, the IaC security scanning ecosystem has matured significantly. Checkov, tfsec, and Semgrep each have distinct strengths. The organizations that get the most value from IaC scanning combine all three, suppress false positives systematically, and close the loop with drift detection to catch resources that were modified outside of Terraform.
IaC scanning without drift detection is a policy for new resources. Drift detection is the policy for everything already running.
Checkov — breadth and policy-as-code
Checkov is the most comprehensive open-source IaC scanner. It covers Terraform, CloudFormation, ARM templates, Kubernetes manifests, Helm charts, Dockerfiles, and GitHub Actions workflows. Its 1,200+ built-in checks cover CIS benchmarks, NIST standards, and vendor best practices. Checkov outputs SARIF, which integrates natively with GitHub Advanced Security and Azure DevOps security tabs.
Checkov's custom policy framework uses Python or YAML. A YAML check that fails any S3 bucket without versioning enabled is five lines. The check registry is extensible and can pull custom policies from a separate Git repository, which allows security teams to maintain custom rules independently from the Terraform code they scan.
tfsec — speed and Terraform-native analysis
tfsec (now maintained as part of the Trivy project) is faster than Checkov for Terraform-only codebases because it understands the Terraform HCL graph natively. It follows variable references, module calls, and locals, which means it can detect misconfigurations that require understanding the resolved value of a variable — something grep-based tools miss. Running tfsec as a pre-commit hook adds under 2 seconds to a commit for most codebases.
Semgrep — custom rule writing for your organization
Semgrep's value in the IaC context is custom rule writing. Built-in rules cover generic misconfigurations, but your organization's specific policies — no resources in us-east-1 outside of DR, all RDS instances must have deletion protection, all Lambda functions must have reserved concurrency — require custom rules. Semgrep's pattern syntax is the clearest of the three tools for expressing these organization-specific policies.
- Use Checkov for comprehensive baseline scanning and CIS benchmark compliance.
- Use tfsec as a pre-commit hook for fast feedback during development.
- Use Semgrep for organization-specific policy rules that go beyond vendor benchmarks.
- Run all three in CI and block on HIGH severity findings; MEDIUM severity goes to a findings backlog with SLA.
Suppression management — avoiding alert fatigue
IaC scanning generates false positives. A finding that correctly identifies a security group allowing all outbound traffic is a false positive if that security group is intentionally permissive for a NAT gateway. The right response is a suppression comment with a business justification, not a policy exclusion. The suppression is inline with the code, reviewable in PRs, and does not silently exclude checks.
Drift detection — closing the loop
Terraform drift occurs when a resource's actual configuration diverges from its Terraform state. The most common cause is manual console changes. Drift detection runs terraform plan in a non-apply mode and alerts when the plan is non-empty. This approach finds drift but does not tell you if the drift is a security regression.
A better approach is to combine terraform plan output with the IaC scanner: generate the plan as JSON, scan the plan JSON with Checkov using the terraform_plan file type, and alert on new HIGH findings in the plan. This surfaces security regressions introduced by drift, not just any configuration change.
- Schedule terraform plan in CI on a cron — daily for production, hourly for sensitive environments.
- Parse plan JSON with Checkov to identify security regressions in drift.
- Alert via Slack or PagerDuty when the plan is non-empty and contains new HIGH-severity findings.
- Establish a drift remediation SLA: console changes must be reconciled to IaC within 24 hours.
- Use Terraform Cloud or Spacelift drift detection for automated drift remediation where appropriate.
Closing
IaC security scanning is table stakes in 2025. The organizations that get value from it are not the ones with the most rules — they are the ones with the lowest suppression rates, the fastest developer feedback loops, and the closed-loop drift detection that catches what slipped through. Start with Checkov in CI, add tfsec as a pre-commit hook, and schedule daily drift detection. The time investment pays back in the first cloud security incident you prevent.
Read more field notes, explore our services, or get in touch at info@bipi.in. Privacy Policy · Terms.