# how to scan Terraform for misconfigurations with checkov

## TL;DR
Install Checkov with pip, run `checkov -d .` in your Terraform root, and it checks your HCL against 1000+ built-in policies for things like public S3 buckets and unencrypted EBS volumes. Wire it into CI with a hard fail so bad config never reaches apply. Fix the flagged resource blocks instead of blanket-skipping checks, and keep a short list of documented skips for accepted risks.

## The query
```text
how to scan Terraform for misconfigurations with checkov
```

## Use this when
- you want to catch Terraform security misconfigurations before apply
- someone asks to "run checkov" or "scan my terraform for security issues"
- you are adding IaC scanning to a CI pipeline
- you need to map a failing CKV check ID to the actual fix

## Not for this skill when
- you are scanning container images or application source code (different scanners)
- Terraform itself wont parse (fix the HCL syntax first)
- your IaC is CloudFormation or Pulumi only (see the variants below)
- you want runtime monitoring of already-deployed infrastructure

## Steps
1. Install Checkov with pip: run `pip install checkov` then `checkov --version`.
   Expected output: a version string like 3.2.x, confirming the CLI works.
2. Scan the Terraform directory: run `checkov -d .` from the repo root.
   Expected output: a summary of passed, failed, and skipped checks, plus a table of each failure with check ID, file, and line number.
3. Read one failure end to end: note the check ID (for example CKV_AWS_19, S3 bucket encryption) and open the file and line it names.
   Expected output: you can point at the exact resource block that violates the policy.
4. Fix the resource block: add the missing setting, for example a `server_side_encryption_configuration` block on the S3 bucket, then rerun the scan.
   Expected output: the check moves from Failed to Passed on the rerun.
5. Gate CI: add a pipeline step running `checkov -d . --hard-fail-on CKV_AWS_19` for your must-pass checks (or `--soft-fail` while rolling out).
   Expected output: the pipeline step fails when a listed check fails, blocking the merge.
6. Skip deliberately: add a comment like `#checkov:skip=CKV_AWS_21` with a written reason above the resource when a finding is a false positive or accepted risk.
   Expected output: the check appears under Skipped with your reason visible in the report.

### Variant: scan the plan instead of the HCL
Run `terraform plan -out planfile`, convert it with `terraform show -json planfile`, and save that JSON to plan.json. Then run `checkov -f plan.json`. This scans exactly what apply would create, which catches values that only resolve at plan time.

### Variant: checkov on CloudFormation
Point checkov at the template file: `checkov -f template.yaml`. The check IDs are still CKV_AWS style, so the fix workflow is the same.

### Variant: run only the checks you care about
`checkov -d . --check CKV_AWS_19,CKV_AWS_21` runs just those two. Handy when a PR touches S3 and you want a focused answer.

## Why this happens
Terraform applies whatever you declare, and the provider defaults lean permissive: buckets without encryption, disks without encryption, security groups you forgot to tighten. Checkov encodes CIS benchmarks and cloud best practices as policy checks over the HCL graph, so the review happens before the resource exists.

## Edge cases and pitfalls
- Checkov reads config files, not live state. Drift in the real account will not show up here.
- Remote modules get scanned too. Pin module versions so results do not change under you.
- A skip without a reason comment is tech debt. Make the justification mandatory in review.
- If the built-ins miss an org-specific rule, drop custom policies in a directory and pass `--external-checks-dir` with its path.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_Dqf95gky-8KuYNm3NffGPw
