
Checkov is an open-source static code analysis tool for infrastructure-as-code (IaC) security. Bridgecrew built it, and Palo Alto Networks later acquired Bridgecrew. It scans cloud infrastructure configurations written in Terraform, CloudFormation, Kubernetes, Dockerfile, and ARM templates, then flags misconfigurations and security vulnerabilities before deployment. The checks run against predefined policies that catch the usual problems: unencrypted storage, too many permissions, open security groups, publicly exposed resources. Since it plugs into CI/CD pipelines and tells you how to fix what it finds, teams use it to move security earlier in development instead of auditing after the fact.
This post focuses on the Terraform and OpenTofu side of Checkov. Scalr has a native integration with Checkov, which we cover at the bottom.
Most infrastructure-as-code security incidents don't start with a clever attack. They start with a misconfigured resource: an unencrypted database, an IAM role that grants too much, a storage bucket left open. As more teams adopt IaC, those gaps multiply. Checkov scans your configuration files early in development and catches the problems before they reach production, where a single misconfiguration can turn into a data breach or a compliance violation. Fixing an issue in a pull request is also far cheaper than fixing it after it ships. Running the same checks on every change keeps your infrastructure aligned with standards like CIS, HIPAA, and SOC2 over time.
First, you’ll want to install Checkov using pip or brew. The full instructions are here.
To understand the basics of Checkov, let’s create a small Terraform module with a few deliberate security holes in it. Save the following Terraform file as main.tf:
provider "aws" { region = "us-west-2" }
resource "aws_s3_bucket" "example" { bucket = "my-example-bucket" }
resource "aws_s3_bucket_public_access_block" "example" { bucket = aws_s3_bucket.example.id
block_public_acls = false block_public_policy = false ignore_public_acls = false restrict_public_buckets = false }
This Terraform configuration file creates an AWS S3 bucket but deliberately has security issues (all public access controls are disabled).
Now, run the following command against this Terraform file:
checkov -f main.tf
The output will look something like this:
___| |__ ___ ___| | _______ __ / __| '_ \ / _ \/ __| |/ / _ \ \ / / | (__| | | | __/ (__| < (_) \ V / \___|_| |_|\___|\___|_|\_\___/ \_/
By Prisma Cloud | version: 3.2.380
terraform scan results:
Passed checks: 2, Failed checks: 4, Skipped checks: 0
Check: CKV_AWS_41: "Ensure no hard coded AWS access key and secret key exists in provider" PASSED for resource: aws.default File: /main.tf:1-3 Guide: https://docs.prismacloud.io/en/enterprise-edition/policy-reference/aws-policies/secrets-policies/bc-aws-secrets-5
Check: CKV_AWS_93: "Ensure S3 bucket policy does not lockout all but root user. (Prevent lockouts needing root account fixes)" PASSED for resource: aws_s3_bucket.example File: /main.tf:5-7 Guide: https://docs.prismacloud.io/en/enterprise-edition/policy-reference/aws-policies/s3-policies/bc-aws-s3-24
Check: CKV_AWS_53: "Ensure S3 bucket has block public ACLS enabled" FAILED for resource: aws_s3_bucket_public_access_block.example File: /main.tf:9-16 Guide: https://docs.prismacloud.io/en/enterprise-edition/policy-reference/aws-policies/s3-policies/bc-aws-s3-19
9 | resource "aws_s3_bucket_public_access_block" "example" { 10 | bucket = aws_s3_bucket.example.id 11 | 12 | block_public_acls = false 13 | block_public_policy = false 14 | ignore_public_acls = false 15 | restrict_public_buckets = false 16 | }
Check: CKV_AWS_54: "Ensure S3 bucket has block public policy enabled" FAILED for resource: aws_s3_bucket_public_access_block.example File: /main.tf:9-16 Guide: https://docs.prismacloud.io/en/enterprise-edition/policy-reference/aws-policies/s3-policies/bc-aws-s3-20
9 | resource "aws_s3_bucket_public_access_block" "example" { 10 | bucket = aws_s3_bucket.example.id 11 | 12 | block_public_acls = false 13 | block_public_policy = false 14 | ignore_public_acls = false 15 | restrict_public_buckets = false 16 | }
Check: CKV_AWS_55: "Ensure S3 bucket has ignore public ACLs enabled" FAILED for resource: aws_s3_bucket_public_access_block.example File: /main.tf:9-16 Guide: https://docs.prismacloud.io/en/enterprise-edition/policy-reference/aws-policies/s3-policies/bc-aws-s3-21
9 | resource "aws_s3_bucket_public_access_block" "example" { 10 | bucket = aws_s3_bucket.example.id 11 | 12 | block_public_acls = false 13 | block_public_policy = false 14 | ignore_public_acls = false 15 | restrict_public_buckets = false 16 | }
Check: CKV_AWS_56: "Ensure S3 bucket has 'restrict_public_buckets' enabled" FAILED for resource: aws_s3_bucket_public_access_block.example| File: /main.tf:9-16 Guide: https://docs.prismacloud.io/en/enterprise-edition/policy-reference/aws-policies/s3-policies/bc-aws-s3-22
9 | resource "aws_s3_bucket_public_access_block" "example" { 10 | bucket = aws_s3_bucket.example.id 11 | 12 | block_public_acls = false 13 | block_public_policy = false 14 | ignore_public_acls = false 15 | restrict_public_buckets = false 16 | }
Checkov has identified several security issues with the Terraform code:
To fix these issues, update your terraform file to include proper security configurations:
provider "aws" { region = "us-west-2" }
resource "aws_s3_bucket" "example" { bucket = "my-example-bucket" }
resource "aws_s3_bucket_versioning" "example" { bucket = aws_s3_bucket.example.id versioning_configuration { status = "Enabled" } }
resource "aws_s3_bucket_logging" "example" { bucket = aws_s3_bucket.example.id
target_bucket = aws_s3_bucket.example.id target_prefix = "log/"
}
resource "aws_s3_bucket_public_access_block" "example" { bucket = aws_s3_bucket.example.id
block_public_acls = true block_public_policy = true ignore_public_acls = true restrict_public_buckets = true
}
Execute Checkov against the main.tf file again to verify the updates worked.
Here are some advanced Checkov commands for finer control over what you scan and how Checkov reports it, for both Terraform and OpenTofu:
# Skip specific checks checkov -f main.tf --skip-check CKV_AWS_18,CKV_AWS_21
# Check only specific checks checkov -f main.tf --check CKV_AWS_53,CKV_AWS_54
# Specify a custom policy directory checkov -f main.tf --external-checks-dir /path/to/custom/checks
# Create and use custom policies checkov -f main.tf --external-checks-git https://github.com/your-org/custom-policies.git
# Use a specific branch for custom policies checkov -f main.tf --external-checks-git https://github.com/your-org/custom-policies.git --branch dev
# Generate JSON output checkov -f main.tf --output json
# Generate JUnit XML for CI integration checkov -f main.tf --output junitxml
# Save results to a file checkov -f main.tf --output json > results.json
# Generate SARIF format (for GitHub code scanning) checkov -f main.tf --output sarif
# Soft-fail (return code 0 even with failures) checkov -f main.tf --soft-fail
# Scan a Terraform plan file terraform plan -out=tfplan.binary terraform show -json tfplan.binary > tfplan.json checkov -f tfplan.json
# Scan for secrets in your code checkov -f main.tf --framework secrets
# Scan with multiple frameworks at once checkov -d . --framework terraform,secrets,dockerfile
# Scan specific variables checkov -f main.tf --var-file prod.tfvars
# Integrate with Bridgecrew platform checkov -f main.tf --bc-api-key <your_api_key>
Checkov supports custom policies in YAML format through its Policy-as-Code (PaC) framework, with a simplified YAML syntax. Custom policies require a metadata section to identify the general information about the policy and a definition section which defines the actual rules.
Here's a very basic custom policy that checks if an AWS S3 bucket has server-side encryption enabled:
metadata: id: "CUSTOM_AWS_001" name: "Ensure S3 buckets have encryption enabled" category: "encryption" severity: "MEDIUM"
definition: and: - resource_types: - aws_s3_bucket attribute: "server_side_encryption_configuration" operator: "exists"
Save this as s3_encryption_policy.yaml in a directory structure like:
custom_policies/
└── yaml/
└── s3_encryption_policy.yaml
Then run the following command with your custom policy:
checkov -f main.tf --external-checks-dir custom_policies
Scalr has a native integration with Checkov that automatically scans the Terraform or OpenTofu code before the Terraform plan runs. To use Checkov in Scalr, enable the integration, pick the version, and pass any custom parameters you need.

Once enabled, Checkov can then be enforced on all Scalr environments or select environments. Once enforced on environments, all runs within the environment will be forced to go through a Checkov scan before the Terraform plan executes:

If the Checkov scan is in hard failure mode, the Terraform run will automatically stop before the plan can execute.
Optionally, custom parameters can be passed to determine Checkov's behavior in Scalr. For example, the “--soft-fail” parameter can be passed to return a code of 0, which will allow the run to continue.
Other options like skip-check or –external-checks can also be used as a custom parameter.
See all available parameters here.
Scalr supports importing and enforcing custom Checkov policies from external repositories. Users can specify a VCS provider, repository, branch, and folder containing their custom Checkov checks, which will be evaluated as part of the policy enforcement in designated environments.

Anyone who has used Checkov knows that jumping from one version to another can take planning. Scalr lets you run multiple versions of Checkov on a single environment so you can stage the upgrade. Keep your current version on its strict setting and add the new version in soft-fail mode, so anything the newer version flags won't block runs yet. That gives your team time to look at whatever the new version finds in their Terraform code and fix it before the upgrade is enforced.
Checkov catches Terraform misconfigurations automatically before they reach production, when a fix is a quick code change instead of a production incident. Running it on every change also keeps your configurations consistent with frameworks like CIS, HIPAA, and SOC2.
If you want the quickest path, the Scalr integration runs Checkov during development without any CI/CD wiring on your side.
This blog has been verified for Terraform and OpenTofu
