DEV Community

Cover image for Applying Checkov to Terraform as Code: A TFSEC Alternative
IKER ALBERTO SIERRA RUIZ
IKER ALBERTO SIERRA RUIZ

Posted on

Applying Checkov to Terraform as Code: A TFSEC Alternative

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
}
Enter fullscreen mode Exit fullscreen mode

🛠️ 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
Enter fullscreen mode Exit fullscreen mode

Or use Docker:

docker run --tty --volume "$(pwd):/tf" bridgecrew/checkov --directory /tf
Enter fullscreen mode Exit fullscreen mode

Run the scan in your project directory:

checkov -d .
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

✅ 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
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Pro Tip: We use --soft-fail so the pipeline does not break on violations (it only reports them). Once your team is accustomed to the tool, remove --soft-fail to 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
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

To run Checkov with your new custom policy:

checkov -d . --external-checks-dir ./custom_policies
Enter fullscreen mode Exit fullscreen mode

⏭️ 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"
}
Enter fullscreen mode Exit fullscreen mode

🎯 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)