rules:
  - id: auth.ruby.jwt.algorithm-none
    languages:
      - ruby
    severity: ERROR
    message: |
      A JWT is encoded or decoded with the `none` algorithm, which produces (and
      accepts) unsigned tokens. Anyone can craft a token with any claims and it
      will be trusted, because there is no signature to verify (CWE-347). This
      shows up in AI-generated "quick token" and debugging code that then ships.

      Sign with a real algorithm and a key from configuration:
        JWT.encode(payload, ENV.fetch('JWT_SECRET'), 'HS256')
        JWT.decode(token, key, true, { algorithm: 'HS256' })
    patterns:
      - pattern-either:
          - patterns:
              - pattern: JWT.encode($P, $K, $ALG)
              - metavariable-regex:
                  metavariable: $ALG
                  regex: (?i)^["']?none["']?$
          - patterns:
              - pattern: 'JWT.decode($T, $K, $V, algorithm: $ALG)'
              - metavariable-regex:
                  metavariable: $ALG
                  regex: (?i)^["']?none["']?$
          - patterns:
              - pattern: 'JWT.decode($T, $K, $V, {algorithm: $ALG})'
              - metavariable-regex:
                  metavariable: $ALG
                  regex: (?i)^["']?none["']?$
          - pattern-regex: '(?i)JWT\.decode\([^)]*algorithms:\s*\[[^\]]*["'']none["'']'
    paths:
      exclude:
        - "**/spec/**"
        - "**/test/**"
        - "**/*_spec.rb"
        - "**/*_test.rb"
        - "**/features/**"
    metadata:
      oauthlint-rule-id: AUTH-RUBY-JWT-003
      oauthlint-doc-url: https://oauthlint.dev/rules/ruby-jwt-algorithm-none
      category: security
      cwe: CWE-347
      owasp: API2:2023
      llm-prevalence: MEDIUM
      technology:
        - ruby-jwt
      references:
        - https://github.com/jwt/ruby-jwt
        - https://cwe.mitre.org/data/definitions/347.html
