Install any skill in seconds. Free to start, no credit card required.
Get Started Free →This skill covers implementing automated security scanning for Infrastructure as Code (IaC) templates using tools like Checkov, tfsec, and KICS. It addresses detecting misconfigurations in Terraform, CloudFormation, Kubernetes manifests, and Helm charts before deployment, establishing policy-based governance, and integrating IaC scanning into CI/CD pipelines to prevent insecure cloud resource provisioning.
.claude/skills/implementing-infrastructure-as-code-security-scanning/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-04 | ✗→✓ | ▲ Improved | — | — |
| case-11 | ✗→✓ | ▲ Improved | — | — |
| case-06 | ✗→✓ | ▲ Improved | — | — |
| case-18 | ✗→✓ | ▲ Improved | — | — |
| case-05 | ✗→✓ | ▲ Improved | — | — |
Do not use for scanning application source code (use SAST), for monitoring already-deployed infrastructure drift (use cloud security posture management tools), or for container image vulnerability scanning (use Trivy).
pip install checkov) or tfsec installedbash# Scan all Terraform files in a directory checkov -d ./terraform/ --framework terraform --output cli --output json --output-file-path ./results # Scan specific file checkov -f main.tf --output json # Scan Terraform plan (more accurate for dynamic values) terraform init && terraform plan -out=tfplan terraform show -json tfplan > tfplan.json checkov -f tfplan.json --framework terraform_plan # Scan with specific checks only checkov -d ./terraform/ --check CKV_AWS_18,CKV_AWS_19,CKV_AWS_20 # Skip specific checks checkov -d ./terraform/ --skip-check CKV_AWS_145,CKV2_AWS_6
yaml# .github/workflows/iac-security.yml name: IaC Security Scan on: pull_request: paths: - 'terraform/**' - 'cloudformation/**' - 'k8s/**' jobs: checkov: name: Checkov IaC Scan runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Run Checkov uses: bridgecrewio/checkov-action@v12 with: directory: terraform/ framework: terraform output_format: cli,sarif output_file_path: console,checkov.sarif soft_fail: false skip_check: CKV_AWS_145 - name: Upload SARIF if: always() uses: github/codeql-action/upload-sarif@v3 with: sarif_file: checkov.sarif category: checkov-iac tfsec: name: tfsec Scan runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Run tfsec uses: aquasecurity/tfsec-action@v1.0.3 with: working_directory: terraform/ sarif_file: tfsec.sarif soft_fail: false - name: Upload SARIF if: always() uses: github/codeql-action/upload-sarif@v3 with: sarif_file: tfsec.sarif category: tfsec
python# custom_checks/s3_versioning.py from checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck from checkov.common.models.enums import CheckResult, CheckCategories class S3BucketVersioning(BaseResourceCheck): def __init__(self): name = "Ensure S3 bucket has versioning enabled" id = "CKV_CUSTOM_1" supported_resources = ["aws_s3_bucket"] categories = [CheckCategories.GENERAL_SECURITY] super().__init__(name=name, id=id, categories=categories, supported_resources=supported_resources) def scan_resource_conf(self, conf): versioning = conf.get("versioning", [{}]) if isinstance(versioning, list) and len(versioning) > 0: if versioning[0].get("enabled", [False])[0]: return CheckResult.PASSED return CheckResult.FAILED check = S3BucketVersioning()
yaml# .checkov.yaml branch: main compact: true directory: - terraform/ - cloudformation/ framework: - terraform - cloudformation - kubernetes output: - cli - sarif skip-check: - CKV_AWS_145 # S3 default encryption with CMK (using SSE-S3 is acceptable) - CKV2_AWS_6 # S3 bucket request logging (handled at CloudTrail level) soft-fail: false
bash# Scan Kubernetes manifests checkov -d ./k8s/ --framework kubernetes # Scan Helm charts (renders templates first) checkov -d ./charts/myapp/ --framework helm # Scan with KICS (Keeping Infrastructure as Code Secure) docker run -v $(pwd)/k8s:/path checkmarx/kics:latest scan \ --path /path \ --output-path /path/results \ --type Kubernetes \ --report-formats json,sarif
| Term | Definition | |------|------------| | IaC Scanning | Automated analysis of infrastructure code templates to detect security misconfigurations before deployment | | Policy as Code | Security policies defined as executable code that can be version-controlled, tested, and enforced automatically | | CKV Check ID | Checkov's unique identifier for each security check (e.g., CKV_AWS_18 for S3 public access) | | Terraform Plan Scanning | Scanning the resolved Terraform plan JSON which includes computed values and module expansions | | Graph-based Scanning | Checkov's ability to analyze relationships between resources, not just individual resource configs | | Drift Detection | Identifying differences between IaC definitions and actual deployed infrastructure state | | Custom Policy | Organization-specific security checks authored in Python or YAML to enforce internal standards |
Context: A development team repeatedly creates S3 buckets without proper access controls. A recent incident exposed customer data through a public bucket.
Approach:
aws_s3_bucket_public_access_block resource for every S3 bucketsoft_fail: false to block PR merges when S3 security checks failPitfalls: Scanning only .tf files misses dynamically computed values. Use Terraform plan scanning for higher accuracy. Checkov's resource-relationship checks (CKV2 prefix) require graph analysis mode.
IaC Security Scan Report
==========================
Framework: Terraform
Directory: terraform/
Scan Date: 2026-02-23
Checkov Results:
Passed: 187
Failed: 12
Skipped: 3
Unknown: 0
FAILED CHECKS:
CKV_AWS_18 [HIGH] S3 Bucket has public read ACL
Resource: aws_s3_bucket.data_lake
File: terraform/storage.tf:15-28
CKV_AWS_24 [HIGH] CloudWatch log group not encrypted
Resource: aws_cloudwatch_log_group.app
File: terraform/monitoring.tf:3-8
CKV_AWS_79 [MEDIUM] Instance metadata service v1 enabled
Resource: aws_instance.web
File: terraform/compute.tf:12-30
QUALITY GATE: FAILED (2 HIGH severity findings)| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-04 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-11 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-06 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-20 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-18 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-19 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-21 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-22 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-08 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-17 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-05 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-09 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-15 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-01 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-13 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-16 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-03 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-10 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-12 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-02 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-07 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-14 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +50 percentage points is the difference between those two pass rates over the 22 comparable cases.
The per-case answers from this run were removed by the retention sweep, so the case table below shows the verdicts without the text either arm produced. The counts above were recorded at the time and are unaffected. Answers are now kept for 180 days.
Other measured skills in the registry, with their headline benchmark lift.