package apperr import "testing" func TestSanitize(t *testing.T) { cases := map[string]string{ "user paul@tito.io not found": "user not found", "Authorization: Bearer abc.def-ghi": "Authorization: Bearer ", "basic dXNlcjpwYXNz failed": "basic failed", "GET /x?token=abc123&y=1": "GET /x?token=&y=1", `{"password": "hunter2", "n": 3}`: `{"password": "", "n": 3}`, "api_key=sk-live-1234 ok": "api_key= ok", "digest 0123456789abcdef0123456789abcdef done": "digest done", "b64 QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo0MTIzNA== ok": "b64 ok", "short 4123 stays": "short 4123 stays", "nothing here": "nothing here", // Regression: a long run of letters/digits/"/"/"-"/"_" is not // automatically a secret — a path or a long identifier must // survive; only something hex- or base64-shaped is redacted. "at Object. (/app/node_modules/express/lib/router/index.js:284:7)": "at Object. (/app/node_modules/express/lib/router/index.js:284:7)", "internalServerErrorHandlerMiddlewareFactory": "internalServerErrorHandlerMiddlewareFactory", "sess 0123456789abcdef0123456789abcdef0123456789abcdef done": "sess done", // A JWT's dot-separated base64url segments: the "." breaks the // candidate run into two tokens. The first (36 chars, mixes // digit/upper/lower) clears the 32-char floor and is redacted; // the second (19 chars) is below the floor and survives — see // the report for why that is an accepted partial redaction here. "jwt eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0In0 x": "jwt .eyJzdWIiOiIxMjM0In0 x", } for in, want := range cases { if got := Sanitize(in); got != want { t.Errorf("Sanitize(%q) = %q, want %q", in, got, want) } } } func TestSanitizePath(t *testing.T) { cases := map[string]string{ "/reset/8f3a9c1e2b4d6f708a9b0c1d2e3f4a5b?x=1#frag": "/reset/:token", "/users/paul@tito.io/edit": "/users/:token/edit", "/items/550e8400-e29b-41d4-a716-446655440000": "/items/:token", "/s/QUJDREVGR0hJSktMTU5PUFFSU1RV": "/s/:token", "/blog/2024-review": "/blog/2024-review", "/api/v2/orders/42": "/api/v2/orders/42", "/": "/", "": "/", } for in, want := range cases { if got := SanitizePath(in); got != want { t.Errorf("SanitizePath(%q) = %q, want %q", in, got, want) } } }