Keep secrets out of plan notes and logs
Optional: hand this page to your coding agentThe steps work by hand too.Show the whole prompt
Read https://intentius.io/terragucci/guides/keep-secrets-out-of-notes/.
List each variable in this repo's roots that holds a secret and is not marked `sensitive = true`, and each secret a root reads that terragucci.yml does not name under `pass.secrets`.
Add the missing names and `sensitive = true`, run `npx terragucci config check --json` and `npx terragucci init`, and open a pull request. Print names only; never write a secret's value anywhere.
Never apply, approve (a pull request review or `terragucci approve`), override a policy denial (`terragucci override`), use `--mode apply`, or merge; never touch `.chant/allowed_signers` or `chant/lifecycle`.Result
Section titled “Result”A secret the plan and apply jobs read by name, whose value never appears in anything terragucci writes or logs.
-
Put the value in your forge’s secret store, named as the root reads it, such as
TF_VAR_db_password(on GitLab, a masked CI/CD variable). -
Mark the variable sensitive in the root:
variable "db_password" {type = stringsensitive = true} -
Name the secret in
terragucci.yml. The pipeline holds the name, never the value:pass:secrets: [TF_VAR_db_password]config checkrefuses a value written in place of a name. On GitLab every job reads the CI/CD variables already, so the key changes nothing there. -
Check the file and write the pipeline again:
Terminal window npx terragucci config checknpx terragucci initEach job that plans or applies gets the secret as an environment variable of that name; Secrets and variables you pass lists the jobs that get none.
-
Open a pull request. When the plan held a sensitive value, the note says so:
Sensitive values are redacted in the stored plans (2).
Redaction
Section titled “Redaction”The binary’s show -json prints sensitive values in plain text. Each one is redacted before a plan is kept anywhere.
| Where | The value becomes |
|---|---|
plan.json and the report |
(sensitive, redacted by terragucci), wherever the value appears, also in an attribute the plan does not mark |
plan.txt and the plan note |
(sensitive value), as the binary prints it, wherever the value appears |
| a policy denial or warning | redacted before it reaches the report, the note or the log |
| a write-only attribute | its version (*_wo_version); the value is never in the plan |
| an ephemeral value | not reported |
Plan digests are taken before redaction, so an approval binds the plan as planned. The policy engine reads the unredacted plan.
Forge tokens are removed from the environment the binary, Terragrunt and the policy engine start with (the list).
Limits
Section titled “Limits”| Case | What happens |
|---|---|
| a value not marked sensitive | it is in the plan, the note and the bucket like any other attribute; mark it, or keep the bucket private |
| a provider or a step that prints a value | it reaches the job log as printed |
| a passed secret in the plan job | the pull request’s code runs there with it, as with the providers’ credentials; a fork’s pull request gets no plan job |
| the state | holds every secret its resources hold; reports and the bucket keep version ids only, and terragucci state export writes a version only to the machine of the person who runs it |
- Sensitive values in the plan report.
- Threat model for what each job can reach.
These docs count page views and clicks with PostHog. They set no cookies, store nothing in your browser, and send nothing when your browser asks not to be tracked.