Checkov, Trivy, and Terrascan compared for Terraform scanning: tfsec's move into Trivy, Terrascan's archival, and where each scanner fits in CI.
Imagine a security team that runs tfsec against its Azure Terraform repository, gets 12 findings, fixes them, and merges with confidence. Two weeks later, Microsoft Defender for Cloud flags a storage account that allows anonymous blob reads. The scanner they trusted had stopped receiving new checks, and nobody on the team knew.
That scenario is illustrative, but the gap is real. The IaC scanning landscape moved, and a comparison written even a year ago can mislead you. Before you pick a scanner, you need to know which of these tools still receive updates at all.
Checkov and Trivy are actively maintained, tfsec now lives inside Trivy, and Terrascan is archived. Pick between Checkov and Trivy for a new pipeline, and treat Terrascan as a migration task.
| Tool | Status | Best for |
|---|---|---|
| Checkov | Active (Palo Alto Networks) | Deep IaC policy coverage |
| Trivy | Active (Aqua Security) | One binary, many targets |
| tfsec | Redirects to Trivy | Nothing new, migrate |
| Terrascan | Archived Nov 20, 2025 | Nothing new, migrate |
Check each project's releases page for current version numbers before you pin anything, because both active tools ship frequently.
Static IaC scanning reads your .tf files, or a terraform plan JSON, and checks resource configuration against a ruleset before anything reaches a cloud account. The scanners differ in breadth and in how you extend them.
trivy config), container images, filesystems, and Kubernetes. It has fewer IaC-specific policies than Checkov and lacks graph-based cross-resource checks, but custom policies use Rego.tfsec's rules now live inside Trivy, and the standalone tfsec repository points users to it. The merge began in 2023, but plenty of pipelines still call tfsec directly, which is the real 2026 problem: the old command works, yet new coverage lands only in Trivy.
## Old workflow (deprecated)tfsec ./terraform/ ## Current workflow, same checks, actively maintainedtrivy config ./terraform/Every tfsec check ID, for example AVD-AWS-0086, works unchanged inside Trivy. That means existing findings and compliance mappings carry over without a rule rewrite. If your CI parses tfsec's flags or output format, budget a small config update because Trivy's equivalents differ slightly.
## GitLab CI: Trivy replacing tfseciac-scan: stage: security image: aquasec/trivy:<pinned-version> script: - trivy config --exit-code 1 --severity HIGH,CRITICAL ./terraform/š Remember: Pin the scanner version instead of using latest. A known regression in Trivy v0.60.0 caused panics on some Terraform configurations, and an unpinned image would have broken every pipeline overnight.
Tenable archived Terrascan on November 20, 2025, and the repository is now read-only. It still runs, but nothing behind it is changing: no CVE fixes, no rule updates, and no coverage for new cloud resource types.
## This still runs, but the rules are frozenterrascan scan -i terraform -d ./terraformTerrascan's OPA/Rego engine was genuinely differentiated. Teams could reuse one policy language across Kubernetes admission control and Terraform scanning, and it shipped a drift-detection feature. That does not offset an archived repository. Treat it like any unmaintained dependency: acceptable for a short migration window, a growing liability after that. Teams that valued Rego can keep it with Trivy (Rego custom policies) or Open Policy Agent directly.
Both tools catch the classic mistakes, such as public storage, and report them with a check ID, a file, and a line number. Here is the storage account from the opening scenario, in a form both Checkov and Trivy will flag, followed by the fixed version:
## Flagged: anonymous blob access allowedresource "azurerm_storage_account" "logs" { name = "stlogsprod001" resource_group_name = azurerm_resource_group.main.name location = "centralindia" account_tier = "Standard" account_replication_type = "GRS" allow_nested_items_to_be_public = true}## Fixed: public access off, TLS 1.2 enforcedresource "azurerm_storage_account" "logs" { name = "stlogsprod001" resource_group_name = azurerm_resource_group.main.name location = "centralindia" account_tier = "Standard" account_replication_type = "GRS" allow_nested_items_to_be_public = false min_tls_version = "TLS1_2"}When a finding is a genuine exception, suppress it inline with a reason so a reviewer can see the decision:
resource "aws_s3_bucket" "website" { ## checkov:skip=CKV_AWS_18:Access logs not needed for public site bucket = "example-public-site"}Trivy uses the same idea with ## trivy:ignore:AVD-AWS-0086 placed on the line above the resource. Review suppressions in pull requests, or they quietly become permanent blind spots.
A mature pipeline runs scanners at different stages instead of relying on one gate. Fast, narrow checks run on the developer's machine, a broader gate runs before merge, and a runtime control catches drift after deploy.
The commands for each stage:
## 1. Pre-commit: fast local feedbacktrivy config ./terraform/ --severity HIGH,CRITICAL ## 2. CI pre-merge: broader, deeper gatecheckov -d ./terraform/ --compact --quiet ## 3. Scan the resolved plan, not just the sourceterraform plan -out=tfplanterraform show -json tfplan > tfplan.jsoncheckov -f tfplan.jsontrivy config tfplan.jsonScanning the plan JSON matters because variables, modules, and conditionals are already resolved, so the scanner sees what will actually be applied. Both tools can emit SARIF (checkov -o sarif, trivy config -f sarif -o results.sarif) for GitHub or GitLab code scanning. If you use the Checkov GitHub Action, pin it to a release tag and not master.
Choose on coverage and extensibility, not on which logo you prefer.
| Factor | Checkov | Trivy |
|---|---|---|
| Maintenance | Active | Active |
| Scope | IaC-focused, many frameworks | IaC, images, filesystem, K8s |
| Custom policies | Python or YAML | Rego |
Checkov's breadth and cross-resource graph checks make it the stronger default when your repository mixes Terraform with Kubernetes manifests or CloudFormation: one CLI, one policy library, and one report format. Trivy earns its place as the fast gate, especially for teams already using it for container image scanning, since one binary then covers both jobs.
For runtime, an IaC scanner is the wrong tool. Admission controllers such as OPA Gatekeeper or Kyverno enforce policy on live Kubernetes resources, and cloud-native tools (Defender for Cloud, AWS Config, Security Command Center) catch drift after deploy.
For a new Terraform security pipeline started today, do not adopt Terrascan, because its archival means no future coverage for new AWS, Azure, or GCP resource types. Do not adopt standalone tfsec either. Move directly to trivy config.
For teams subject to PCI DSS or RBI requirements, run Checkov in CI as the policy gate and Trivy pre-commit for fast iteration. The two are complementary: one catches issues before a developer opens a pull request, the other catches what the first gate missed. A scanner helps you evidence controls, but passing it does not certify compliance, so map findings to your own control framework.
If you have existing Terrascan pipelines, plan a migration window instead of an emergency rip-and-replace. Run Checkov or Trivy alongside Terrascan for a sprint, compare findings, port any custom Rego policies, then remove Terrascan.
Finally, fail the build on HIGH and CRITICAL findings only at first. Teams that start with every severity blocking usually end up disabling the scanner, which is worse than no scanner.
NoteReferences and Further Reading
- Trivy Documentation - IaC scanning and tfsec migration guide
- Checkov Documentation - Policy library and CI/CD integration
- tfsec repository - Transition notes pointing to Trivy
- Terrascan repository - Archived by Tenable in November 2025
No. Tenable archived Terrascan on November 20, 2025, so the repository is read-only. Existing pipelines keep running, but there will be no CVE fixes, rule updates, or support for new cloud resource types, so it is not a sound choice for a new pipeline.
Yes. Trivy absorbed tfsec's rule library, and tfsec check IDs such as AVD-AWS-0086 work unchanged inside trivy config. Existing suppressions and compliance mappings carry over, though you should re-test CI flags and output parsing because they differ slightly.
Running both at different stages is a strong pattern. Use Trivy as a fast pre-commit gate, especially if you already scan container images with it, and Checkov in CI as the broader gate, since it offers more IaC-specific policies and graph-based cross-resource checks.
Add an inline comment on the resource. Checkov uses a checkov:skip=CKV_ID:reason comment and Trivy uses a trivy:ignore:AVD-ID comment. Always include a reason and review suppressions in code review, otherwise they become permanent blind spots.
Plan output has variables, modules, and conditionals already resolved, so the scanner sees the values that will actually be applied. Raw .tf files can hide misconfigurations behind variables or remote modules. Run terraform show -json on the plan file and scan that JSON.
Discussion0