Skip to content

OAuth redirect URLs are console.log'd to stdout in production — leaks state tokens to server logs #202

@hariom888

Description

@hariom888

Root cause: In apps/backend/src/routes/auth.ts, lines 30–31 and 158–159 call console.log('--- GITHUB OAUTH REDIRECT ---') and console.log('URL:', authUrl). The authUrl variable contains the full OAuth authorization URL including the state parameter. The state token is a 64-character hex string generated by randomBytes(32), designed specifically to be a secret CSRF protection token. Logging it to stdout in production means it ends up in any log aggregator (Datadog, CloudWatch, Loki, etc.), and anyone with log-read access can extract valid state tokens and craft CSRF attacks against the OAuth flow. The app uses app.log.error elsewhere — these are the only two places using raw console.log.

Why it matters: OAuth state tokens are security-sensitive. NIST SP 800-63B and the OAuth 2.0 Security Best Current Practice (RFC 9700) both treat unintentional disclosure of state tokens as a CSRF vulnerability. Beyond the security angle, console.log bypasses Fastify's structured logger (pino), breaking log formatting and level filtering in production. This is a quick, high-signal fix.

Affected files/functions: apps/backend/src/routes/auth.ts, /github handler lines 30–31, /google handler lines 158–159.

Current behavior: Every OAuth initiation logs the full redirect URL including the state token to raw stdout using console.log, bypassing Fastify's pino logger.

Expected behavior: Debug logging should either be removed entirely (preferred) or replaced with app.log.debug(...) which (a) uses pino structured logging, (b) is suppressed in production when log level is info or above, and (c) should never include the full URL with the state token.

Minimal fix plan:
Remove the four console.log lines (lines 30, 31, 158, 159) from auth.ts. If debug logging is truly needed during development, replace with app.log.debug({ provider: 'github' }, 'OAuth redirect initiated') — logging the provider name only, never the URL or state.

Suggested tests: Add a test that spies on console.log during a GET /auth/github request and asserts it is never called. Also assert app.log.debug is called at most once and does not contain the word state in its arguments.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions