Terraform
Protection patterns for Terraform operations including apply, state, and workspace commands
The terraform check group covers Terraform operations that can destroy infrastructure or modify state without review.
Terraform checks
Apply with auto-approve
| ID | terraform:apply_with_auto_approve |
| Severity | Critical |
| Alternative | terraform plan -out=plan.tfplan && terraform apply plan.tfplan -- review the plan first, then apply from the saved plan file |
The -auto-approve flag skips the interactive confirmation that Terraform normally requires. This is the most dangerous Terraform command because it applies changes without any review.
# Triggers
terraform apply -auto-approve
terraform apply -auto-approve -var="env=production"
Destroy with auto-approve
| ID | terraform:destroy_auto_approve |
| Severity | Critical |
| Alternative | terraform plan -destroy -- preview what would be destroyed first, then run terraform destroy with manual approval |
# Triggers
terraform destroy -auto-approve
terraform destroy -target=aws_instance.foo -auto-approve
# Does NOT trigger (requires manual confirmation)
terraform destroy
State move / replace-provider
| ID | terraform:state |
| Severity | High |
| Filter | NotContains -dry-run |
| Alternative | terraform state <cmd> -dry-run -- preview the state change before actually modifying state |
# Triggers
terraform state mv aws_instance.old aws_instance.new
terraform state replace-provider hashicorp/aws registry.example.com/aws
# Does NOT trigger
terraform state mv -dry-run aws_instance.old aws_instance.new
State remove
| ID | terraform:state_rm |
| Severity | High |
| Alternative | terraform state list -- list resources in state first to verify what you're removing |
# Triggers
terraform state rm aws_instance.foo
terraform state rm module.foo
# Does NOT trigger
terraform state list
terraform state show aws_instance.foo
Workspace delete with force
| ID | terraform:workspace_delete_with_force_flag |
| Severity | High |
# Triggers
terraform workspace delete -force staging
Workspace delete without lock
| ID | terraform:workspace_delete_without_lock |
| Severity | High |
# Triggers
terraform workspace delete -lock=false staging
Force unlock
| ID | terraform:force_unlock_with_force_flag |
| Severity | High |
Manually unlocking state without confirmation can lead to state corruption if another operation is in progress.
# Triggers
terraform force-unlock -force LOCK_ID
Summary table
| ID | Command | Severity | Filter | Alternative |
|---|---|---|---|---|
terraform:apply_with_auto_approve | terraform apply -auto-approve | Critical | -- | Plan + apply from plan file |
terraform:destroy_auto_approve | terraform destroy -auto-approve | Critical | -- | terraform plan -destroy |
terraform:state | terraform state mv/replace-provider | High | NotContains -dry-run | -dry-run flag |
terraform:state_rm | terraform state rm | High | -- | terraform state list |
terraform:workspace_delete_with_force_flag | terraform workspace delete -force | High | -- | -- |
terraform:workspace_delete_without_lock | terraform workspace delete -lock=false | High | -- | -- |
terraform:force_unlock_with_force_flag | terraform force-unlock -force | High | -- | -- |
Best practices with shellfirm
-
Never use
-auto-approvein interactive sessions. Useterraform plan -out=plan.tfplanfollowed byterraform apply plan.tfplan. shellfirm catches this at Critical severity. -
Always dry-run state modifications. The
NotContains -dry-runfilter meansterraform state mv -dry-runpasses through without a challenge, encouraging the safe workflow. -
Combine with team policies. In a
.shellfirm.yaml, you can denyterraform:apply_with_auto_approveoutright:
version: 1
deny:
- terraform:apply_with_auto_approve
This prevents anyone on the team from using -auto-approve in the project directory, regardless of their personal settings.