# Diagnosing secrets leaked into Terraform state and plan output
## Symptom
A secret (password, token, private key) appears in plaintext in the state file, in plan output, or in a CI log. It may have been there for a long time.
## Cause
A non-sensitive variable or output carried the value: variables default to non-sensitive, and any value flowing through them lands in state and plan logs in cleartext.
## Confirmation
1. `terraform state pull | grep -c` for the secret pattern (careful: this puts the secret in your shell history; use a script or pipe, not the literal secret on the command line).
2. Trace the flow: which variable, local, or output carried it? `terraform console` is not needed; the config shows the path.
3. Check exposure: who can read the state backend? Who can read CI logs containing plans? The blast radius is everyone with that access, for the whole time the secret was there.
## Fix
1. Rotate the secret first. It is compromised; scrubbing the file without rotation achieves nothing.
2. Mark the variable `sensitive = true` and the output `sensitive = true`. This redacts them from plan output and console.
3. For state history: backend versioning keeps old copies with the old secret. Rotate, then consider the old versions burned; you cannot unsee them, but rotation makes them useless.
4. OpenTofu users: enable state encryption so future state is encrypted client-side.
## Verification
1. New `terraform plan` output no longer shows the value (shows `(sensitive value)`).
2. `terraform state pull` on a fresh state still contains the value by design (Terraform needs it to manage the resource); the protection is access control plus rotation, not absence. Verify backend access is scoped to the operators who need it.
3. CI logs: confirm plan output is redacted in the log viewer, not just in your terminal.