Skip to content

Keep secrets out of plan notes and logs

llms.txtlists every page for an agent
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`.

A secret the plan and apply jobs read by name, whose value never appears in anything terragucci writes or logs.

  1. 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).

  2. Mark the variable sensitive in the root:

    variable "db_password" {
    type = string
    sensitive = true
    }
  3. Name the secret in terragucci.yml. The pipeline holds the name, never the value:

    pass:
    secrets: [TF_VAR_db_password]

    config check refuses a value written in place of a name. On GitLab every job reads the CI/CD variables already, so the key changes nothing there.

  4. Check the file and write the pipeline again:

    Terminal window
    npx terragucci config check
    npx terragucci init

    Each 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.

  5. Open a pull request. When the plan held a sensitive value, the note says so:

    Sensitive values are redacted in the stored plans (2).

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).

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

terragucci

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.