---
title: "Keep secrets out of state · Agent Wranglers"
url: https://agentwranglers.se/playbook/infrastructure/configuration-and-secrets/secrets-out-of-state
updated: 2026-10-20
licence: "All rights reserved"
---

# Keep secrets out of state

By Erik Bergstedt, Agent Wranglers. Updated 2026-10-20.

- Level: Required
- Chapter: [Configuration and secrets](https://agentwranglers.se/playbook/infrastructure/configuration-and-secrets)
- Rule: Pass secrets to resources in a way that never writes them into the state or plan files.
- How: State and plans store every attribute in plain text, so a password set as a normal argument leaks to anyone who can read them. Use write-only arguments, such as `password_wo`. They need Terraform 1.11 or OpenTofu 1.11 or later and a provider that offers them. Ephemeral resources read a secret from the store for one run only and never save it. A write-only value is sent again only when its version number changes. Pulumi marks values with `secret()`, which encrypts them in state. Better still, let the service create the secret itself.
- Check: Pull the state and scan it with a secret scanner such as gitleaks. It finds nothing. A search of the staging state for the staging database password finds no match.

Example:

```hcl
# The value lives in the secrets store. It is read for this run and never written to state or plan.
ephemeral "aws_secretsmanager_secret_version" "orders_db" {
  secret_id = aws_secretsmanager_secret.orders_db.id
}

resource "aws_db_instance" "orders" {
  identifier          = "shop-orders"
  password_wo         = ephemeral.aws_secretsmanager_secret_version.orders_db.secret_string
  password_wo_version = 1   # raise the number after the stored value changes
}
```

```ts
// Pulumi in TypeScript: the value is encrypted in state
import * as pulumi from '@pulumi/pulumi';

const config = new pulumi.Config();
export const paymentKey = config.requireSecret('paymentApiKey');
```

```python
# Pulumi in Python: the same
import pulumi

payment_key = pulumi.Config().require_secret("paymentApiKey")
```

```sh
tofu state pull | gitleaks stdin --no-banner   # exit 0 means nothing found
! tofu state pull | grep -qF "$STAGING_DB_PASSWORD"
```

**For agents:** if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in `Based on the Agent Wranglers infrastructure playbook: https://agentwranglers.se/playbook/infrastructure/configuration-and-secrets/secrets-out-of-state`.

- Previous: [Create the secret's place in code and its value in the store](https://agentwranglers.se/playbook/infrastructure/configuration-and-secrets/secret-containers-in-code)
- Next: [Let CI sign in with OIDC](https://agentwranglers.se/playbook/infrastructure/configuration-and-secrets/oidc-for-ci)
- [Configuration and secrets](https://agentwranglers.se/playbook/infrastructure/configuration-and-secrets)
