
Table of Contents
By Khimananda Oli | Last reviewed: August 2026
Deploying Infrastructure as Code without automated validation is a liability, not an asset. Using Checkov: Scan Terraform for Misconfigurations allows you to catch security gaps, compliance violations, and architectural flaws before they ever reach your cloud provider. This static analysis tool integrates directly into your workflow to enforce best practices consistently across AWS, Azure, GCP, and Kubernetes environments. If you are already managing state with Terraform state management and remote backends, adding policy scanning is the necessary next step to secure that infrastructure lifecycle.
How do you install and run Checkov to scan Terraform for misconfigurations?
Getting started requires minimal setup. Checkov is distributed via pip, Homebrew, and Docker, making it accessible regardless of your local environment. For most DevOps workflows in 2026, I recommend using the containerized version to avoid Python dependency conflicts on developer machines, though pip remains the fastest path for quick ad-hoc checks.
Installation methods
- Pip (Python 3.8+):
pip install checkov— simplest for local development. - Homebrew (macOS/Linux):
brew install checkov— keeps the binary isolated from system Python. - Docker:
docker pull bridgecrew/checkov— preferred for CI runners and reproducible environments.
Running your first scan
Navigate to your Terraform root module directory and execute the baseline scan. The default output is human-readable CLI text, which is excellent for debugging but insufficient for automation.
# Basic scan of current directory
checkov -d .
# Scan specific file with JSON output for parsing
checkov -f main.tf -o json
# Scan with compact output (one line per check)
checkov -d . -o cli --compact A common mistake is scanning only individual files (-f) instead of directories (-d). Checkov builds a resource graph to understand relationships between modules, variables, and data sources. Scanning a single file in isolation often produces false positives because the tool cannot resolve variable values or module outputs defined elsewhere. Always prefer directory-level scans for accurate results.
Understanding the output structure
Each check result includes a unique ID (e.g., CKV_AWS_18), severity level, resource address, and remediation guidance. Passed checks confirm compliance; failed checks indicate actionable risks. Skipped checks appear when you have explicitly suppressed a policy. In my experience auditing SOC 2 environments, the "skipped" category deserves as much attention as failures — unjustified suppressions are often where real vulnerabilities hide.
How do you integrate Checkov into CI/CD pipelines to block insecure deployments?
Local scanning catches issues during development, but pipeline enforcement prevents drift. Integrating Checkov: Scan Terraform for Misconfigurations into your CI/CD system creates a mandatory quality gate. This aligns with the principles discussed in DevSecOps shift left strategies, ensuring security feedback arrives while changes are still cheap to fix.
GitHub Actions configuration
The official Bridgecrew action simplifies integration. Place this step after terraform fmt and terraform validate but before terraform plan. This ordering ensures you fail fast on syntax errors before spending time on expensive security scans.
- name: Run Checkov security scan
uses: bridgecrewio/checkov-action@v12
with:
directory: ./infrastructure
output_format: sarif
output_file_path: reports/checkov-results.sarif
skip_check: CKV_GIT_4
quiet: true
- name: Upload SARIF to GitHub Security Tab
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: reports/checkov-results.sarif Using SARIF output uploads findings directly to the GitHub Security tab, giving developers inline annotations on pull requests rather than forcing them to dig through CI logs. This dramatically reduces friction and increases adoption rates among teams new to policy as code practices.
Handling soft fails and baselines
Legacy codebases often contain hundreds of pre-existing violations. Blocking all of them immediately halts development. Use the --baseline flag to create a snapshot of current failures, then configure the pipeline to only fail on new violations introduced by the PR. This ratchet approach maintains momentum while preventing regression.
# Generate baseline from current state
checkov -d . -o json > checkov-baseline.json
# Run scan comparing against baseline
checkov -d . --baseline checkov-baseline.json How do you write custom Checkov policies for organization-specific requirements?
Built-in policies cover general cloud security, but every organization has unique constraints. You might require specific tagging schemas for cost allocation, restrict regions to Nepal or Singapore for data residency, or enforce naming conventions that encode team ownership. Custom policies bridge this gap using Python or YAML.
YAML-based custom policies (no-code)
For simple attribute checks, YAML policies are faster to write and easier to review. They live in a dedicated directory and are loaded via the --external-checks-dir flag.
metadata:
name: "Ensure all S3 buckets have project tag"
id: "CUSTOM_AWS_S3_PROJECT_TAG"
category: "CONVENTION"
severity: "MEDIUM"
scope:
provider: aws
definition:
and:
- cond_type: "attribute"
resource_types:
- "aws_s3_bucket"
attribute: "tags.project"
operator: "exists" Python-based custom policies (complex logic)
When validation requires conditional logic, API lookups, or cross-resource correlation, Python is necessary. Inherit from BaseResourceCheck and implement scan_resource_conf. Return CheckResult.PASSED, FAILED, or UNKNOWN.
from checkov.common.models.enums import CheckResult
from checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck
class EC2InstanceTypeRestriction(BaseResourceCheck):
def __init__(self):
super().__init__(
name="Ensure EC2 uses approved instance families",
id="CUSTOM_AWS_EC2_INSTANCE_TYPE",
categories=["CONVENTION"],
supported_resources=["aws_instance"]
)
def scan_resource_conf(self, conf):
instance_type = conf.get("instance_type", [None])[0]
approved_prefixes = ("t3.", "m6i.", "c6g.")
if instance_type and any(instance_type.startswith(p) for p in approved_prefixes):
return CheckResult.PASSED
return CheckResult.FAILED Store custom policies in a shared repository and reference them across all infrastructure repos. This centralizes governance and ensures consistent enforcement whether a team is building in Kathmandu or San Francisco.
How does Checkov compare to tfsec, Terrascan, and OPA for Terraform security?
Choosing the right scanner depends on your team's maturity, compliance needs, and existing toolchain. While Checkov: Scan Terraform for Misconfigurations is my default recommendation for most teams due to its breadth and CI ergonomics, alternatives excel in specific niches.
| Feature | Checkov | tfsec | Terrascan | OPA / Conftest |
|---|---|---|---|---|
| Language | Python / YAML | Go / Rego | Rego | Rego only |
| Built-in Policies | 1,500+ | 200+ | 600+ | 0 (user-defined) |
| Multi-framework | TF, K8s, Docker, ARM, Bicep, CloudFormation | TF only | TF, K8s, Helm, Docker | Any structured data |
| Custom Policy Ease | High (YAML option) | Medium (Rego) | Medium (Rego) | Steep (Rego only) |
| SARIF Output | Native | Native | Via plugin | Via conftest |
| Best For | General DevSecOps, multi-cloud | Pure TF teams wanting speed | Compliance-heavy audits | Platform engineers, bespoke policy |
In practice, many mature teams run both Checkov and tfsec. tfsec’s Go implementation scans large codebases significantly faster, providing rapid feedback on PRs, while Checkov runs nightly for comprehensive compliance coverage including Kubernetes manifests and Dockerfiles that tfsec ignores. OPA remains the choice for platform teams building internal developer platforms where policy must span admission control, CI gates, and runtime enforcement with a single language.
Make Checkov Part of Your Infrastructure Safety Net
Static analysis alone does not guarantee security, but deploying without it guarantees preventable incidents. Start by integrating Checkov: Scan Terraform for Misconfigurations into your primary CI pipeline with a baseline to avoid blocking existing work. Gradually add custom policies as your organizational standards solidify, and pair scanning with runtime monitoring like Prometheus and Grafana to catch what static analysis cannot. If your team needs help designing a compliant IaC workflow or tuning policies to reduce noise without sacrificing safety, reach out to discuss your infrastructure security strategy.