Problem
app/middleware/error-handler.js's notFound returns the raw request URL verbatim:
function notFound(req, res) {
return res.status(404).json({
message: 'Not found.',
method: req.method,
path: req.originalUrl,
});
}
If an SDK puts the authKey on the query string instead of the authKey header (GET /v1/foo?authKey=SECRET) and the path 404s, the response body contains:
{ "message": "Not found.", "method": "GET", "path": "/v1/foo?authKey=SECRET" }
The client sent the secret to begin with, but echoing it back in the response body is a real exposure: any upstream reverse proxy / Cloudflare / Caddy with response-body logging now has the secret; any client-side error logger capturing 4xx bodies persists it. Logs accumulate far from where the secret was meant to live.
pino-http's request logger already routes req.url through app/middleware/redact-url.js for exactly this reason — but the notFound handler builds its own echo and skips redaction.
Proposed fix
Pass req.originalUrl through redactUrl() before echoing. Same allowlist that the pino serializer uses; same sensitive-name set (authkey, apikey, api_key, token, access_token, password, secret). Pin behavior with a test asserting ?authKey=... becomes ?authKey=<REDACTED> in the echoed path while non-sensitive params (?q=ok) are preserved.
Proudly Made in Nebraska. Go Big Red! 🌽 https://xkcd.com/2347/
Problem
app/middleware/error-handler.js'snotFoundreturns the raw request URL verbatim:If an SDK puts the
authKeyon the query string instead of theauthKeyheader (GET /v1/foo?authKey=SECRET) and the path 404s, the response body contains:{ "message": "Not found.", "method": "GET", "path": "/v1/foo?authKey=SECRET" }The client sent the secret to begin with, but echoing it back in the response body is a real exposure: any upstream reverse proxy / Cloudflare / Caddy with response-body logging now has the secret; any client-side error logger capturing 4xx bodies persists it. Logs accumulate far from where the secret was meant to live.
pino-http's request logger already routesreq.urlthroughapp/middleware/redact-url.jsfor exactly this reason — but the notFound handler builds its own echo and skips redaction.Proposed fix
Pass
req.originalUrlthroughredactUrl()before echoing. Same allowlist that the pino serializer uses; same sensitive-name set (authkey,apikey,api_key,token,access_token,password,secret). Pin behavior with a test asserting?authKey=...becomes?authKey=<REDACTED>in the echoed path while non-sensitive params (?q=ok) are preserved.Proudly Made in Nebraska. Go Big Red! 🌽 https://xkcd.com/2347/