v0.14 is out: a mobile auth pack for Swift/iOS and Android, catching insecure token storage, cleartext traffic, and OAuth in embedded WebViews. Read more →
HIGH AI PREVALENCE: MEDIUM auth.flow.oauth-credential-in-log

An OAuth/OIDC credential from the request flows into a logging call.

Why AI tools produce this: AI coding tools produce this regularly, typically when prompted for a shortcut or a quick fix.

Why this matters

The tainted value is an authorization code, an access_token / refresh_token / id_token, a bearer token, a client_secret, or the raw Authorization header, and the sink is a console.* or logger.* call. Logs are written to files, shipped to aggregators (Datadog, Splunk, CloudWatch) and read by people and systems that should never see live credentials. A leaked authorization code or token can be replayed to impersonate the user or complete the OAuth exchange (CWE-532).

Never log the raw credential. Redact or mask it before logging (token.slice(0, 4) + '…'), log a non-sensitive identifier instead (a user id, a key id), or drop the field entirely.

VULNERABLE
vulnerable.ts
import type { Request, Response } from 'express';

declare const logger: {
  info: (...a: unknown[]) => void;
  debug: (...a: unknown[]) => void;
  error: (...a: unknown[]) => void;
};

// Authorization code from the callback logged directly.
export function callback(req: Request, res: Response): void {
  // ruleid: auth.flow.oauth-credential-in-log
  console.log('oauth callback', req.query.code);
  res.sendStatus(200);
}

// access_token assigned to a local, then logged via a logger (indirection).
export function exchange(req: Request, res: Response): void {
  const at = req.body.access_token as string;
  // ruleid: auth.flow.oauth-credential-in-log
  logger.info('token exchange complete', at);
  res.sendStatus(200);
}

// Raw Authorization header logged on an auth failure.
export function authFailure(req: Request, res: Response): void {
  // ruleid: auth.flow.oauth-credential-in-log
  console.error('auth failed for', req.headers.authorization);
  res.sendStatus(401);
}

// refresh_token from the body logged via logger.debug.
export function refresh(req: Request, res: Response): void {
  const rt = req.body.refresh_token as string;
  // ruleid: auth.flow.oauth-credential-in-log
  logger.debug(rt);
  res.sendStatus(200);
}

// id_token via index accessor, interpolated into a warning.
export function verifyId(req: Request, res: Response): void {
  // ruleid: auth.flow.oauth-credential-in-log
  console.warn('received id_token', req.query['id_token']);
  res.sendStatus(200);
}
SAFE
safe.ts
import type { Request, Response } from 'express';

declare const logger: {
  info: (...a: unknown[]) => void;
  debug: (...a: unknown[]) => void;
};

declare function redact(value: string): string;

// Constant status message — no request data, no taint.
export function ping(_req: Request, res: Response): void {
  console.log('oauth callback received');
  res.sendStatus(200);
}

// Benign request field (pagination) — not a credential source.
export function list(req: Request, res: Response): void {
  console.log('listing page', req.query.page);
  res.sendStatus(200);
}

// Non-credential identifier — safe to log.
export function whoami(req: Request, res: Response): void {
  logger.info('request from user', req.query.userId);
  res.sendStatus(200);
}

// Sanitized: only a masked prefix of the code is logged.
export function callback(req: Request, res: Response): void {
  const code = req.query.code as string;
  console.log('code prefix', code.slice(0, 6));
  res.sendStatus(200);
}

// Sanitized: the Authorization header is redacted before logging.
export function authFailure(req: Request, res: Response): void {
  logger.debug('auth failed for', redact(req.headers.authorization as string));
  res.sendStatus(401);
}

Suppressing this rule

If a finding is a genuine false positive, scope the suppression to the exact line and leave a reason, never disable the rule project-wide. Disable directives are line-scoped by design.

// oauthlint-disable-next-line auth.flow.oauth-credential-in-log -- <reason>

References

https://cwe.mitre.org/data/definitions/532.html ↗https://datatracker.ietf.org/doc/html/rfc6749#section-10.3 ↗https://owasp.org/API-Security/editions/2023/en/0xa8-security-misconfiguration/ ↗