Testland
Browse all skills & agents

checkov-policy

Configures Checkov for IaC security scanning across Terraform, CloudFormation, Kubernetes, Helm, ARM, Serverless, AWS CDK - `pip install checkov`, custom Python checks, SARIF / JUnit output, and `--baseline` gating so CI fails only on new findings in legacy code. Use for the broadest built-in rule set with Python custom checks; for Terraform-only scanning use tfsec-policy, for wider platform breadth (OpenAPI / Pulumi / Crossplane) use kics-policy, and for a consolidated new-project scanner use trivy-config.

Install with skills.sh (any agent)

npx skills add testland/qa --skill checkov-policy
View source

checkov-policy

Overview

Per checkov-home (opens in new window), supported frameworks: Terraform and Terraform plan, CloudFormation, Kubernetes, Helm, ARM Templates, Serverless framework, AWS CDK. Checkov is the broadest IaC security scanner - covers more frameworks than tfsec (Terraform-only) or KICS (similar coverage but Checkov has more built-in checks per release).

When to use

  • Team uses any of the supported IaC frameworks.
  • Need security scanning for misconfigurations (open ports, unencrypted storage, overly broad IAM, etc.).
  • Want one tool covering Terraform + Kubernetes + Dockerfile + CI pipelines.

How to use

  1. Install Checkov and pin the version in requirements-dev.txt for CI determinism (Step 1).
  2. Run checkov -d . locally, narrowing frameworks with --framework when the repo mixes IaC types (Step 2).
  3. Emit SARIF for GitHub Code Scanning and JUnit for CI test reporting (Step 3).
  4. Triage findings - fix real issues, annotate intentional exceptions with justified checkov:skip= comments (Step 4).
  5. Add custom Python or YAML checks for team-specific policy the built-in rules miss (Step 5).
  6. Create a .checkov.baseline so CI fails only on new findings, then wire the scan into CI with SARIF upload (Steps 7-8).
  7. Pair with tfsec / KICS and unify the reports for overlapping-but-non-identical coverage (Step 9).

Step 1 - Install

pip install checkov
checkov --version

Per project (recommended for CI determinism):

echo 'checkov==3.2.500' >> requirements-dev.txt
pip install -r requirements-dev.txt

Step 2 - Run

# Scan a directory
checkov -d .

# Scan a specific Terraform file
checkov -f main.tf

# Scan multiple frameworks
checkov -d . --framework terraform,kubernetes,dockerfile

# Scan a Terraform plan (deeper analysis)
terraform plan -out=plan.tfplan
terraform show -json plan.tfplan > plan.json
checkov -f plan.json

Step 3 - Output formats

# Default (CLI)
checkov -d .

# JSON for parsing
checkov -d . -o json

# SARIF for code-scanning dashboards (GitHub Code Scanning)
checkov -d . -o sarif --output-file-path checkov.sarif

# JUnit XML for CI test reporting
checkov -d . -o junitxml > checkov.xml

# Multiple
checkov -d . -o cli -o sarif

Step 4 - Skip checks

# Skip specific checks
checkov -d . --skip-check CKV_AWS_18,CKV_AWS_20

# Skip a check class
checkov -d . --skip-check CKV_AWS_*

In code:

# main.tf
resource "aws_s3_bucket" "logs" {
  bucket = "my-logs"

  # checkov:skip=CKV_AWS_20:Public read access intentional for log distribution
}

The :skip= annotation requires a justification - reviewable in PRs.

Step 5 - Custom Python checks

Author custom Python checks (and the no-code YAML-policy alternative) for team-specific rules the built-in set misses: references/custom-checks-and-ci.md.

Step 6 - Soft fail / hard fail

# Default: any failed check exits non-zero (CI fails)
checkov -d .

# Soft fail: log issues but exit 0 (informational)
checkov -d . --soft-fail

# Soft fail only on specific checks
checkov -d . --soft-fail-on CKV_AWS_*

Pattern: hard fail on critical / new findings; soft fail on legacy issues being ratcheted down.

Step 7 - Baseline comparison

# Generate baseline (current state of findings)
checkov -d . --create-baseline

# Use baseline (fail only on NEW findings vs baseline)
checkov -d . --baseline .checkov.baseline

Baselines let teams adopt Checkov against legacy code without fixing all existing issues at once - only new findings break the build.

Step 8 - CI integration

Wire the scan into CI with a baseline plus SARIF upload to GitHub Code Scanning (findings surface as PR comments + the Security tab): references/custom-checks-and-ci.md.

Step 9 - Combine with other scanners

Checkov + tfsec + KICS catch overlapping but non-identical issues. Combine results to a unified verdict.

checkov -d . -o json > checkov.json
tfsec . -f json > tfsec.json
kics scan -p . --report-formats json -o ./kics-results
# Combine the three reports into a unified verdict

Worked example

A team adopts Checkov on a legacy Terraform + Kubernetes monorepo.

  1. pip install checkov==3.2.500, pinned in requirements-dev.txt.
  2. First run checkov -d . --framework terraform,kubernetes reports a large backlog of existing failures - too many to fix at once.
  3. They capture the current state: checkov -d . --create-baseline writes .checkov.baseline.
  4. CI runs checkov -d . --baseline .checkov.baseline -o sarif --output-file-path checkov.sarif; the build passes because no findings are new versus the baseline.
  5. A PR adds an aws_s3_bucket with acl = "public-read". Checkov flags CKV_AWS_20 as a NEW finding and fails the build.
  6. The author drops public-read (or adds a justified checkov:skip=CKV_AWS_20 comment); the SARIF upload clears the Security-tab entry and the build goes green.

