Advisories for Composer/Web-Token/Jwt-Library package

2026

PHP JWT Library: RSA1_5 (RSAES-PKCS1-v1_5) decryption lacks implicit rejection, exposing a Bleichenbacher/Marvin padding oracle

RSACrypt::decryptWithRSA15() (used by the RSA1_5 key-encryption algorithm) implements RSAES-PKCS1-v1_5 decryption by inspecting the padding after RSADP and throwing InvalidArgumentException as soon as the padding is malformed. It does not implement the implicit-rejection countermeasure required by RFC 3447 §7.2.2 / RFC 8017 §7.1.2 (return a deterministic pseudo-random value of the expected length on padding failure and let the downstream step fail uniformly). From a JWE caller this yields a Bleichenbacher/Marvin padding …

PHP JWT Library: PBES2-HS*+A*KW unwrap accepts an unbounded p2c iteration count, enabling CPU-amplification denial of service

When a JWE uses a password-based key-encryption algorithm (PBES2-HS256+A128KW, PBES2-HS384+A192KW, PBES2-HS512+A256KW), PBES2AESKW::unwrapKey() reads the p2c (PBKDF2 iteration count) parameter directly from the attacker-controlled JOSE header and passes it to hash_pbkdf2() with no upper bound. The only validation performed (checkHeaderAdditionalParameters()) was is_int($p2c) && $p2c > 0. An unauthenticated attacker can craft a single JWE whose protected header sets a very large p2c (e.g. 100_000_000 ≈ 87 s of CPU, or PHP_INT_MAX), …

PHP JWT Framework: JWSVerifier uses algorithm from unprotected header, enabling algorithm confusion attacks

JWSVerifier::getAlgorithm() in src/Library/Signature/JWSVerifier.php (line 144) merges protected and unprotected headers using PHP's spread operator: $completeHeader = […$signature->getProtectedHeader(), …$signature->getHeader()]; In PHP, when spreading arrays with duplicate string keys, the last array's values take precedence. Since the unprotected header (getHeader()) is spread second, an attacker can override the integrity-protected alg parameter by placing a different value in the unprotected header. This creates a Time-of-Check/Time-of-Use (TOCTOU) vulnerability: HeaderCheckerManager validates alg from the protected …

PHP JWT Framework: Chacha20Poly1305 key-encryption algorithm discards the Poly1305 authentication tag, performing no authentication on decryption

The experimental Chacha20Poly1305 key-encryption algorithm generates the 16-byte Poly1305 authentication tag during encryptKey() but discards it: the tag is never written to the header and therefore never reaches the wire. On the receiving side, decryptKey() calls openssl_decrypt('chacha20-poly1305', …) without the tag argument, which makes OpenSSL skip authentication entirely. As a result the AEAD construction is silently degraded to unauthenticated ChaCha20: a tampered encrypted CEK is accepted, and because ChaCha20 is …