← All tasks
javaauth0/java-jwt #69Not a task: already works

Race condition in repackaged Base64 breaks auths at random

envgap__auth0__java-jwt-69

01 / FAILURE SIGNATURE

As reported upstream

No identifying execution failure has been captured.
Not a benchmark task.
  • The project already builds and runs before the fix, so there is nothing to repair.

02 / ENVIRONMENT RECIPE

Base commit
217af05d16d62e462f5fa4456c090c1af9e1a51e
Manifest
pom.xml
Reproduce
Awaiting issue-specific recipe
Run under trace
Awaiting a meaningful runtime command

03 / ORIGINAL ISSUE TEXT

auth0/java-jwt #69 · read the original issue
After updating our auth0 libs to pull in some important fixes, we started having random authentication failures that would not reproduce.

Turns out that `JWTVerifier.decodeAndParse()` was failing with IOException from time to time.

Diagnosis: the base64 decoder used is not thread safe. For some reason you repackaged a buggy commons-codec.

PS: This took me almost a whole day to nail down and it's a blocker for us. 

Proof of concept:

```
import com.auth0.jwt.internal.org.apache.commons.codec.binary.Base64;

public class Poc {

  public static void main(String... args) throws Exception {

    final int threads = 2;

    String[] tokens = new String[] {
        "eyJyb2xlcyI6WyIqIiwiY29tcGFueS4wMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDAiXSwiY29tcGFueUlkIjoiMDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAwIiwidXNlcklkIjoiMDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtNzU3MzY1NzIwMDAwIiwidXNlcm5hbWUiOiJyb290IiwiZW1haWwiOiJyb290LWRldkB0aWVycmEuaW8iLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsInVzZXJfaWQiOiJhdXRoMHw1NzkwYTcyNTYzMjkyYjY5NmZlMjEwZWUiLCJpc3MiOiJodHRwczovL3RpZXJyYS1pb3QuYXV0aDAuY29tLyIsInN1YiI6ImF1dGgwfDU3OTBhNzI1NjMyOTJiNjk2ZmUyMTBlZSIsImF1ZCI6Im9SdkJHVFRQV0JFekVDNTU5aUFXRGt6M3MyMWNVNkJ3IiwiZXhwIjoxNDcxNjI5MDc0LCJpYXQiOjE0NzE1OTMwNzR9",
        "eyJyb2xlcyI6WyIqIiwiY29tcGFueS4wMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDAiXSwiY29tcGFueUlkIjoiMDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAwIiwidXNlcklkIjoiMDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtNzU3MzY1NzIwMDAwIiwidXNlcm5hbWUiOiJyb290IiwiZW1haWwiOiJ4QHRpZXJyYS5pbyIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwidXNlcl9pZCI6ImF1dGgwfDU3OTBhNzI1NjMyOTJiNjk2ZmUyMTBlZiIsImlzcyI6Imh0dHBzOi8vdGllcnJhLWlvdC5hdXRoMC5jb20vIiwic3ViIjoiYXV0aDB8NTc5MGE3MjU2MzI5MmI2OTZmZTIxMGVlIiwiYXVkIjoib1J2QkdUVFBXQkV6RUM1NTlpQVdEa3ozczIxY1U2QnciLCJleHAiOjE0NzE2MjkwNzQsImlhdCI6MTQ3MTU5MzA3NH0="
    };

    final Base64 decoder = new Base64(true);

    for (int i = 0; i < threads; i++) {

      final String b64String = tokens[i % tokens.length];
      final String expected = new String(decoder.decode(b64String), "UTF-8"); // no concurrency here

      (new Thread() {

        @Override
        public void run() {
          System.err.println("Starting thread");
          try {
            while (true) {
              final String jsonString = new String(decoder.decode(b64String), "UTF-8");
              if (!expected.equals(jsonString)) {
                System.err.println("BUG: got <" +  jsonString + ">, expected + <" + expected + ">");
                break;
              }
            }
          } catch (Exception e) {
            e.printStackTrace();
          }
          System.exit(1);
        }

      }).start();

    }
  }
}

```
Continue on GitHub ↗

04 / LABELS

Labels from the report text only; not yet run

No supported category has been assigned.

Label rules and the text that matched
[]