Threat model¶
The problem. Credentials leak into observability data by accident, and the moment that data reaches a third party it is outside your control. This page explains the leak, the trust boundary, and why in-process redaction is the right defence.
How credentials leak¶
Nobody writes log.Println(apiKey). Secrets escape by accident, riding along
inside strings that were never meant to carry them:
- Error messages. An HTTP client fails and wraps the URL it dialled —
including any
user:pass@userinfo. A config loader rejects a token and quotes it back at you. An OTLP export fails and the error embeds theAuthorizationheader it sent. - Command arguments. A flag like
--api-key=sk-abc123lands inos.Args, and any code that logs the invocation for diagnostics ships the key with it. - HTTP headers. Request and response dumps carry
Authorization,Cookie, andX-*-Tokenvalues verbatim.
Each of these is a free-form string that happens to contain a credential. The code producing it is not the code that leaks it — the leak happens later, when something logs, traces, or reports that string.
The trust boundary¶
The danger is not that the string exists in memory. It is that the string crosses a boundary into a surface you no longer control:
your process │ third-party ingest
(trusted) │ (untrusted)
│
error string ────────────┼──▶ telemetry vendor
log field ───────────────┼──▶ log aggregator
header dump ─────────────┼──▶ crash / error tracker
│
the boundary
On the far side of that line, a leaked credential is replicated, indexed, and retained — potentially for far longer than you intended, across systems you cannot audit or purge. A secret that reaches a log aggregator is, for practical purposes, a secret you must now rotate. The blast radius is defined by where the data goes, not by where it originated.
Inside the boundary — host-only debug logs that never leave the machine — the same string is not a problem. Those logs are within your trust boundary and may genuinely need the raw content to be useful.
Why redact at the boundary¶
Given that the leak happens at the crossing, that is where the defence belongs.
Redacting at the boundary means running untrusted strings through
String in-process, immediately before they are
shipped.
This beats the alternatives:
- Redacting at every call site is unenforceable — there are hundreds of places a string might be logged, and the one you forget is the one that leaks.
- Trusting the third party to redact hands your secret across the boundary first and hopes; the credential is already outside your control.
- Redacting at the boundary is a single, auditable choke point. Wire it into the exporter, the shipped-log handler, and the header dumper, and every string is sanitised on the way out whether or not the caller remembered.
Because String is idempotent, redacting defensively at the boundary never
double-mangles a string that was already cleaned upstream — so the boundary can
be a blanket safety net without coordination.
What redaction is — and is not¶
Redaction here means masking known credential shapes while preserving the
surrounding structure, so a redacted error is still useful for debugging:
https://<redacted>@host/path tells you the request target even though the
userinfo is gone.
It is emphatically not a guarantee of secrecy. A pattern catalogue can only match shapes it knows. This module deliberately trades a little recall for a very low false-positive rate (see the rule catalogue), so a credential in a bespoke, non-standard format will pass straight through.
That is why boundary redaction is the last line of defence, not the only one. Where you know a string carries a secret in a format the catalogue does not recognise, strip it at the source too — pass an identifier instead of the token, and never construct a shipped string out of a raw secret you already hold. The boundary catches the accidents you did not anticipate; upstream discipline handles the ones you can.
Related¶
- Redact at the boundary — apply the discipline in code.
- The rule catalogue & its limits — the exact shapes matched, and the recall tradeoffs behind them.