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.py.oauth.token-request-verify-disabled

An OAuth client fetches or refreshes a token with TLS certificate verification disabled (verify=False).

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 token request carries the client_secret, the authorization code, and the issued access/refresh tokens; with verification off, an attacker who can intercept the connection presents any certificate and reads or tampers with them, a classic man-in-the-middle on the most sensitive call in the flow (CWE-295).

Never pass verify=False to fetch_token / refresh_token / fetch_access_token (Authlib, requests-oauthlib). Leave verification on (the default) so the system CA bundle is used, or point verify at a CA bundle path for a private CA.

VULNERABLE
vulnerable.py
"""OAuth token exchange with TLS verification disabled."""

from authlib.integrations.requests_client import OAuth2Session, OAuth1Session

TOKEN_URL = "https://idp.example.com/oauth/token"


def fetch(client_id: str, client_secret: str, code: str):
    client = OAuth2Session(client_id, client_secret)
    # ruleid: auth.py.oauth.token-request-verify-disabled
    return client.fetch_token(TOKEN_URL, code=code, verify=False)


def refresh(client, rt: str):
    # ruleid: auth.py.oauth.token-request-verify-disabled
    return client.refresh_token(TOKEN_URL, refresh_token=rt, verify=False)


def oauth1_access(client_id: str, client_secret: str):
    client = OAuth1Session(client_id, client_secret)
    # ruleid: auth.py.oauth.token-request-verify-disabled
    return client.fetch_access_token("https://idp.example.com/access_token", verify=False)
SAFE
safe.py
"""OAuth token exchange that keeps TLS verification on."""

from authlib.integrations.requests_client import OAuth2Session

TOKEN_URL = "https://idp.example.com/oauth/token"
CA_BUNDLE = "/etc/ssl/certs/internal-ca.pem"


def fetch(client_id: str, client_secret: str, code: str):
    client = OAuth2Session(client_id, client_secret)
    # ok: auth.py.oauth.token-request-verify-disabled -- verification left on (default)
    return client.fetch_token(TOKEN_URL, code=code)


def fetch_explicit(client_id: str, client_secret: str, code: str):
    client = OAuth2Session(client_id, client_secret)
    # ok: auth.py.oauth.token-request-verify-disabled -- verification explicitly on
    return client.fetch_token(TOKEN_URL, code=code, verify=True)


def fetch_private_ca(client_id: str, client_secret: str, code: str):
    client = OAuth2Session(client_id, client_secret)
    # ok: auth.py.oauth.token-request-verify-disabled -- pinned to a private CA bundle
    return client.fetch_token(TOKEN_URL, code=code, verify=CA_BUNDLE)

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.py.oauth.token-request-verify-disabled -- <reason>

References

https://docs.authlib.org/en/latest/client/oauth2.html ↗https://requests.readthedocs.io/en/latest/user/advanced/#ssl-cert-verification ↗https://cwe.mitre.org/data/definitions/295.html ↗