rules:
  - id: auth.fastify.cors-wildcard-credentials
    languages:
      - javascript
      - typescript
    severity: ERROR
    message: |
      `@fastify/cors` is registered with a wildcard/reflected origin
      (`origin: '*'` or `origin: true`) together with `credentials: true`. The
      CORS spec forbids `Access-Control-Allow-Origin: *` with credentials, so
      `origin: true` reflects the caller's origin back instead, effectively
      allowing credentialed cross-site requests from ANYWHERE. That is a
      CSRF / account-takeover primitive.

      Enumerate the exact trusted origins instead:
      `fastify.register(cors, { origin: ['https://app.example.com'], credentials: true })`,
      or pass a function that validates the origin against an allowlist. If the
      API is public and needs no cookies or auth headers, keep `credentials` at
      its default `false`.
    # Requires BOTH the wildcard/reflected origin AND credentials: true on the
    # same @fastify/cors registration (either key order). The plugin regex keeps
    # it scoped to a cors registration; a scoped origin (URL string, array
    # allowlist, or validating function) with credentials never matches, and a
    # wildcard origin without credentials (a public API) is left alone.
    patterns:
      - pattern-either:
          - pattern: '$F.register($PLUGIN, { ..., origin: "*", ..., credentials: true, ... })'
          - pattern: '$F.register($PLUGIN, { ..., credentials: true, ..., origin: "*", ... })'
          - pattern: '$F.register($PLUGIN, { ..., origin: true, ..., credentials: true, ... })'
          - pattern: '$F.register($PLUGIN, { ..., credentials: true, ..., origin: true, ... })'
      - metavariable-regex:
          metavariable: $PLUGIN
          regex: (?i).*cors
    paths:
      exclude:
        - "**/test/**"
        - "**/__tests__/**"
        - "**/*.test.*"
        - "**/*.spec.*"
        - "**/example/**"
        - "**/examples/**"
        - "**/demo/**"
        - "**/benchmark/**"
        - "**/benchmarks/**"
        - "**/integration/**"
        - "**/*.tst.*"
    metadata:
      oauthlint-rule-id: AUTH-FASTIFY-003
      oauthlint-doc-url: https://oauthlint.dev/rules/fastify-cors-wildcard-credentials
      category: security
      cwe: CWE-942
      owasp: API8:2023
      llm-prevalence: MEDIUM
      technology:
        - fastify
        - "@fastify/cors"
      references:
        - https://github.com/fastify/fastify-cors#options
        - https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors/CORSNotSupportingCredentials
