describe-secrets — audit a secrets file without reading it

/home/john/bin/describe-secrets (on PATH). Reports the structure of a YAML secrets file — what variables exist, how long each value is, what character classes it uses, whether any two share a value — while never printing, logging or returning a single secret. Written 2026-09-17 for ~/ansible/secrets.yml, but it works on any YAML mapping of names to values.

Why it exists

A secrets file is the one file you want to audit but must not open casually. Opening it puts the values into a terminal, a scrollback buffer, and — when an agent does the opening — a conversation transcript. That is exactly how three credentials came to be leaked on 2026-09-09 (see john/actions item 9). This tool lets the useful questions be answered without that risk: is anything still a placeholder, is any secret implausibly short, has the same password been pasted into two variables, does a value have trailing whitespace that will break an auth header.

Usage

describe-secrets ~/ansible/secrets.yml
describe-secrets --hide-names ~/ansible/secrets.yml   # shape only
describe-secrets --min-len 16 secrets.yml            # stricter length flag

Output is one line per leaf value: name, type, length, a duplicate-detection tag, and a character-class shape such as lower+upper+digit+punct [base64-ish]. Then a findings list.

The duplicate tag is HMAC with a random per-run salt — deliberately

Do not "simplify" this to a plain hash. A bare SHA-256 of a short or low-entropy secret is trivially brute-forced from a wordlist, so publishing one in a report would leak the value. The tag is HMAC-SHA256(random 32-byte salt, value) truncated to 8 hex characters, with a fresh salt generated on every run. Identical values therefore produce identical tags within one report — which is all that duplicate detection needs — while nothing in the output can be attacked, and two runs cannot be correlated against each other.

What it deliberately does disclose

How the no-leak property was verified

Not by inspection. A synthetic file was written with known values covering each case — a placeholder, a short password, a hex token, a duplicated pair, a value with trailing whitespace, an empty string, a nested key — then the tool was run and its output was grepped for every one of those values. All absent. Repeat that test if the output format is ever changed; a formatting change is exactly how a leak would be introduced.

What it found on first use (2026-09-17)

Conventions

Follows main-pattern (importable main(), no sys.exit inside it) and cli-options (argparse, so --help and unknown-option errors come free). Per documentation-in-notes the documentation is here rather than beside the code, and --help prints a pointer back to this note.

tags tools, security, secrets, ansible, README