rules:
  - id: auth.flow.credentials-in-url
    languages:
      - javascript
      - typescript
    severity: ERROR
    message: |
      A secret credential is placed in a URL query string. URLs leak into
      server access logs, reverse-proxy logs, browser history, and the
      `Referer` header (sent to every third-party CDN, analytics, and ad
      script on the destination page), so any of `password`, `client_secret`,
      `api_key`, `apikey`, or `secret` in the query is a leaked credential.

      Send credentials in the POST request body or in the `Authorization`
      header. Never in the URL.

      OWASP ASVS V3.2 / CWE-598 explicitly forbid credentials in URL
      parameters.
    # `access_token` is deliberately NOT matched: passing it as a query
    # parameter to a provider's userinfo/API endpoint is a legitimate (and
    # sometimes mandated) server-side OAuth pattern. Flagging it produces
    # false positives on real provider integrations. Bearer tokens in URLs
    # are still covered by auth.jwt.in-url for JWT-shaped tokens.
    pattern-either:
      # Credential name in a query string (literal or template-built URL).
      - pattern-regex: '[?&](?:password|client_secret|api_key|apikey|secret)='
      # URLSearchParams / params builder: .set('client_secret', ...) / .append('secret', ...)
      - pattern-regex: '\.(?:set|append)\s*\(\s*[''"`](?:password|client_secret|api_key|apikey|secret)[''"`]'
    metadata:
      oauthlint-rule-id: AUTH-FLOW-009
      oauthlint-doc-url: https://oauthlint.dev/rules/flow-credentials-in-url
      category: security
      cwe: CWE-598
      owasp: API2:2023
      llm-prevalence: HIGH
      references:
        - https://owasp.org/www-project-application-security-verification-standard/