Result: legacy debt is ratcheted down, not ignored, and each PR is gated only on net-new misconfigurations.

Anti-patterns

Anti-patternWhy it failsFix
Skipping all failed checks via --skip-checkDefeats security scanning.Per-check checkov:skip= with justification (Step 4).
Baseline never updatedLegacy issues never fixed; only-new gating becomes meaningless.Periodic baseline review + ratchet down.
Checkov as the only IaC scannerTool-specific gaps; some issues missed.Pair with tfsec / KICS (Step 9).
Ignoring SARIF / GitHub Security tabFindings invisible until someone runs the CLI.SARIF upload (Step 8).
Custom checks without testsCustom logic bugs let bad config through.Test custom checks (per OPA's opa test pattern).

Limitations

  • Per-framework rule depth varies. Terraform / Kubernetes have hundreds of rules; ARM / Serverless have fewer.
  • False positives common in early adoption. Use baseline to manage.
  • Performance on large repos. Checkov scans whole-tree; can take minutes.
  • Built-in rules may not match team policy. Custom checks for team-specific rules (Step 5).

References

  • ch (opens in new window) - Checkov overview, supported IaC frameworks, common CLI usage, Palo Alto Networks maintainer.
  • tfsec-policy, kics-policy - sister scanners.
  • policy-as-code-runner - custom policies via OPA / Conftest (Checkov for built-in; OPA for custom).

Checkov custom checks and CI integration

View source (opens in new window)

Checkov custom checks and CI integration

Custom Python checks

# .checkov/custom_checks/cost_center_tag.py
from checkov.common.models.enums import CheckCategories, CheckResult
from checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck

class CostCenterTagPresent(BaseResourceCheck):
    def __init__(self):
        super().__init__(
            name="Ensure all EC2 instances have a cost_center tag",
            id="CKV_CUSTOM_001",
            categories=[CheckCategories.GENERAL_SECURITY],
            supported_resources=['aws_instance'],
        )

    def scan_resource_conf(self, conf):
        tags = conf.get('tags', [{}])[0]
        if 'cost_center' in tags:
            return CheckResult.PASSED
        return CheckResult.FAILED

check = CostCenterTagPresent()
checkov -d . --external-checks-dir .checkov/custom_checks

For custom YAML policies (no Python required), use the graph-based policies/ directory (Checkov supports YAML rules).

CI integration

jobs:
  iac-security:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-python@v5
        with: { python-version: '3.13' }
      - run: pip install checkov
      - name: Run Checkov
        run: checkov -d . --output sarif --output-file-path checkov.sarif --baseline .checkov.baseline
      - uses: github/codeql-action/upload-sarif@v3
        if: always()
        with:
          sarif_file: checkov.sarif

The SARIF upload to GitHub Code Scanning surfaces findings as PR comments + the Security tab.

Related skills

helm-chart-tester

Configures helm-unittest for Helm chart unit testing - installs the `helm-unittest` plugin, authors `tests/*.yaml` per template, asserts on rendered manifests (`isKind`, `equal`, `matchRegex`, snapshots), plus `helm lint` and `helm template` render testing. Use to verify a chart's template logic and rendered shape; this is unit-level correctness testing, not security scanning - to enforce policy on rendered manifests use policy-as-code-runner, and to scan charts for misconfigurations use checkov-policy or kics-policy.

kics-policy

Configures KICS (Keeping Infrastructure as Code Secure), Checkmarx's scanner covering Terraform, Kubernetes, Helm, Dockerfile, OpenAPI, Ansible, ARM, CloudFormation, Pulumi, Crossplane - CLI / Docker / GitHub Action / pre-commit, JSON / SARIF / HTML / JUnit output, custom Rego queries. Use for the widest platform breadth, especially OpenAPI / Pulumi / Crossplane; for the broadest built-in checks with Python custom rules use checkov-policy, for Terraform-only scanning use tfsec-policy, and for a consolidated scanner use trivy-config.

policy-as-code-runner

Configures policy-as-code testing using OPA / Conftest / Cedar - authors policies in Rego (OPA's language), runs Conftest against Kubernetes manifests / Terraform plans / Dockerfiles / arbitrary structured data, integrates with CI for PR-time policy gates. Per OPA's docs: "an open source, general-purpose policy engine that unifies policy enforcement across the stack." Use to express + enforce custom policies (cost limits, tagging requirements, security baselines) that Checkov / tfsec / KICS don't cover.

tfsec-policy

Configures tfsec for Terraform-specific security scanning - covers AWS / Azure / GCP / Kubernetes / OpenStack / Oracle / DigitalOcean / CloudStack, custom YAML rules, and SARIF / JUnit / Markdown output. Note: tfsec is transitioning to Trivy per Aqua Security, so new projects evaluate that first. Use for an existing Terraform-only tfsec stack; for the consolidated forward-path scanner use trivy-config, for the broadest multi-framework checks use checkov-policy, and for wider platform breadth use kics-policy.

trivy-config

Runs Trivy's misconfiguration scanner (`trivy config`) against IaC directories to detect security issues across Terraform, CloudFormation, Kubernetes manifests, Helm charts, Dockerfiles, and Azure ARM templates - installs Trivy, scans with severity gating via `--exit-code`, suppresses findings via `.trivyignore` / `.trivyignore.yaml` or inline annotations, extends built-in checks with custom Rego policies, and emits SARIF for GitHub Code Scanning. Trivy is the forward path from tfsec (per Aqua Security's own migration guidance). Use when adopting a consolidated IaC scanner for new projects, migrating away from tfsec, or scanning mixed IaC stacks with a single tool.