java.java-jwt.security.audit.jwt-decode-without-verify.java-jwt-decode-without-verify

profile photo of semgrepsemgrep
Author
6,345
Download Count*

Detected the decoding of a JWT token without a verify step. JWT tokens must be verified before use, otherwise the token's integrity is unknown. This means a malicious actor could forge a JWT token with any claims. Call '.verify()' before using the token.

Run Locally

Run in CI

Defintion

rules:
  - id: java-jwt-decode-without-verify
    message: Detected the decoding of a JWT token without a verify step. JWT tokens
      must be verified before use, otherwise the token's integrity is unknown.
      This means a malicious actor could forge a JWT token with any claims. Call
      '.verify()' before using the token.
    metadata:
      cwe:
        - "CWE-345: Insufficient Verification of Data Authenticity"
      owasp:
        - A08:2021 - Software and Data Integrity Failures
      source-rule-url: https://semgrep.dev/blog/2020/hardcoded-secrets-unverified-tokens-and-other-common-jwt-mistakes/
      category: security
      technology:
        - jwt
      confidence: MEDIUM
      references:
        - https://owasp.org/Top10/A08_2021-Software_and_Data_Integrity_Failures
      subcategory:
        - vuln
      likelihood: LOW
      impact: HIGH
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - Improper Authentication
    languages:
      - java
    severity: WARNING
    patterns:
      - pattern: |
          com.auth0.jwt.JWT.decode(...);
      - pattern-not-inside: |-
          class $CLASS {
            ...
            $RETURNTYPE $FUNC (...) {
              ...
              $VERIFIER.verify(...);
              ...
            }
          }

Examples

jwt-decode-without-verify.java

package jwt_test.jwt_test_1;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier;

public class App
{

    private void verifyToken(String token, String secret) {
        Algorithm algorithm = Algorithm.HMAC256(secret);
        JWTVerifier verifier = JWT.require(algorithm)
                .withIssuer("auth0")
                .build(); //Reusable verifier instance
        DecodedJWT jwt2 = verifier.verify(token);
    }

    public void ok( String[] args )
    {
        System.out.println( "Hello World!" );

        try {
            Algorithm algorithm = Algorithm.HMAC256(args[0]);

            String token = JWT.create()
                .withIssuer("auth0")
                .sign(algorithm);

            DecodedJWT jwt = JWT.decode(token);

        } catch (JWTCreationException exception){
            //Invalid Signing configuration / Couldn't convert Claims.
        }

    }
}

abstract class App2
{

    private void bad( String[] args )
    {
        System.out.println( "Hello World!" );

        try {
            Algorithm algorithm = Algorithm.none();

            String token = JWT.create()
                .withIssuer("auth0")
                .sign(algorithm);
            // ruleid: java-jwt-decode-without-verify
            DecodedJWT jwt = JWT.decode(token);

        } catch (JWTCreationException exception){
            //Invalid Signing configuration / Couldn't convert Claims.
        }

    }
}