Infrastructure as Code (IaC) brings version control to infrastructure, but it also introduces the risk of deploying architecture-level misconfigurations at scale. While TFSEC is well known in the community, this article demonstrates Checkov – an open-source static analysis tool with graph-based scanning, over 1,000 built-in policies, and robust support for Terraform, CloudFormation, Kubernetes, and more.
🤔 Why Checkov?
Checkov (developed by Bridgecrew) scans IaC for security and compliance violations. Unlike traditional pattern-based checkers that only look at resources in isolation, Checkov builds a graph of resources and their relationships.
This allows it to detect complex issues, such as an S3 bucket that is set to private but is missing an account-level public access block.
🚨 The Problem: Vulnerable Terraform Configuration
Let's look at a problematic main.tf file. On the surface, it deploys standard AWS resources, but it contains three major security violations:
provider "aws" { region = "us-east-1" }
# Violation 1: Public S3 bucket
resource "aws_s3_bucket" "data_bucket" {
bucket = "my-company-data-2026"
acl = "public-read" # Checkov: CKV_AWS_18
}
# Violation 2: SSH open to world
resource "aws_security_group" "web_sg" {
name = "web_sg"
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # Checkov: CKV_AWS_5
}
}
# Violation 3: RDS without encryption
resource "aws_db_instance" "default" {
allocated_storage = 20
engine = "mysql"
instance_class = "db.t3.micro"
storage_encrypted = false # Checkov: CKV_AWS_16
}
🛠️ Installing and Running Checkov
You can easily install Checkov via Python's package manager or run it directly through Docker.
Install via pip:
pip install checkov
Or use Docker:
docker run --tty --volume "$(pwd):/tf" bridgecrew/checkov --directory /tf
Run the scan in your project directory:
checkov -d .
Sample Output
Checkov instantly identifies the vulnerable configurations and maps them to specific AWS security policies:
Check: CKV_AWS_18: "Ensure the S3 bucket has public access blocks"
FAILED for resource: aws_s3_bucket.data_bucket
File: /main.tf:6-10
Check: CKV_AWS_5: "Ensure security groups restrict SSH from 0.0.0.0/0"
FAILED for resource: aws_security_group.web_sg
Check: CKV_AWS_16: "Ensure all data stored in the RDS is securely encrypted at rest"
FAILED for resource: aws_db_instance.default
✅ Remediation Steps
To pass the Checkov scan, we need to apply the following fixes to our infrastructure code:
1. Fix the S3 Bucket:
Set the ACL to private and attach a Public Access Block resource.
resource "aws_s3_bucket" "data_bucket" {
bucket = "my-company-data-2026"
acl = "private"
}
resource "aws_s3_bucket_public_access_block" "block" {
bucket = aws_s3_bucket.data_bucket.id
block_public_acls = true
block_public_policy = true
}
2. Fix the Security Group: Change cidr_blocks = ["10.0.0.0/16"] to restrict SSH access to an internal network only.
3. Fix the RDS Instance: Set storage_encrypted = true and ensure it references a valid KMS key.
🚀 CI/CD Integration with GitLab CI
Finding vulnerabilities locally is good, but preventing them from being merged is better. Here is how to integrate Checkov into your GitLab CI pipeline by creating a .gitlab-ci.yml file:
stages:
- validate
checkov-scan:
stage: validate
image: bridgecrew/checkov:latest
script:
- checkov --directory . --quiet --output cli --soft-fail
artifacts:
reports:
terraform: checkov_report.json
only:
- merge_requests
- main
Pro Tip: We use
--soft-failso the pipeline does not break on violations (it only reports them). Once your team is accustomed to the tool, remove--soft-failto enforce hard security gates.
⚙️ Custom Policies with YAML
Checkov allows you to write custom organizational rules. For example, if you want to prevent developers from provisioning specific instance types to control costs, you can create a .checkov.yaml config map:
custom-policies:
- name: "Prohibit t2.micro instances"
file: custom_policies/prohibit_t2_micro.yaml
Content of prohibit_t2_micro.yaml:
metadata:
id: CUSTOM_1
name: "No t2.micro allowed"
category: "COST_OPTIMIZATION"
definition:
cond_type: "attribute"
resource_types: "aws_instance"
attribute: "instance_type"
operator: "not_equals"
value: "t2.micro"
To run Checkov with your new custom policy:
checkov -d . --external-checks-dir ./custom_policies
⏭️ Skipping False Positives
Sometimes, a resource like an S3 bucket needs to be public (e.g., for static website hosting). You can suppress Checkov warnings by adding a simple inline comment inside your Terraform code:
resource "aws_s3_bucket" "data_bucket" {
# checkov:skip=CKV_AWS_18:This bucket is for public static website hosting
bucket = "my-public-website"
acl = "public-read"
}
🎯 Conclusion
Checkov is a mature, highly active SAST tool for Infrastructure as Code. By integrating it into your CI/CD pipeline, you prevent misconfigurations—like open S3 buckets or unencrypted databases—from ever reaching production.
As a TFSEC alternative, it stands out by offering broader framework support (including Kubernetes, CloudFormation, and Pulumi) and intelligent, graph-based security analysis.
Top comments (0)