ruby.jwt.security.jwt-hardcode.ruby-jwt-hardcoded-secret

Verifed by r2c
Community Favorite
profile photo of semgrepsemgrep
Author
63,819
Download Count*

Hardcoded JWT secret or private key is used. This is a Insufficiently Protected Credentials weakness: https://cwe.mitre.org/data/definitions/522.html Consider using an appropriate security mechanism to protect the credentials (e.g. keeping secrets in environment variables)

Run Locally

Run in CI

Defintion

rules:
  - id: ruby-jwt-hardcoded-secret
    message: "Hardcoded JWT secret or private key is used. This is a Insufficiently
      Protected Credentials weakness:
      https://cwe.mitre.org/data/definitions/522.html Consider using an
      appropriate security mechanism to protect the credentials (e.g. keeping
      secrets in environment variables)"
    metadata:
      cwe:
        - "CWE-522: Insufficiently Protected Credentials"
      owasp:
        - A02:2017 - Broken Authentication
        - A04:2021 - Insecure Design
      source-rule-url: https://semgrep.dev/blog/2020/hardcoded-secrets-unverified-tokens-and-other-common-jwt-mistakes/
      category: security
      technology:
        - jwt
      references:
        - https://owasp.org/Top10/A04_2021-Insecure_Design
      cwe2021-top25: true
      subcategory:
        - audit
      likelihood: LOW
      impact: LOW
      confidence: LOW
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - Cryptographic Issues
    patterns:
      - pattern-inside: |
          require 'jwt'
          ...
      - pattern-either:
          - pattern: |
              JWT.encode($PAYLOAD,"...",...)
          - pattern: |
              JWT.decode($PAYLOAD,"...",...)
          - pattern: |
              JWT.encode($PAYLOAD,nil,...)
          - pattern: |
              JWT.decode($PAYLOAD,nil,...)
          - pattern: |
              $SECRET = "..."
              ...
              JWT.encode($PAYLOAD,$SECRET,...)
          - pattern: |
              $SECRET = "..."
              ...
              JWT.decode($PAYLOAD,$SECRET,...)
      - pattern-not: |
          JWT.encode($PAYLOAD, nil, ... , jwks: ..., ...)
      - pattern-not: |
          JWT.decode($PAYLOAD, nil, ..., jwks: ..., ...)
    languages:
      - ruby
    severity: ERROR

Examples

jwt-hardcode.rb

require 'jwt'

# ruleid: ruby-jwt-hardcoded-secret
secret_const = 'secret-yo'

def bad1
    # ruleid: ruby-jwt-hardcoded-secret
    hmac_secret = 'my$ecretK3y'
    # ruleid: ruby-jwt-hardcoded-secret
    token = JWT.encode payload, hmac_secret, 'HS256'
    puts token
end

def bad2(token)
    # ruleid: ruby-jwt-hardcoded-secret
    decoded_token = JWT.decode token, secret_const, true, { algorithm: 'HS256' }
    puts decoded_token
end

def bad3
    # ruleid: ruby-jwt-hardcoded-secret
    token = JWT.encode payload, 'hardcode', 'HS256'
    puts token
end

def bad4
    # ruleid: ruby-jwt-hardcoded-secret
    token = JWT.encode payload, nil, 'HS256'
    puts token
end

def ok1(secret_key)
    # ok: ruby-jwt-hardcoded-secret
    token = JWT.encode payload, hmac_secret, 'HS256'
    puts token
    decoded_token = JWT.decode token, secret_key, true, { algorithm: 'HS256' }
    puts decoded_token
end

def ok2()
    token = JWT.encode payload, hmac_secret, 'HS256'
    puts token
    jwk_loader = ->(options) do
        # jwk_loader implementation here
    end
    # ok: ruby-jwt-hardcoded-secret
    decoded_token = JWT.decode token, nil, true, { algorithm: 'HS256' }, jwks: jwk_loader
    puts decoded_token
end