· PathShield Team · Tutorials · 5 min read
How to Scan Terraform Code for Security Issues (Tools & Techniques)
Discover the best Terraform security scanning tools and learn how to integrate them into your CI/CD pipeline to catch misconfigurations before deployment.
How to Scan Terraform Code for Security Issues (Tools & Techniques)
Infrastructure as Code (IaC) has revolutionized cloud deployments, but with great power comes great responsibility. A single misconfiguration in your Terraform code can expose your entire infrastructure to security risks. This guide explores the best tools and techniques for scanning Terraform code to catch security issues before they reach production.
Why Terraform Security Scanning Matters
Terraform misconfigurations account for a significant portion of cloud security incidents. Common issues include:
- Open security groups allowing unrestricted access
- Unencrypted storage buckets and databases
- Overly permissive IAM policies
- Missing logging and monitoring configurations
- Exposed secrets and hardcoded credentials
The good news? Most of these issues can be caught automatically before deployment.
Top Terraform Security Scanning Tools
1. Checkov - The Comprehensive Scanner
Checkov is an open-source static analysis tool that scans Terraform (and other IaC) for security and compliance misconfigurations.
Installation:
pip install checkov
Basic Usage:
checkov -d . --framework terraform
Key Features:
- 1000+ built-in policies
- Custom policy support
- Multiple output formats
- IDE integrations
Example Output:
Check: CKV_AWS_23: "Ensure every security group rule has a description"
FAILED for resource: aws_security_group.web
File: /main.tf:15-25
Guide: https://docs.bridgecrew.io/docs/networking_31
2. tfsec - Purpose-Built for Terraform
tfsec focuses specifically on Terraform security scanning with deep AWS, Azure, and GCP knowledge.
Installation:
brew install tfsec
# or
go install github.com/aquasecurity/tfsec/cmd/tfsec@latest
CI/CD Integration Example:
name: tfsec
on: [push, pull_request]
jobs:
tfsec:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: aquasecurity/tfsec-action@v1.0.0
with:
format: sarif
out: tfsec.sarif
- uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: tfsec.sarif
Custom Rules Example:
# .tfsec/custom_rule.yaml
rules:
- code: CUSTOM-001
description: S3 buckets must have specific tags
severity: HIGH
requiredTypes:
- resource
requiredLabels:
- aws_s3_bucket
matchSpec:
name: tags
action: contains
value: Environment
3. Terrascan - Policy as Code Engine
Terrascan uses Open Policy Agent (OPA) for highly customizable security policies.
Installation:
curl -L "$(curl -s https://api.github.com/repos/tenable/terrascan/releases/latest | grep -o -E "https://.+?_Darwin_x86_64.tar.gz")" > terrascan.tar.gz
tar -xf terrascan.tar.gz terrascan && rm terrascan.tar.gz
sudo mv terrascan /usr/local/bin
Scanning with Policy Filters:
terrascan scan -t aws -i terraform --severity high,critical
4. Snyk Infrastructure as Code
Snyk IaC combines security scanning with remediation guidance and developer-friendly integrations.
CLI Usage:
snyk iac test main.tf
Fixing Issues:
# Get remediation advice
snyk iac test main.tf --json | jq '.infrastructureAsCodeIssues[0].remediation'
5. KICS (Keeping Infrastructure as Code Secure)
KICS supports multiple IaC languages and provides extensive query libraries.
Docker Usage:
docker run -v "$(pwd)":/path checkmarx/kics:latest scan -p /path -o /path/results
Integrating Security Scans into Your Workflow
Pre-Commit Hooks
Catch issues before they’re even committed:
# .pre-commit-config.yaml
repos:
- repo: https://github.com/antonbabenko/pre-commit-terraform
rev: v1.77.0
hooks:
- id: terraform_tfsec
- id: terraform_checkov
args:
- --args=--quiet --compact --framework terraform
CI/CD Pipeline Integration
Example GitLab CI:
terraform-security:
stage: test
image: python:3.9
script:
- pip install checkov
- checkov -d . --output-format json --output-file checkov-report.json
artifacts:
reports:
junit: checkov-report.json
only:
changes:
- "**/*.tf"
VS Code Integration
Install extensions for real-time feedback:
- Checkov extension
- tfsec extension
- Terraform extension with security linting
Common Security Issues and How to Fix Them
1. Unencrypted S3 Buckets
Vulnerable Code:
resource "aws_s3_bucket" "data" {
bucket = "my-data-bucket"
}
Secure Version:
resource "aws_s3_bucket" "data" {
bucket = "my-data-bucket"
}
resource "aws_s3_bucket_server_side_encryption_configuration" "data" {
bucket = aws_s3_bucket.data.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
resource "aws_s3_bucket_public_access_block" "data" {
bucket = aws_s3_bucket.data.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
2. Open Security Groups
Vulnerable Code:
resource "aws_security_group" "web" {
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
Secure Version:
resource "aws_security_group" "web" {
ingress {
description = "SSH from corporate VPN"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = [var.corporate_vpn_cidr]
}
}
3. Hardcoded Secrets
Vulnerable Code:
resource "aws_db_instance" "database" {
password = "SuperSecret123!" # Never do this!
}
Secure Version:
resource "random_password" "db_password" {
length = 32
special = true
}
resource "aws_secretsmanager_secret" "db_password" {
name = "rds-password"
}
resource "aws_secretsmanager_secret_version" "db_password" {
secret_id = aws_secretsmanager_secret.db_password.id
secret_string = random_password.db_password.result
}
resource "aws_db_instance" "database" {
password = random_password.db_password.result
}
Building a Security-First Terraform Culture
1. Establish Baseline Policies
Create a minimum security standard for your organization:
# modules/security-baseline/main.tf
resource "aws_ebs_encryption_by_default" "main" {
enabled = true
}
resource "aws_s3_account_public_access_block" "main" {
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
2. Use Terraform Modules for Security
Create reusable, pre-secured modules:
module "secure_vpc" {
source = "./modules/secure-vpc"
enable_flow_logs = true
enable_guardduty = true
enable_vpc_endpoints = true
}
3. Regular Security Reviews
Schedule monthly reviews of:
- Failed security scans
- Policy violations
- New security rules needed
- Module updates
Advanced Scanning Techniques
Custom Policy Development
Create organization-specific rules:
# custom_checkov_check.py
from checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck
from checkov.common.models.enums import CheckResult, CheckCategories
class S3BucketMustHaveLifecycle(BaseResourceCheck):
def __init__(self):
name = "Ensure S3 buckets have lifecycle policies"
id = "CUSTOM_AWS_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):
if 'lifecycle_rule' in conf:
return CheckResult.PASSED
return CheckResult.FAILED
check = S3BucketMustHaveLifecycle()
Combining Multiple Scanners
Use a meta-scanner approach:
#!/bin/bash
# security-scan.sh
echo "Running Terraform security scans..."
# Run multiple scanners
tfsec . --format json > tfsec-results.json
checkov -d . --output json > checkov-results.json
terrascan scan -i terraform --format json > terrascan-results.json
# Aggregate results
python aggregate_results.py
# Fail if any critical issues
if [ -f "critical-issues.txt" ]; then
echo "Critical security issues found!"
exit 1
fi
Measuring and Improving Security Posture
Key Metrics to Track
- Number of security issues per deployment
- Time to remediation
- Policy compliance percentage
- False positive rate
Continuous Improvement Process
- Baseline: Establish current security posture
- Target: Set improvement goals
- Implement: Add scanning tools and policies
- Measure: Track metrics over time
- Iterate: Refine rules and processes
Conclusion
Terraform security scanning is not optional—it’s essential for maintaining secure cloud infrastructure. Start with one tool, integrate it into your workflow, and gradually expand your security coverage. Remember: the best security issue is the one that never makes it to production.
Action Items:
- Install at least one scanning tool today
- Run it against your existing Terraform code
- Fix the top 5 critical issues found
- Set up pre-commit hooks or CI/CD integration
By making security scanning a natural part of your Terraform workflow, you’ll sleep better knowing your infrastructure is secure by design.