Audits Terraform code for anti-patterns, security issues, and best practice violations. Use when asked to audit, review, or check terraform code quality...
Enforce Terraform code quality and security standards across the terraform/ directory through automated checks.
What it checks (9 checks):
Full audit (all checks):
node .claude/skills/terraform-audit/scripts/run_all_checks.mjs
Generate report (all checks + markdown report):
node .claude/skills/terraform-audit/scripts/generate_report.mjs
Report saved to: reports/YYYY-MM-DD/terraform-audit.md
Individual checks:
node .claude/skills/terraform-audit/scripts/check_hardcoded_secrets.mjs
node .claude/skills/terraform-audit/scripts/check_security_issues.mjs
node .claude/skills/terraform-audit/scripts/check_missing_versions.mjs
node .claude/skills/terraform-audit/scripts/check_resource_lifecycle.mjs
node .claude/skills/terraform-audit/scripts/check_deprecated_syntax.mjs
node .claude/skills/terraform-audit/scripts/check_module_structure.mjs
node .claude/skills/terraform-audit/scripts/check_dependency_issues.mjs
node .claude/skills/terraform-audit/scripts/check_missing_descriptions.mjs
node .claude/skills/terraform-audit/scripts/check_naming_conventions.mjs
RULE: Never hardcode sensitive values. Exposed secrets = compromised infrastructure.
Violations:
password = "mysecretpassword"api_key = "sk-1234567890"access_key = "AKIA..."github_token = "ghp_..."_pat, _token, _secret, _key with literal valueFix: Use var.password, random_password.db.result, or secrets manager.
RULE: Follow least-privilege principle. Over-permissive = security breach waiting to happen.
Violations:
"Action": "*" or "Resource": "*" in IAM policiesverbs = ["*"], resources = ["*"], api_groups = ["*"] in K8s RBACcidr_blocks = ["0.0.0.0/0"] - open to internetencrypted = false - unencrypted data at restpublicly_accessible = true - database exposedprivileged = true - container running as rootskip_final_snapshot = true - data loss on deletedeletion_protection = false - accidental deletion riskFix: Use specific permissions, restrict CIDR blocks, enable encryption, protect resources.
RULE: Pin versions for reproducibility. Unpinned = CI/CD failures + breaking changes in production.
Violations:
required_providersversion?ref= or ?tag=required_version for Terraform itselfFix: Add version = "~> 2.0" to providers and modules.
RULE: Protect critical resources. No protection = data loss + downtime.
Violations:
lifecycle { prevent_destroy = true }timeout (infinite hang possible)deletion_protection = trueskip_final_snapshot = trueFix: Add lifecycle blocks and deletion protection to critical resources.
RULE: Use modern Terraform syntax. Deprecated syntax = upgrade blockers + state corruption risk.
Violations:
"${var.name}" instead of var.name (unnecessary interpolation)list("a", "b") instead of ["a", "b"] (deprecated function)map("key", "value") instead of { key = "value" } (deprecated function)count = length(var.x) instead of for_each (index-based state = corruption risk)element(list, count.index) instead of list[count.index]terraform.workspace usage (anti-pattern)Fix: Update to modern HCL syntax before Terraform upgrades.
RULE: Follow standard module structure for maintainability.
Required files:
variables.tf, outputs.tf, versions.tf, README.mdViolations:
Fix: Add missing files, configure backend, refactor large modules.
RULE: Use implicit dependencies. Explicit depends_on = maintenance nightmare.
Violations:
5
depends_onin one file (over-reliance)
depends_on with data sources (usually unnecessary)null_resource provisioner without depends_on or triggersFix: Use resource references for implicit dependencies.
RULE: Document all variables and outputs for usability.
Violations:
variable "name" { type = string } (no description)output "id" { value = ... } (no description)Fix: Add description = "..." to all variables and outputs.
RULE: Use snake_case everywhere for consistency.
Violations:
myResourceNamemy-resource-nameFix: Rename to my_resource_name.