rules:
  - id: auth.php.secret.hardcoded-jwt-key
    languages:
      - php
    severity: ERROR
    message: |
      A JWT signing key is a hard-coded string literal, passed to
      `JWT::encode()` / `new Key()` (firebase/php-jwt) or
      `InMemory::plainText()` / `InMemory::base64Encoded()` (lcobucci/jwt). This
      key signs and verifies every token: committed to source control it is one
      search away from compromise, letting an attacker forge a token for any
      user or role (CWE-798). AI-generated samples inline the secret to make the
      snippet "just work" and it ships unchanged.

      Read the key from the environment or a secret store instead:
        JWT::encode($payload, $_ENV['JWT_SECRET'], 'HS256');
        new Key(getenv('JWT_SECRET'), 'HS256');
    # Only a quoted string literal of a plausible length (>= 6) fires. `$_ENV[..]`,
    # `getenv(...)`, `config(...)` and plain variables are not string literals, so
    # they never match; the length floor drops trivial placeholders.
    patterns:
      - pattern-either:
          - patterns:
              - pattern: JWT::encode($P, $K, $ALG)
              - metavariable-regex:
                  metavariable: $K
                  regex: "^[\"'][^\"']{6,}[\"']$"
          - patterns:
              - pattern: new Key($K, $ALG)
              - metavariable-regex:
                  metavariable: $K
                  regex: "^[\"'][^\"']{6,}[\"']$"
          - patterns:
              - pattern: InMemory::plainText($K)
              - metavariable-regex:
                  metavariable: $K
                  regex: "^[\"'][^\"']{6,}[\"']$"
          - patterns:
              - pattern: InMemory::base64Encoded($K)
              - metavariable-regex:
                  metavariable: $K
                  regex: "^[\"'][^\"']{6,}[\"']$"
    paths:
      exclude:
        - "**/test/**"
        - "**/*Test.php"
        - "**/vendor/**"
        - "**/examples/**"
        - "**/samples/**"
        - "**/demo/**"
    metadata:
      oauthlint-rule-id: AUTH-PHP-SECRET-001
      oauthlint-doc-url: https://oauthlint.dev/rules/php-secret-hardcoded-jwt-key
      category: security
      cwe: CWE-798
      owasp: API2:2023
      llm-prevalence: HIGH
      technology:
        - firebase-php-jwt
        - lcobucci-jwt
      references:
        - https://github.com/firebase/php-jwt
        - https://github.com/lcobucci/jwt
        - https://cwe.mitre.org/data/definitions/798.html
