redact

package
v0.2.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 14, 2026 License: MIT Imports: 2 Imported by: 0

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

View Source
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

func Error(err error) string

Error is a convenience wrapper equivalent to String(err.Error()). Returns "" for a nil error so callers do not need to guard.

func IsSensitiveHeaderKey

func IsSensitiveHeaderKey(name string) bool

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

func String(s string) 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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL