The state file
Terraform state records the values of the resources it manages, and that includes sensitive ones. RDS passwords, generated keys, secret values. Stored in plaintext regardless of whether the variable was marked sensitive.
Marking a variable sensitive = true hides it from plan output. It does not encrypt it in state.
So: remote backend with encryption at rest and access control, state locking to prevent concurrent writes, and *.tfstate in .gitignore. If state has ever been committed, treat every secret in it as compromised and rotate.
Credentials in configuration
Hardcoded access keys in .tf files get committed. Reference secret managers or use provider credential chains instead of embedding values.
Same for .tfvars, those get committed constantly. Keep them out of version control and template an example version instead.
Insecure configuration
The other half. Terraform will happily create infrastructure that's wide open, and the mistakes are consistent:
Security groups with
0.0.0.0/0on anything that isn't a load balancerIAM policies with
Action = "*"andResource = "*"S3 buckets without public access blocks
Unencrypted volumes, databases and queues
Databases with
publicly_accessible = trueNo logging or flow logs
tfsec, checkov and terrascan all catch these. Run one in CI on every pull request. They're free, fast, and this is a class of problem where pattern matching works well. The vulnerable configuration has a recognisable shape.
Review the plan, not just the code
terraform plan output shows what will actually change, including things a module chose on your behalf. In CI, post the plan to the pull request and require approval before apply.
Pin module and provider versions. A module pulled from a registry at a floating version can change what it creates between runs.
Drift
Infrastructure changed by hand in the console won't appear in your code, and the next apply may revert it, or preserve a manual change nobody reviewed. Run drift detection on a schedule and treat console access to production as an exception rather than a habit.