Redact before an external surface¶
Any free-form string that leaves the process — a telemetry event, a log
line shipped to a third-party sink, an error message attached to a crash
report — may have had a secret interpolated into it somewhere upstream.
Route it through rtb_redact::string at the boundary:
use rtb_redact::string;
fn emit(event_args: &str) {
let safe = string(event_args);
external_sink.send(&safe);
}
string returns Cow::Borrowed when nothing matched, so the common
clean-string case costs no allocation. For hot paths that reuse a
buffer, string_into appends into a caller-supplied String.
Headers¶
At DEBUG/TRACE, HTTP headers get logged. Check names against the
SENSITIVE_HEADERS set and redact values before they hit the log:
use rtb_redact::{is_sensitive_header, redact_header_value};
for (name, value) in headers {
let shown = if is_sensitive_header(name) {
redact_header_value(value)
} else {
value.into()
};
tracing::debug!(header = name, value = %shown);
}
What not to do¶
- Don't redact typed secrets with this crate — those belong in
secrecy::SecretString, which prevents them being formatted at all.rtb-redactis the safety net for strings already assembled. - Don't build your own per-call-site regex list. The whole point is one hardened, tested, conservatively-ordered rule set (see the toolkit's security stance on centralising foot-guns).