CVE-2015-2951: Improper Input Validation (CWE-20)
value: JWT.php in F21 JWT before 2.0 allows remote attackers to bypass signature verification via crafted tokens.
CWE description: The product receives input or data, but it does
        not validate or incorrectly validates that the input has the
        properties that are required to process the data safely and
        correctly.
Published: 2015-06-05T10:59Z
Repository: https://github.com/F21/jwt
Language: PHP
Files changed: JWT/JWT.php, README.md
Commit date: 2015-05-01 22:21:32 +1000
Commit message: Fixed security issue: JVN#06120222

Diff: diff --git a/JWT/JWT.php b/JWT/JWT.php
index 8de71ec..d692e8d 100644
--- a/JWT/JWT.php
+++ b/JWT/JWT.php
@@ -23,11 +23,11 @@ class JWT
         $segments[] = JWT::urlsafeB64Encode($signature);
 
         return implode('.', $segments);
     }
 
-    public static function decode($jwt, $key = null, $verify = true)
+    public static function decode($jwt, $key = null, $algo = null)
     {
         $tks = explode('.', $jwt);
 
         if (count($tks) != 3) {
             throw new Exception('Wrong number of segments');
@@ -43,24 +43,25 @@ class JWT
             throw new Exception('Invalid segment encoding');
         }
 
         $sig = JWT::urlsafeB64Decode($cryptob64);
 
-        if ($verify) {
+        if (isset($key)) {
+
             if (empty($header->alg)) {
                 throw new DomainException('Empty algorithm');
             }
 
-            if (!JWT::verifySignature($sig, "$headb64.$payloadb64", $key, $header->alg)) {
+            if (!JWT::verifySignature($sig, "$headb64.$payloadb64", $key, $algo)) {
                 throw new UnexpectedValueException('Signature verification failed');
             }
         }
 
         return $payload;
     }
 
-    private static function verifySignature($signature, $input, $key, $algo = 'HS256')
+    private static function verifySignature($signature, $input, $key, $algo)
     {
         switch ($algo) {
             case'HS256':
             case'HS384':
             case'HS512':
@@ -78,11 +79,11 @@ class JWT
             default:
                 throw new Exception("Unsupported or invalid signing algorithm.");
         }
     }
 
-    private static function sign($input, $key, $algo = 'HS256')
+    private static function sign($input, $key, $algo)
     {
         switch ($algo) {
 
             case 'HS256':
                 return hash_hmac('sha256', $input, $key, true);
diff --git a/README.md b/README.md
index 4f9c956..6c446c1 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,20 @@
 JWT
 ===
-
 A PHP library for encoding and decoding JSON Web Tokens.
 
+**Important security notice**
+
+Thanks to Toshiharu Sugiyama!
+
+Please upgrade to 2.0 as soon as possible as previous versions are susceptible to verification bypass attacks if the same public key is used for signing when using asymmetric and symmetric algorithms.
+
+This is a release breaks backwards compatibility because you now need to pass in the decoding algorithm when decoding in order to verify the JWT.
+
+For more information see: JVN#06120222 at jpcert.or.jp
+
+
 Supported Algorithms
 --------------------
 
 **HMAC**
 

Vulnerable code:     public static function decode($jwt, $key = null, $verify = true)
        if ($verify) {
            if (!JWT::verifySignature($sig, "$headb64.$payloadb64", $key, $header->alg)) {
    private static function verifySignature($signature, $input, $key, $algo = 'HS256')
    private static function sign($input, $key, $algo = 'HS256')

Fixed code:     public static function decode($jwt, $key = null, $algo = null)
        if (isset($key)) {

            if (!JWT::verifySignature($sig, "$headb64.$payloadb64", $key, $algo)) {
    private static function verifySignature($signature, $input, $key, $algo)
    private static function sign($input, $key, $algo)
**Important security notice**

Thanks to Toshiharu Sugiyama!

Please upgrade to 2.0 as soon as possible as previous versions are susceptible to verification bypass attacks if the same public key is used for signing when using asymmetric and symmetric algorithms.

This is a release breaks backwards compatibility because you now need to pass in the decoding algorithm when decoding in order to verify the JWT.

For more information see: JVN#06120222 at jpcert.or.jp