← All field notes
terraform cloudstate secretsfor developers

Terraform state is a secret store: when a stolen token reads everything

A stolen Terraform Cloud token reads plaintext secrets out of state and queues applies that rewrite infrastructure. The principal is the token, so you revoke, not chase a human.

A Terraform Cloud API token does not just describe infrastructure. It can read the secrets sitting in state and queue applies that change real infrastructure, which makes a stolen token both data theft and an integrity event.

How the attack works

The token authenticates from a source the org has never seen, over the API rather than the UI. It reads state versions and outputs across multiple workspaces, pulling database passwords and provider keys that live in plaintext state. Then it queues a run that applies, modifying security group and network rules to open access. A provider key read from state later authenticates straight to the cloud, confirming the secrets are in active use. The tell is a token from an unfamiliar source reading state across workspaces and applying with no commit or pull request behind the run. In ATT&CK terms this is T1552, Unsecured Credentials, with T1578, Modify Cloud Compute Infrastructure.

Why it works

State is treated as a config artifact, but it is a secret store and a change engine at once. A long-lived, broadly scoped token can read every secret in state and apply changes with no human in the path and no pull request review gating it.

How to fix it

The acting identity is a token, so revoke it. There is no engineer to suspend and no org password that invalidates a standalone token. Lock the affected workspaces, cancel queued runs, and because state was read, treat every secret in it as exposed and rotate it. The non-obvious move is that a read secret is exposed whether or not you confirm reuse. Long term, replace long-lived broad tokens with short-lived scoped ones, keep secrets out of state with dynamic provider credentials and a secrets manager, restrict who can apply, and require approved runs triggered from version control.

Practice it

We built this as a GraphLattice Range scenario so teams can rehearse the token theft, the state read, and the revoke-lock-rotate response.