Sensitive header reference¶
The two header-related symbols answer a narrow question: which header names carry secrets? Neither one redacts anything — masking the value is the caller's job, and Redact HTTP headers shows how to wire that up.
The curated list: SensitiveHeaderKeys¶
redact.SensitiveHeaderKeys contains exactly ten entries, in this order:
| # | Header |
|---|---|
| 1 | Authorization |
| 2 | Proxy-Authorization |
| 3 | Cookie |
| 4 | Set-Cookie |
| 5 | X-API-Key |
| 6 | X-API-Token |
| 7 | X-Auth-Token |
| 8 | X-Access-Token |
| 9 | X-CSRF-Token |
| 10 | X-Session-Token |
Comparison against this list is case-insensitive: the entries are lowercased into a lookup map at package init, and the name you pass is lowercased too.
The list is exported for composition, not for editing — appending to it does not
change what IsSensitiveHeaderKey returns. See
Treat SensitiveHeaderKeys as read-only.
Four of the entries are guarded by TestSensitiveHeaderKeys_ContainsCoreSet
against accidental deletion — Authorization, Cookie, Set-Cookie and
X-API-Key — because external consumers rely on them.
The wider fuzzy match¶
IsSensitiveHeaderKey returns true for anything on the curated list and
for any name matching this pattern:
So a name qualifies if it contains any of these as a whole word:
auth, token, key, secret, bearer, password, credential
or contains authorization anywhere, whole word or not.
Word boundaries follow the ASCII rule where letters, digits and _ are word
characters and everything else — including - — is a separator. Header names are
hyphen-separated, so each component of X-Auth-Token is a word in its own right.
The two mechanisms answer different questions. Use the curated list when you are
deciding what your own code should mask by policy; use IsSensitiveHeaderKey
when you are deciding whether an operator-supplied header name might be hiding
a secret, where erring toward redaction is the safe direction.
Which names match, and which do not¶
| Header name | IsSensitiveHeaderKey |
Why |
|---|---|---|
Authorization |
true |
Curated list |
authorization |
true |
Comparison is case-insensitive |
" Authorization " |
true |
Surrounding whitespace is trimmed first |
Proxy-Authorization |
true |
Contains authorization |
Cookie / Set-Cookie |
true |
Curated list |
X-API-Key |
true |
Curated list, and whole word key |
X-Custom-Auth |
true |
Whole word auth |
X-User-Password |
true |
Whole word password |
X-Amz-Security-Token |
true |
Whole word token |
X-Bearer-Only |
true |
Whole word bearer |
X-Key-Id |
true |
Whole word key |
Public-Key-Pins |
true |
Whole word key — a false positive |
Content-Type |
false |
No credential word |
Accept / User-Agent / Referer |
false |
No credential word |
X-Request-ID |
false |
No credential word |
Location |
false |
No credential word, though a redirect target can carry a token |
X-Apikey |
false |
apikey is a single word; the pattern wants key alone |
Authentication |
false |
Not authorization, and auth is not a whole word here |
Www-Authenticate |
false |
Same reason |
Cookie2 |
false |
Not an exact list entry, and cookie is not in the fuzzy word list |
"" |
false |
Empty short-circuits before matching |
The pattern is word-based, so glued spellings escape it: X-API-Key matches and
X-Apikey does not. If your service accepts either spelling, test for the glued
form yourself as well.
http.Header canonicalises keys when you use Set/Get, but ranging over the
map gives you whatever form was stored. IsSensitiveHeaderKey lowercases and
trims for you, so you do not need to normalise the name before calling it.
Header values are not redacted for you¶
redact.String has no rule for a generic Name: value header line. Only
authorization: followed by Bearer, Basic, Digest or ApiKey is
recognised, and that is what makes the two header symbols necessary:
Authorization: Bearer abc123def456 → Authorization: Bearer ***
X-API-Key: abc123def456ghijklmno → unchanged
Cookie: session=deadbeef → unchanged
Pass header names through IsSensitiveHeaderKey and mask the values yourself.
Running the values you keep through String afterwards is a useful second pass —
it catches a token embedded in a Location redirect — but it is not a substitute
for the first.