Jun 18, 2026·7 min read·14 visits
A flaw in the way PHP JWT Framework merges headers allows parameters in unprotected headers to overwrite those in protected headers, leading to cryptographic signature bypass via algorithm confusion.
An algorithm confusion vulnerability exists in the PHP JWT Framework (web-token/jwt-library) where the JWSVerifier and JWEDecrypter components merge integrity-protected and unprotected headers using insecure methods. Under specific conditions, duplicate parameters defined in unprotected headers override those in integrity-protected headers, allowing an attacker to bypass cryptographic signature verification.
The PHP JWT Framework (web-token/jwt-framework) is an implementation of JWT, JWS, JWE, and JWK specifications. Within this framework, JSON Web Signatures (JWS) and JSON Web Encryption (JWE) operations are handled by the JWSVerifier and JWEDecrypter helper classes. These classes process cryptographic tokens which may contain both integrity-protected headers (defined in the protected segment of the token) and unprotected headers (defined in the header segment of a JSON Flattened or General serialized JWS/JWE payload).
The attack surface exists in the parser's validation pipeline, where incoming tokens are examined. Integrity-protected headers are base64url-encoded and cryptographically bound to the signature. Unprotected headers, conversely, are transmitted in plain JSON format without verification, allowing an attacker to alter their values arbitrarily without invalidating the token structure itself.
This vulnerability, classified under CWE-345 (Active Verification of Cryptographic Signature), occurs when the logic designed to merge these headers allows unprotected parameters to supersede integrity-protected parameters. When critical values such as the signature algorithm (alg) or encryption algorithm (enc) are overridden, the framework relies on unauthenticated data to execute cryptographic operations.
The underlying flaw stems from the use of unsafe array merging behavior when combining protected and unprotected headers in PHP. In PHP 8.1, array unpacking via the spread operator (...) was introduced for string-keyed arrays. This operator, alongside the legacy array_merge() function, exhibits an overwrite behavior where values from subsequent arrays replace values from prior arrays if keys are identical.
In src/Library/Signature/JWSVerifier.php, the library merges headers inside the JWSVerifier::getAlgorithm() method using the following code path:
$completeHeader = [...$signature->getProtectedHeader(), ...$signature->getHeader()];Here, $signature->getProtectedHeader() contains parameters validated by the cryptographic signature, while $signature->getHeader() contains unauthenticated parameters from the unprotected header segment. Because the unprotected header is unpacked second, duplicate keys in the unprotected header overwrite those in the protected header.
This behavior exposes a Time-of-Check to Time-of-Use (TOCTOU) vulnerability. During the 'Time-of-Check' phase, the framework uses the HeaderCheckerManager to validate parameters. This validator inspects the protected header's alg parameter (for instance, verifying that the algorithm is a permitted asymmetric algorithm like RS256). During the subsequent 'Time-of-Use' phase, JWSVerifier processes the token using the overridden algorithm from the unprotected header (for instance, a symmetric algorithm like HS256), bypassing the validation checks completed during the initial step.
A corresponding vulnerability exists in src/Library/Encryption/JWEDecrypter.php during key management processing. The class merges headers using the following instruction:
$completeHeader = array_merge(
$jwe->getSharedProtectedHeader(),
$jwe->getSharedHeader(),
$recipient->getHeader()
);Because the unprotected shared headers (getSharedHeader()) and recipient headers (getHeader()) are appended after the protected header, an attacker can override critical decryption parameters (alg and enc) and control the key unwrapping logic.
The following code blocks illustrate the vulnerable header merging logic and the subsequent remediation applied to secure the cryptographic parameter extraction.
In the vulnerable implementation, the merged header structure was passed directly to the algorithm resolution manager:
// VULNERABLE
private function getAlgorithm(Signature $signature): Algorithm
{
// Unprotected headers overwrite protected headers due to the spread operator order
$completeHeader = [...$signature->getProtectedHeader(), ...$signature->getHeader()];
if (!isset($completeHeader['alg'])) {
throw new InvalidArgumentException('No "alg" parameter found.');
}
return $this->signatureAlgorithmManager->get($completeHeader['alg']);
}The patched implementation addresses the issue by retrieving cryptographic metadata exclusively from the protected header context:
// PATCHED
private function getAlgorithm(Signature $signature): Algorithm
{
// Read parameter strictly from the cryptographically bound protected header
$protectedHeader = $signature->getProtectedHeader();
if (!isset($protectedHeader['alg'])) {
throw new InvalidArgumentException('The "alg" parameter must be in the protected header.');
}
return $this->signatureAlgorithmManager->get($protectedHeader['alg']);
}By querying $signature->getProtectedHeader() rather than $completeHeader, the resolver ignores any injected alg parameter present in the unprotected segment.
A similar fix was implemented within JWEDecrypter.php to retrieve key management and encryption parameters exclusively from the integrity-protected $jwe->getSharedProtectedHeader() and appropriate recipient headers, avoiding the insecure merge pattern entirely.
Exploitation relies on an algorithm confusion technique. This occurs when an asymmetric algorithm (such as RSA or ECDSA) is downgraded to a symmetric algorithm (such as HMAC). In asymmetric setups, the server uses a public key to verify signatures. If the server is tricked into using a symmetric algorithm, it uses that public key as a secret key to compute and verify the HMAC signature.
An attacker crafts a token leveraging JSON Flattened JWS serialization. The JSON structure is defined as follows:
{
"payload": "eyJzdWIiOiJhZG1pbiIsImV4cCI6MTkwMDAwMDAwMH0",
"protected": "eyJhbGciOiJSUzI1NiJ9",
"header": {
"alg": "HS256"
},
"signature": "u6_malicious_hmac_signature_using_public_key_here"
}The target application processes this token using the sequence described in the following diagram:
To construct the signature, the attacker obtains the application's public RSA key (which is frequently public-facing in JWT/OIDC endpoints) and uses it as a symmetric HMAC key to generate the HMAC-SHA256 signature over the payload. During verification, the library validates the protected header's RS256 algorithm, proceeds to overwrite the active algorithm with HS256, and performs symmetric HMAC verification using the public key. Because the attacker computed the HMAC signature with that same public key, the cryptographic check succeeds, granting arbitrary authorization.
A successful compromise of this verification logic allows an attacker to construct valid JWT payloads containing arbitrary claims. By spoofing identity tokens, an attacker can bypass authorization constraints, impersonate administrative accounts, and perform unauthorized operations within the affected infrastructure.
The CVSS v4.0 score is rated at 8.1, with the vector CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N/E:P. The attack complexity is evaluated as High because the exploit is only viable under specific environmental conditions, such as when the system is configured to verify tokens using a JSON Web Key Set (JWKSet) that mixes symmetric and asymmetric keys, or when developers invoke JWSVerifier directly without integrating the HeaderCheckerManager component.
If the application implements proper header checks independently or limits key sets to uniform cryptographic families, the probability of successful exploitation is mitigated. However, if the JWKSet contains mixed-type keys, the impact on integrity and confidentiality is critical.
To address this vulnerability, administrators and developers must upgrade the underlying web-token/jwt-library packages to the designated secure versions.
If an immediate dependency upgrade is not possible, apply code modifications to manually inspect the structure of incoming tokens prior to verification. Ensure that parameters defined in the unprotected header cannot overwrite protected options:
// Prevent verification if 'alg' or 'enc' is defined in unprotected headers
$unprotectedHeader = $jws->getHeader();
if (isset($unprotectedHeader['alg']) || isset($unprotectedHeader['enc'])) {
throw new SecurityException('Rejected: Critical parameters present in unprotected header.');
}Additionally, developers must separate key repositories. Do not combine symmetric secrets (HMAC) and asymmetric keys (RSA/EC) in the same JWKSet definition. This segregation ensures that the verification pipeline cannot access a public key when executing symmetric signature algorithms.
CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N/E:P| Product | Affected Versions | Fixed Version |
|---|---|---|
web-token/jwt-library web-token | < 3.4.10 | 3.4.10 |
web-token/jwt-library web-token | >= 4.0.0, < 4.0.7 | 4.0.7 |
web-token/jwt-library web-token | >= 4.1.0, < 4.1.7 | 4.1.7 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-345 (Active Verification of Cryptographic Signature) |
| Attack Vector | Network (AV:N) |
| CVSS v4.0 Score | 8.1 |
| Exploit Status | Proof of Concept |
| Vulnerability Type | Cryptographic Bypass / Algorithm Confusion |
| Affected Component | JWSVerifier and JWEDecrypter |
The software does not verify, or incorrectly verifies, the cryptographic signature for data.
A denial-of-service (DoS) and resource exhaustion vulnerability exists in Grav CMS prior to version 2.0.0. The package installer decompressor fails to validate ZIP archive limits before extraction, allowing authenticated administrators to cause disk exhaustion, inode exhaustion, or process termination.
CVE-2026-57173 (GHSA-hcwq-8wjf-3gcr) represents a critical resource allocation validation vulnerability in the vLLM inference engine. Prior to version 0.24.0, vLLM's multimodal chat completions pipeline failed to enforce maximum audio decode duration limits. Unauthenticated remote attackers can exploit this to perform an audio decompression bomb attack, causing massive memory allocations that trigger immediate system Out-Of-Memory (OOM) crashes and service termination.
Grav CMS before v2.0.1 contains a security bypass vulnerability in its blueprint validation logic. The XSS detection routine, Security::detectXss(), was executed on raw page contents prior to Twig engine processing. When Twig processing is enabled for editor-authored page content, an attacker can dynamically reconstruct harmful HTML elements, attributes, or protocols using string concatenation (e.g. `{{ 'on' ~ 'error' }}`). When compiled, the benign source converts into active XSS payloads, which are rendered to the client browser via raw filters. This vulnerability was resolved in version 2.0.1 by adding a post-render validation backstop.
An OAuth resource spoofing vulnerability in the rmcp crate prior to 2.0.0 allows a malicious Model Context Protocol (MCP) server to spoof protected resource metadata. By presenting metadata pointing to a legitimate resource and authorization server, the attacker can trick the client into completing the authentication flow and subsequently sending the authorized token back to the malicious server.
CVE-2026-63128 is a high-severity uncontrolled resource consumption vulnerability in the Model Context Protocol (MCP) official Rust SDK (the rmcp crate) prior to version 2.0.0. An unauthenticated attacker can exploit this vulnerability by sending malformed or mismatching handshake requests to the stateful Streamable HTTP server, causing persistent memory allocation without cleanup. This results in an unbounded memory leak and lock contention that ultimately leads to complete denial of service.
A cross-site scripting (XSS) vulnerability was identified in @nuxtjs/mdc prior to version 0.22.1. Gaps in the HTML/SVG attribute verification and URL protocol parsing allow unauthenticated remote attackers to bypass the application's sanitization routines. By embedding malicious SVG links or data-encoded iframe elements within Markdown, attackers can execute arbitrary JavaScript in the victim's browser context.