rules:
  - id: auth.express.trust-proxy-true
    languages:
      - javascript
      - typescript
    severity: WARNING
    message: |
      Express is configured to trust EVERY proxy (`app.set('trust proxy', true)`
      or the equivalent `app.enable('trust proxy')`). With unbounded trust,
      Express believes the `X-Forwarded-For` and `X-Forwarded-Proto` headers on
      any incoming request. A client can then spoof its source IP (defeating
      IP allowlists, rate limiters, and audit logs) and spoof `https`, which can
      trick `secure` session cookies into being sent over plain HTTP.

      Set `trust proxy` to the number of proxies actually in front of the app
      (e.g. `app.set('trust proxy', 1)`), or to a specific address / subnet /
      preset (`'loopback'`, `'uniquelocal'`, a CIDR, or an allowlist array), so
      only your real infrastructure is trusted. Never trust all proxies.
    # Matches only the two unbounded forms. A numeric hop count, a preset string,
    # a CIDR, an allowlist array, or `false` all express a BOUNDED trust and are
    # left alone, so idiomatic reverse-proxy setups never fire.
    pattern-either:
      - pattern: $APP.set("trust proxy", true)
      - pattern: $APP.enable("trust proxy")
    # Framework example/dev apps set `trust proxy: true` deliberately as working
    # demos; scanning user code should not fire on those trees.
    paths:
      exclude:
        - "**/test/**"
        - "**/__tests__/**"
        - "**/*.test.*"
        - "**/*.spec.*"
        - "**/example/**"
        - "**/examples/**"
        - "**/demo/**"
        - "**/dev/**"
    metadata:
      oauthlint-rule-id: AUTH-EXPRESS-002
      oauthlint-doc-url: https://oauthlint.dev/rules/express-trust-proxy-true
      category: security
      cwe: CWE-348
      owasp: A05:2021
      llm-prevalence: MEDIUM
      technology:
        - express
      references:
        - https://expressjs.com/en/guide/behind-proxies.html
        - https://cwe.mitre.org/data/definitions/348.html
