rules:
  - id: auth.rust.jwt.hardcoded-secret
    languages:
      - rust
    severity: ERROR
    message: |
      A JWT HMAC signing/verification key is hardcoded as a literal. It is
      passed directly to jsonwebtoken's `EncodingKey::from_secret` /
      `DecodingKey::from_secret`. Anyone who can read the source or git history
      can forge or tamper with tokens, which is a complete authentication
      bypass.

      Load the secret at runtime from the environment or a secret manager
      instead, e.g. `let key = std::env::var("JWT_SECRET")?;` followed by
      `EncodingKey::from_secret(key.as_bytes())`. Never commit signing keys to
      source control.
    # Only literals in key position are flagged: a byte-string literal
    # `b"..."`, or a string literal coerced with `"...".as_ref()` /
    # `"...".as_bytes()`. Because the literal must appear directly in the
    # argument, `from_secret(secret.as_bytes())` (a variable) and
    # `from_secret(std::env::var("JWT_SECRET")?.as_bytes())` are NOT matched.
    pattern-either:
      - pattern: jsonwebtoken::EncodingKey::from_secret(b"...")
      - pattern: jsonwebtoken::DecodingKey::from_secret(b"...")
      - pattern: EncodingKey::from_secret(b"...")
      - pattern: DecodingKey::from_secret(b"...")
      - pattern: EncodingKey::from_secret("...".as_ref())
      - pattern: DecodingKey::from_secret("...".as_ref())
      - pattern: EncodingKey::from_secret("...".as_bytes())
      - pattern: DecodingKey::from_secret("...".as_bytes())
    metadata:
      oauthlint-rule-id: AUTH-RUST-JWT-002
      oauthlint-doc-url: https://oauthlint.dev/rules/rust-jwt-hardcoded-secret
      category: security
      cwe: CWE-798
      owasp: API2:2023
      llm-prevalence: HIGH
      technology:
        - jsonwebtoken
      references:
        - https://docs.rs/jsonwebtoken/latest/jsonwebtoken/struct.EncodingKey.html#method.from_secret
        - https://cwe.mitre.org/data/definitions/798.html
