Cloud misconfigurations were responsible for 15% of all initial attack vectors in data breaches last year. Not zero-days. Not sophisticated exploits. Misconfigurations. Public S3 buckets, overprivileged IAM roles, security groups that allow the entire internet to SSH in.
The infrastructure-as-code revolution was supposed to fix this — codify your infrastructure, review it like application code, catch mistakes in PRs. But terraform plan tells you what will change. It does not tell you if what you're deploying is secure.
I built CloudGuard to close that gap. 90 security patterns for Terraform and CloudFormation files. Here's what it checks and why.
1. Public S3 Buckets and Storage Access
# The pattern — public-read ACL with no block
resource "aws_s3_bucket" "assets" {
bucket = "company-assets"
acl = "public-read" # Anyone on the internet can read this
}
# The fix — block public access explicitly
resource "aws_s3_bucket" "assets" {
bucket = "company-assets"
}
resource "aws_s3_bucket_public_access_block" "assets" {
bucket = aws_s3_bucket.assets.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
Why it still happens: marketing wants a public assets bucket, someone copies a Terraform example that defaults to public, the bucket policy is complex and nobody reads it carefully.
CloudGuard rule S3-001 catches public-read ACL on buckets. S3-004 flags missing S3 Block Public Access configuration. S3-008 detects bucket policies allowing wildcard principals.
2. Wildcard IAM Policies
# The pattern — full admin access to everything
resource "aws_iam_policy" "admin" {
name = "ci-pipeline-policy"
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Action = "*" # Every AWS action
Resource = "*" # On every resource
}]
})
}
# The fix — scope to specific actions and resources
resource "aws_iam_policy" "ci_deploy" {
name = "ci-pipeline-policy"
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Action = ["s3:PutObject", "s3:GetObject"]
Resource = "arn:aws:s3:::my-deploy-bucket/*"
}]
})
}
"I'll scope it down later." You won't. Or: "It's just for the CI pipeline." Until the CI credentials leak.
CloudGuard rule IM-001 catches wildcard Action in IAM policies. IM-003 flags wildcard Resource. IM-007 detects IAM roles with wildcard trust policies.
3. Open Security Groups
# The pattern — SSH open to the entire internet
resource "aws_security_group" "web" {
name = "web-server"
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # The entire internet can SSH in
}
}
# The fix — restrict to specific CIDR blocks
resource "aws_security_group" "web" {
name = "web-server"
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["10.0.0.0/8"] # VPN/internal only
}
}
"I need to SSH in from home." Use a bastion host or AWS SSM Session Manager. Never expose SSH directly to the internet.
CloudGuard rule SG-001 catches security groups allowing 0.0.0.0/0 ingress. SG-004 flags database ports open to the internet.
4. Unencrypted Storage and Databases
# The pattern — RDS without encryption (Terraform default)
resource "aws_db_instance" "main" {
engine = "postgres"
instance_class = "db.t3.micro"
# storage_encrypted is false by default
}
# The fix — always encrypt
resource "aws_db_instance" "main" {
engine = "postgres"
instance_class = "db.t3.micro"
storage_encrypted = true
kms_key_id = aws_kms_key.rds.arn
}
Most Terraform resources don't enable encryption by default. If you don't explicitly set it, it's off. There's almost no performance penalty for encryption at rest.
CloudGuard rule EC-001 catches RDS without encryption at rest. EC-004 flags unencrypted EBS volumes. EC-012 detects missing KMS key rotation.
5. Missing Logging and Audit Trails
# What's missing — no CloudTrail, no VPC flow logs
# If you don't have these resources, you're flying blind
resource "aws_cloudtrail" "main" {
name = "main-trail"
s3_bucket_name = aws_s3_bucket.trail.id
include_global_service_events = true
is_multi_region_trail = true
enable_log_file_validation = true
}
resource "aws_flow_log" "vpc" {
vpc_id = aws_vpc.main.id
traffic_type = "ALL"
log_destination = aws_cloudwatch_log_group.flow.arn
}
CloudTrail is non-negotiable. Without it, you have no audit trail of who did what in your AWS account. VPC Flow Logs on production VPCs. S3 access logging on buckets with sensitive data.
CloudGuard rule LG-001 catches missing CloudTrail configuration. LG-004 flags VPCs without flow logs. LG-007 detects S3 buckets without access logging.
6. Compliance Mapping
Every CloudGuard finding is tagged with relevant compliance framework sections:
| Finding | SOC2 | HIPAA | PCI-DSS |
|---|---|---|---|
| Public S3 bucket | CC6.1 | 164.312(a)(1) | Req 7 |
| Wildcard IAM | CC6.3 | 164.312(a)(1) | Req 7.1 |
| Open security group | CC6.6 | 164.312(e)(1) | Req 1.2 |
| Unencrypted RDS | CC6.1 | 164.312(a)(2)(iv) | Req 3.4 |
| No CloudTrail | CC7.2 | 164.312(b) | Req 10.1 |
Run a scan, get a compliance report. No manual mapping required.
Run It On Your Infrastructure
clawhub install cloudguard
cloudguard scan infra/
Example output:
$ cloudguard scan infra/
[CRITICAL] S3-001 Bucket with public-read ACL — storage.tf:15
[CRITICAL] IM-003 IAM policy: Action * on Resource * — iam/admin-role.tf:22
[HIGH] SG-001 Security group allows 0.0.0.0/0 on port 22 — network/security.tf:34
[HIGH] EC-005 RDS without encryption at rest — database/main.tf:18
Score: 38/100 (Grade: F)
Most Terraform codebases I've scanned score below 50.
How It Compares to tfsec and checkov
Both are solid tools. CloudGuard differs in:
- Scoring — 0-100 grade per scan, not just pass/fail
- Compliance mapping — SOC2/HIPAA/PCI in the report
- Pre-commit hooks — bad IaC never merges (Pro tier)
- Ecosystem — part of 26 tools, same installer, same philosophy
If tfsec or checkov is working for your team, you probably don't need to switch. CloudGuard is for teams that want scoring + compliance mapping + the broader ecosystem.
Free to scan. Pro ($19/mo) adds pre-commit hooks + compliance reports. 100% local — your infrastructure code is literally a map of your cloud. It should never leave your machine.
Top comments (0)