Detect risky cloud defaults in Terraform plans before they reach production.
Most cloud security scanners check what you wrote. DefaultRisk checks what you forgot to write — the omitted settings that silently inherit insecure provider defaults.
Cloud services ship with defaults optimised for ease of use, not security. When a team deploys an S3 bucket without configuring a public access block, encryption, or versioning, nothing in the Terraform code looks wrong. But the bucket is now publicly exposable, unencrypted, and unrecoverable on deletion.
Conventional linters catch explicit misconfigurations. DefaultRisk catches the invisible ones — security-relevant fields that were never set.
terraform show -json → Plan Loader → Rule Engine → Findings + Remediation
- Parse the Terraform plan JSON to extract resource configurations.
- Detect omissions by checking security-relevant fields against known provider defaults.
- Report findings with severity, risk explanation, evidence, and a Terraform code snippet to fix it.
No cloud API calls. No credentials required. Runs entirely on the plan file.
pip install -e .
# If you have a Terraform project:
terraform init
terraform plan -out tfplan
terraform show -json tfplan > tfplan.json
defaultrisk scan tfplan.json
# Or use the bundled examples directly:
defaultrisk scan examples/plans/insecure_s3.plan.jsonFound 4 risky default(s):
[HIGH] DR-S3-001: S3 public access block not configured
Resource : aws_s3_bucket.customer_uploads
Default : all four flags default to false (public access allowed)
Risk : Without an explicit public access block, the bucket can be made
publicly readable or writable through ACLs or bucket policies.
This is the number one cause of S3 data leaks.
Fix :
resource "aws_s3_bucket_public_access_block" "customer_uploads" {
bucket = aws_s3_bucket.customer_uploads.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
[HIGH] DR-S3-002: S3 server-side encryption not configured
...
[MEDIUM] DR-S3-003: S3 versioning not enabled
...
[MEDIUM] DR-S3-004: S3 access logging not configured
...
Summary: 2 high, 2 medium
# Human-readable (default)
defaultrisk scan plan.json
# JSON (for scripting)
defaultrisk scan plan.json --format json --out results.json
# SARIF (for GitHub code scanning)
defaultrisk scan plan.json --format sarif --out results.sarif| Code | Meaning |
|---|---|
0 |
No findings at or above the severity threshold |
1 |
One or more findings meet the threshold |
2 |
Input error (file not found, invalid JSON) |
The default threshold is high. Override with --severity-threshold:
defaultrisk scan plan.json --severity-threshold critical| Rule ID | Severity | What It Catches |
|---|---|---|
| DR-S3-001 | High | S3 public access block not configured |
| DR-S3-002 | High | S3 encryption not configured |
| DR-S3-003 | Medium | S3 versioning not enabled |
| DR-S3-004 | Medium | S3 access logging not configured |
| DR-SG-001 | Critical | SSH (22) open to 0.0.0.0/0 |
| DR-SG-002 | Critical | RDP (3389) open to 0.0.0.0/0 |
| DR-SG-003 | Critical | All ports open to 0.0.0.0/0 |
| DR-RDS-001 | Critical | RDS publicly accessible |
| DR-RDS-002 | High | RDS storage encryption off |
| DR-RDS-003 | Medium | RDS backup retention too short |
| DR-EBS-001 | High | EBS volume encryption off |
| DR-ECR-001 | Medium | ECR scan on push disabled |
| DR-ECR-002 | Low | ECR image tags mutable |
| DR-IAM-001 | Critical | IAM wildcard Action + Resource |
| DR-IAM-002 | High | iam:PassRole on * |
Full details with remediation guidance: docs/rules.md
- name: Scan Terraform plan
run: |
pip install defaultrisk
defaultrisk scan tfplan.json --format sarif --out results.sarif
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarifdefaultrisk scan tfplan.json --severity-threshold high
# exits 1 if any high/critical finding → fails the pipelinedefaultrisk/
src/defaultrisk/
cli.py # command-line interface
plan_loader.py # terraform plan JSON parser
report.py # console, JSON, SARIF formatters
rules/
aws_s3.py # S3 bucket defaults
aws_sg.py # security group rules
aws_rds.py # RDS defaults
aws_ebs.py # EBS encryption
aws_ecr.py # ECR repository defaults
aws_iam.py # IAM policy analysis
tests/
test_smoke.py # unit + integration tests
examples/
terraform/ # sample insecure configs
plans/ # pre-generated plan JSONs
expected/ # golden outputs for test comparison
docs/
architecture.md # how the tool works internally
rules.md # full rule reference
git clone https://github.com/yourname/defaultrisk.git
cd defaultrisk
pip install -e ".[dev]"
pytest -v- AWS only for now. Azure and GCP rules are planned.
- Static analysis only. This tool reads plan files — it does not connect to your cloud account or inspect live state.
- No cross-resource reasoning yet. Each resource is evaluated independently. A security group attached to a private-subnet-only instance is flagged the same as one on a public instance. Context-aware scoring (reachability analysis) is on the roadmap.
- Rule coverage is not exhaustive. We cover the most common and impactful defaults. Contributions for additional resource types are welcome.
- Azure resource rules (Storage Account, NSG, SQL Database)
- GCP resource rules (GCS, Firewall, Cloud SQL)
- Cross-resource reachability scoring
- Intent inference from naming/tagging patterns
- Terraform module-aware scanning
-
defaultrisk initto generate a baseline config - Plugin system for custom rules
MIT


