whiteweb.security / guides / Terraform state exposed
terraform.tfstate Critical exposure ~8 min read

My Terraform state file got exposed. What should I do?

Terraform's state file is a JSON document that records the real-world state of every resource it manages — and it stores secrets in plain text. AWS access keys, RDS passwords, database connection strings, and private keys are all potentially present. This is a full infrastructure compromise until you rotate everything.

This is a cloud infrastructure compromise — act on the cloud side first.

Unlike other config file exposures, a Terraform state leak can give attackers complete access to your AWS, GCP, or Azure environment. Revoke cloud credentials in the cloud provider's console before you do anything else — speed matters here.

// the 60-second version

  • Revoke every AWS/GCP/Azure IAM key visible in the state file — right now.
  • Remove the state file from the web root and any public repository.
  • Review cloud audit logs (CloudTrail, GCP Audit Logs) for unauthorised API calls.
  • Migrate to encrypted remote state (S3 + DynamoDB or Terraform Cloud) permanently.

01Understand what Terraform state files contain

Terraform's terraform.tfstate is a JSON file that records the desired and actual state of every managed resource. The Terraform documentation explicitly warns that state can contain sensitive values. In practice, a state file may include:

  • AWS IAM access key IDs and secret access keys — if you provisioned IAM users with Terraform, their credentials appear in the state file in plain text.
  • RDS / database master passwords — the initial password for any managed database instance.
  • Private TLS certificate keys — if you provisioned TLS certificates or loaded them into ACM, the private key may be in state.
  • Service account keys — GCP service account JSON keys for any Google provider resources.
  • Variable values — if you passed secrets in via -var or .tfvars files, they appear in the state as resource attribute values.

AWS keys in a Terraform state file are particularly dangerous. A motivated attacker with valid AWS credentials can provision EC2 instances for cryptomining, exfiltrate data from S3, or create new IAM users with administrator access — all within seconds of obtaining the key.

02Remove the state file and rotate ALL cloud credentials immediately

First, remove the file from wherever it was exposed. Then go straight to the cloud console and revoke every key you can find in the state file:

extract secrets from a state file for reviewbash
# find all sensitive-looking values
cat terraform.tfstate | python3 -m json.tool | \
  grep -E "(secret|password|key|token|private)" -i -A1
deactivate an IAM access key immediatelyAWS CLI
# deactivate (not delete — preserve evidence) aws iam update-access-key \ --access-key-id AKIAIOSFODNN7EXAMPLE \ --status Inactive \ --user-name terraform-user # then create a replacement aws iam create-access-key --user-name terraform-user

After revoking, also rotate: RDS master passwords, any explicitly stored API keys, and TLS private keys. Update your Terraform variables with the new values and run terraform apply to push the changes.

03Review cloud audit logs for unauthorised activity

AWS CloudTrail records every API call made with your credentials. Search for calls made with the compromised keys during the exposure window:

query CloudTrail for activity from compromised keyAWS CLI
# look for events by the access key ID aws cloudtrail lookup-events \ --lookup-attributes AttributeKey=AccessKeyId,AttributeValue=AKIAIOSFODNN7EXAMPLE \ --start-time 2026-01-01T00:00:00Z \ --query 'Events[].{Time:EventTime,Event:EventName,User:Username}'

Look for: new IAM users or roles created, S3 bucket policy changes or downloads, EC2 instance launches (especially in unusual regions), Lambda function creations, or any other actions you didn't authorise. For GCP, check the GCP Audit Log in Cloud Logging. For Azure, use Activity Log and sign-in logs.

04Migrate to encrypted remote state

Local state files are inherently risky. The solution is remote state with encryption. The most common pattern for AWS is an S3 backend with server-side encryption and a DynamoDB table for state locking:

secure remote state backend configurationmain.tf
terraform { backend "s3" { bucket = "my-tf-state-bucket" key = "prod/terraform.tfstate" region = "eu-west-1" encrypt = true kms_key_id = "arn:aws:kms:…" dynamodb_table = "terraform-locks" } }

The S3 bucket should have: versioning enabled, public access blocked, access logging to a separate bucket, and a bucket policy that restricts access to specific IAM roles only. Terraform Cloud and HCP Terraform also provide managed remote state with encryption and access controls.

05Review your terraform.tfvars and variable files

The state file is often the worst offender, but variable files can compound the exposure. Review your repository for files that shouldn't be committed:

files that should never be committed.gitignore
# Terraform sensitive files *.tfstate *.tfstate.* *.tfvars .terraform/ terraform.tfplan

If any .tfvars files with production secrets have already been committed to git, use git filter-branch or BFG Repo Cleaner to purge them from history, rotate the exposed values, and force-push the cleaned history. Coordinate with your team — all contributors will need to re-clone.

If the exposed AWS keys had administrator or broad IAM permissions, a thorough forensic review of your cloud environment is warranted. An attacker may have created backdoor IAM users, roles, or access keys that survived your credential rotation. Audit all IAM users and roles for anything unfamiliar.

Was this guide useful?

These playbooks are free to read and share. If a heads-up ever saved you a bad week, you can say thanks — or jump into the other guides.