← Back to Terraform Plan Secret Exposure Check
The free way to look for a leaked secret in a Terraform plan is to open the structured JSON from
terraform show -json and either read through it or grep it for known shapes --
grep -i akia plan.json, a search for BEGIN PRIVATE KEY, that kind of
thing. That catches the literal string every time it is genuinely there and costs nothing to try.
This checker runs the same pattern match -- an AWS access key, a PEM private key,
a JSON Web Token, or a URL with an embedded username and password -- but does one more thing first:
for every match, it walks the plan's own before_sensitive/after_sensitive
tree to the exact attribute path and checks whether Terraform's provider schema already marked that
value sensitive, including the case where a whole subtree collapsed to a single true
higher up. A value Terraform already redacts is skipped; a value the schema missed is reported. A
plain grep has no way to make that distinction -- it treats every match the same.
| What you are trying to do | Where to do it |
|---|---|
| Confirm a specific known string (a key you already suspect is in there) appears anywhere in the plan file. | A manual grep -- that is exactly what it is good at. |
| Know whether a matched value is a real leak or one Terraform's schema already marks sensitive and redacts everywhere else. | This checker -- it reads the sensitivity tree per attribute path before reporting anything, which a grep cannot do at all. |
| Catch a secret-shaped value nested several levels inside a resource block, next to fields that are correctly marked sensitive. | This checker -- it walks every attribute path recursively rather than relying on a reader to notice the one field that differs from its neighbors. |
| Check an output value, which carries one sensitive flag for the whole value instead of a per-path tree. | This checker -- it checks outputs with the correct, different rule automatically, instead of relying on a human to remember outputs work differently. |
| Gate a CI pipeline on this exact check with no install and no third-party upload. | This checker's CLI -- node cli.mjs check plan.json exits non-zero on a finding, same as a grep in a pipeline, but without the false confidence of an unfiltered match. |
| Try it for free with a tool you already have on every machine. | Manual grep -- no page load required, and it is a reasonable first pass before reaching for anything else. |
A grep is not wrong, it is incomplete: it answers "does this string appear" and has no way to answer "does it appear somewhere Terraform already told you not to worry about." Every real finding a grep turns up is also a hit this checker would report -- the difference is what happens to the hits a grep cannot rule out, which on a plan with dozens of correctly-redacted attributes is most of them.
grep -i akia plan.json good enough?It finds the same literal string this checker's aws-access-key-id pattern finds. What it cannot do is the next step: for every match, look up whether that exact attribute path is covered by the plan's before_sensitive or after_sensitive tree, which collapses to a bare true at whatever level everything under it is marked sensitive. A human re-deriving that by hand has to open the sensitive tree, walk it to the matching path, and check whether an ancestor already collapsed to true -- for every hit, in a plan that can have hundreds of resources. Grep has no way to do that lookup at all, so every real match reads the same as a value Terraform already redacts.
Two things this checker does that a read-through has no natural way to replicate. First, a nested block's secret-shaped field several levels deep, buried inside a resource that also has plenty of ordinary sensitive-marked fields nearby -- easy to assume the whole block is covered when only a sibling attribute actually is. Second, an output value: outputs carry a single sensitive flag for the whole value rather than a per-path tree, so a human has to remember that outputs are checked differently from resource attributes at all, not just check them the same way and get it wrong.
terraform show output before merging?The human-readable terraform plan output already redacts anything the schema marked sensitive, which is exactly the problem: a value the schema forgot to mark prints in plain sight next to a dozen values that are correctly redacted, with nothing visually distinguishing the leak from the routine. Reading top to bottom trains you to trust the formatting instead of checking it. This checker reads the structured JSON, where sensitivity is a fact you can look up per attribute rather than a formatting choice you have to notice was never applied.
There is nothing to upload either way. Reading the JSON by eye or grepping it locally involves no third party at all, and this checker runs entirely in your browser against the file you paste or load -- or, from the CLI, reads only a file already on your own disk. Neither path sends the plan anywhere.