Skip to content

security(error-handler): notFound echoes raw query string — leaks authKey if a client mis-sends it as ?authKey= #131

@CryptoJones

Description

@CryptoJones

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/

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions