Documentation
¶
Overview ¶
Package redact strips credential-like content from free-form strings at the boundary between trusted and untrusted observability surfaces (telemetry vendors, log aggregators, metric stores).
Threat model ¶
Error messages, command arguments, and HTTP header values routinely carry credentials by accident: an HTTP client wraps a URL with an embedded token, a command-line flag like `--api-key=sk-abc123` lands in `os.Args`, an error from a failed OTLP export quotes an Authorization header. The moment that content reaches a third-party ingest, it is outside the operator's control — potentially replicated, indexed, and retained longer than intended.
The right defence is to redact at the boundary. This package applies pattern-based redaction in-process, before data is shipped. Callers do not need to remember to sanitise: the collector, middleware, and logger helpers route untrusted strings through String on their way out.
Discipline ¶
Use String or Error anywhere a caller-supplied or environment-derived string is written to telemetry, distributed logs, or any surface where credentials would be harmful. Do not use it on local process logs that never leave the host — those may need raw content for debugging.
Limitations ¶
Pattern catalogues never reach 100 % recall. The rules here catch the common shapes (URL userinfo, common query-parameter names, Authorization-header tokens, well-known provider prefixes like "sk-", "ghp_", "AIza", "AKIA", and a conservative ≥ 41-char opaque token fallback). A custom credential in a non-standard format will slip through; callers handling such inputs must supply their own redaction upstream.
The fallback opaque-token pattern is intentionally conservative (≥ 41 chars) so it does not false-positive on UUIDs (36 with hyphens), MD5 (32) or SHA-1 (40) hashes. SHA-256 (64 chars) will match — accepted tradeoff; hashes rarely appear in error strings.
Patterns are ASCII-only. Virtually all real-world provider tokens are ASCII; UTF-8 credentials in the wild are vanishingly rare.
See docs/development/specs/2026-04-17-telemetry-redaction.md (M-5 and M-6 from the 2026-04-17 security audit) for the full threat model and design rationale.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var SensitiveHeaderKeys = []string{
"Authorization",
"Proxy-Authorization",
"Cookie",
"Set-Cookie",
"X-API-Key",
"X-API-Token",
"X-Auth-Token",
"X-Access-Token",
"X-CSRF-Token",
"X-Session-Token",
}
SensitiveHeaderKeys is the default set of HTTP header names whose values should be redacted whenever headers are written to a log, telemetry, or error surface. Match is case-insensitive.
Callers that need to add more entries should compose a wider set locally rather than mutating this slice at runtime.
Functions ¶
func Error ¶
Error is a convenience wrapper equivalent to String(err.Error()). Returns "" for a nil error so callers do not need to guard.
func IsSensitiveHeaderKey ¶
IsSensitiveHeaderKey reports whether name identifies a header whose value should be redacted before logging. Matches either (a) an entry of SensitiveHeaderKeys (case-insensitive exact) or (b) the fuzzy substring pattern used for advisory warnings.
Use (a) when deciding what to redact; use the result of this function when deciding whether to WARN about a caller-supplied header name.
func String ¶
String applies all redaction patterns to s and returns the sanitised result. Safe to call on any string; idempotent; returns the input unchanged when no sensitive patterns match.
Invariants guaranteed by [FuzzRedactString]:
- No panic on any input.
- len(String(s)) <= len(s) + K, where K is a small constant accounting for the fixed-length replacements (e.g. "***", "<redacted-token>"). Never pathologically grows the input.
- String(String(s)) == String(s) — applying redaction twice produces the same output as applying it once.
Types ¶
This section is empty.