Secrets and redaction
What Treeship hashes, what it scrubs, what it misses, and why the difference matters.
Receipts get published. So the question is not "does Treeship try to hide secrets" — it is which parts of a receipt are safe by construction, and which are safe only by best effort.
Two different mechanisms are at work, and conflating them is how a credential ends up in a signed artifact.
The guarantee: hashes
Everything load-bearing in a receipt is a digest, not content.
| field | what it holds |
|---|---|
args_hash | sha256 of the input |
output_hash | sha256 of the output |
readback | digest of an independent post-state read |
output_digest | sha256 of stdout + stderr |
env_allowlist_digest | digest over environment variable names, never values |
A hash proves a specific input produced a specific output without disclosing either. You can hand someone a chain proving forty tool calls ran in a given order with given outcomes and disclose nothing about the data they touched. If you later want to prove what one call did, you reveal that one input and let them recompute the digest.
This is the part that is safe by construction. A digest cannot leak what it never contained.
The courtesy: command scrubbing
treeship wrap also records a human-readable command string and an argv
vector, so a receipt is legible to a person. Those hold real text, so they run
through a redactor first.
The redactor is a pattern denylist. It splits on whitespace and replaces any
token containing a known secret-ish pattern (TOKEN=, --api-key=,
AWS_SECRET, and similar) with [REDACTED].
Denylists catch what they know about. Measured against the shipping binary:
| command | recorded as | caught |
|---|---|---|
--token=sk-SECRET | [REDACTED] | ✅ |
AWS_SECRET_ACCESS_KEY=sk-SECRET | [REDACTED] | ✅ |
--token sk-SECRET | --token sk-SECRET | ❌ |
-H 'Authorization: Bearer sk-SECRET' | Authorization: Bearer sk-SECRET | ❌ |
postgres://user:PASSWORD@host/db | postgres://user:PASSWORD@host/db | ❌ |
-p sk-SECRET | -p sk-SECRET | ❌ |
The pattern is consistent: secrets attached with = are caught; secrets
passed as a separate argument, inside a header string, or embedded in a URL are
not. The redactor sees --token and sk-SECRET as two unrelated words, and
nothing about the second one looks like a secret.
So: treat scrubbing as a seatbelt, not a vault.
What follows from that
Do not put secrets in argv. This is true regardless of Treeship — argv is
visible in ps output to every process on the machine, and shells record it in
history. Treeship makes an existing exposure durable and signed, which is worse,
but the exposure is not new. Use environment variables or a file.
Environment values are never recorded. env_allowlist_digest covers the
sorted names of a fixed set of behavior-affecting variables. The allowlist
deliberately excludes anything whose presence is itself sensitive (*_TOKEN,
*_KEY, AWS_*), because a digest that changes when a credential appears leaks
that a credential appeared.
Review before publishing. Publishing is explicit and never automatic. A
receipt sits locally until you push it, and treeship package inspect shows
exactly what a reader would see.
A receipt is a capability, not a publication. Receipt pages are excluded from search indexes, so a receipt is readable by whoever holds the URL and not discoverable without one. That limits blast radius; it does not undo a leak.
If a secret does land in a receipt
Rotate the credential. That is the whole answer.
Receipts are immutable and content-addressed by design — editing one to remove a secret would change its ID and break every chain link after it, which is exactly the property that makes them evidence. There is no scrub-in-place, and offering one would be worse than not: a record you can quietly edit is not a record.
If the receipt was published, assume it was read.
Where this is heading
The denylist should be wider, and per-field disclosure rules would beat one global scrubber. But the honest framing today is:
Hashes are the guarantee. Scrubbing is best-effort. Keep secrets out of argv and the guarantee is enough on its own.
Related
- What a receipt proves — and does not
- Effect receipts — hashed evidence in detail
- Artifacts — the signed object