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 →
MEDIUM AI PREVALENCE: MEDIUM auth.oauth.access-token-in-url

An OAuth access_token (or refresh_token / id_token) is placed in a URL query string.

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

Why this matters

URLs leak: the full URL (token included) is recorded in server and reverse-proxy access logs, saved in browser history, and sent in the Referer header to every third-party CDN, analytics, and ad script loaded by the destination page. A token in a URL is a leaked token.

Send the token in the Authorization: Bearer … header, or in a POST request body. Never in the URL query string.

CWE-598: Use of GET Request Method With Sensitive Query Strings.

VULNERABLE
vulnerable.ts
// ruleid: auth.oauth.access-token-in-url
export function buildUrl(base: string, t: string) {
  return `${base}?access_token=${t}`;
}

// ruleid: auth.oauth.access-token-in-url
export function callbackUrl(rt: string) {
  return '/cb?refresh_token=' + rt;
}

// ruleid: auth.oauth.access-token-in-url
export function fetchResource(t: string) {
  return fetch(`https://api.example.com/me?fields=name&access_token=${t}`);
}

// ruleid: auth.oauth.access-token-in-url
export const idTokenLink =
  'https://app.example.com/dashboard?next=/home&id_token=abc123';
SAFE
safe.ts
// ok: auth.oauth.access-token-in-url -- token sent in the Authorization header, not the URL
export function callApi(accessToken: string) {
  return fetch('https://api.example.com/data', {
    headers: { Authorization: `Bearer ${accessToken}` },
  });
}

// ok: auth.oauth.access-token-in-url -- token in a POST body object property, not a URL query param
export function exchange(accessToken: string) {
  return fetch('https://api.example.com/token', {
    method: 'POST',
    body: JSON.stringify({ access_token: accessToken }),
  });
}

// ok: auth.oauth.access-token-in-url -- a non-token query parameter
export const pagedUrl = 'https://api.example.com/items?page=2';

// ok: auth.oauth.access-token-in-url -- the bare word access_token in a comment is not a URL param
export const note = 'remember to refresh the access_token before it expires';

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.oauth.access-token-in-url -- <reason>

References

https://owasp.org/Top10/A05_2021-Security_Misconfiguration/ ↗https://cwe.mitre.org/data/definitions/598.html ↗