Implementing Infrastructure as Code Security Scanning
When to Use
- When provisioning cloud infrastructure with Terraform, CloudFormation, or Pulumi and needing automated security validation
- When compliance frameworks require evidence of infrastructure configuration review before deployment
- When preventing common cloud misconfigurations like public S3 buckets, open security groups, or unencrypted storage
- When establishing guardrails that block insecure infrastructure changes in pull requests
- When managing multi-cloud environments requiring consistent security policies across AWS, Azure, and GCP
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).
Prerequisites
- Checkov v3.x installed (
pip install checkov) or tfsec installed - Terraform, CloudFormation, or Kubernetes IaC files in the repository
- CI/CD pipeline with access to IaC directories
- Bridgecrew API key (optional, for Checkov platform integration)
Workflow
Step 1: Run Checkov Against Terraform Files
# 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
Step 2: Integrate IaC Scanning into GitHub Actions
# .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
Step 3: Create Custom Checkov Policies
# 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()
Step 4: Configure Baseline and Suppressions
# .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
Step 5: Scan Kubernetes Manifests and Helm Charts
# 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
Key Concepts
| 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 |
Tools & Systems
- Checkov: Open-source IaC scanner by Bridgecrew with 2500+ built-in policies covering major cloud providers
- tfsec: Terraform-focused static analysis tool by Aqua Security with deep HCL understanding
- KICS: Open-source IaC scanner by Checkmarx supporting 15+ IaC frameworks
- Terrascan: IaC scanner with OPA Rego policy support for custom policy authoring
- Snyk IaC: Commercial IaC scanner integrated with the Snyk platform
Common Scenarios
Scenario: Preventing Public S3 Buckets in Terraform
Context: A development team repeatedly creates S3 buckets without proper access controls. A recent incident exposed customer data through a public bucket.
Approach:
- Enable Checkov in the CI/CD pipeline for all Terraform changes
- Enforce CKV_AWS_18 (no public read ACL), CKV_AWS_19 (encryption), CKV_AWS_20 (no public access block disabled)
- Create a custom policy requiring the
aws_s3_bucket_public_access_blockresource for every S3 bucket - Set
soft_fail: falseto block PR merges when S3 security checks fail - Provide Terraform modules with security defaults that teams can reuse
Pitfalls: 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.
Output Format
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)
Verification Criteria
Confirm successful execution by validating:
- [ ] All prerequisite tools and access requirements are satisfied
- [ ] Each workflow step completed without errors
- [ ] Output matches expected format and contains expected data
- [ ] No security warnings or misconfigurations detected
- [ ] Results are documented and evidence is preserved for audit
Compliance Framework Mapping
This skill supports compliance evidence collection across multiple frameworks:
- SOC 2: CC8.1 (Change Management), CC6.1 (Logical Access)
- ISO 27001: A.14.2 (Secure Development), A.12.1 (Operational Procedures)
- NIST 800-53: SA-11 (Developer Testing), CM-3 (Configuration Change Control), SA-15 (Development Process)
- NIST CSF: PR.IP (Information Protection), PR.DS (Data Security)
Claw GRC Tip: When this skill is executed by a registered agent, compliance evidence is automatically captured and mapped to the relevant controls in your active frameworks.
Deploying This Skill with Claw GRC
Agent Execution
Register this skill with your Claw GRC agent for automated execution:
# Install via CLI
npx claw-grc skills add implementing-infrastructure-as-code-security-scanning
# Or load dynamically via MCP
grc.load_skill("implementing-infrastructure-as-code-security-scanning")
Audit Trail Integration
When executed through Claw GRC, every step of this skill generates tamper-evident audit records:
- SHA-256 chain hashing ensures no step can be modified after execution
- Evidence artifacts (configs, scan results, logs) are automatically attached to relevant controls
- Trust score impact — successful execution increases your agent's trust score
Continuous Compliance
Schedule this skill for recurring execution to maintain continuous compliance posture. Claw GRC monitors for drift and alerts when re-execution is needed.