Redact HTTP headers¶
Headers get logged at DEBUG and TRACE, and several of them carry a credential in
full. string will not save you here — it works on free-form text and has no
idea what a header name is. Redacting headers is an explicit, separate call.
Mask the values before logging a header map¶
Test the name, then mask the value:
use rtb_redact::{is_sensitive_header, redact_header_value};
fn log_headers<'a>(headers: impl Iterator<Item = (&'a str, &'a str)>) {
for (name, value) in headers {
let shown = if is_sensitive_header(name) {
redact_header_value(value)
} else {
value.to_string()
};
tracing::debug!(header = name, value = %shown);
}
}
is_sensitive_header is ASCII-case-insensitive, so Authorization,
AUTHORIZATION and authorization all match. redact_header_value returns
[redacted] for anything non-empty and an empty string for an empty value — it
never inspects the value, so nothing can leak through a partial match.
Which headers are covered¶
Ten names, listed in full in the
API reference:
authorization, proxy-authorization, cookie, set-cookie, x-api-key,
x-auth-token, x-amz-security-token, x-goog-api-key,
x-anthropic-api-key, x-openai-api-key.
Do not query the set directly — SENSITIVE_HEADERS.contains("Authorization") is
false, because every entry is stored lowercase and the underlying phf::Set
is case-sensitive. Go through is_sensitive_header.
Add the headers your service treats as secret¶
The set is fixed at compile time and cannot be extended. x-gitlab-token,
x-hub-signature, x-shopify-hmac-sha256 and every internal header your own
services mint are not in it.
Layer your own names on top:
use rtb_redact::is_sensitive_header;
const EXTRA_SENSITIVE: &[&str] = &["x-gitlab-token", "x-internal-session"];
fn sensitive(name: &str) -> bool {
is_sensitive_header(name)
|| EXTRA_SENSITIVE.iter().any(|h| h.eq_ignore_ascii_case(name))
}
Keep the local list in one place, next to the code that logs headers, rather than repeating it per call site. If the name is a widely-used one rather than something internal, it belongs in the crate — raise it on the project on GitLab.
Do not rely on string for a header line pasted into text¶
A header that arrives as part of an error message or a raw request dump is just text, and only the ordinary rules apply to it:
in : x-api-key: sk-abcdef1234567890abcdef out: x-api-key: [redacted]
in : Cookie: session=abc123; theme=dark out: unchanged
The first is redacted because the value matches the sk- prefix rule, not
because the header name is known. The second keeps its session cookie in full:
session is not a recognised query-parameter name and the value is too short
for the opaque-run rule.
If you are logging a request dump, mask the headers before you build the dump string.
Related¶
- Redact before an external surface
- API reference — exact signatures and edge cases
- What rtb-redact does not do