Jun 18, 2026·7 min read·6 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.
An authentication bypass in the SiYuan personal knowledge management system before version 3.7.0 exposes a dynamic icon rendering endpoint. This endpoint processes client-supplied Go template directives. By submitting a crafted request, an unauthenticated remote attacker can leverage registered database template functions to execute arbitrary read-only SQL queries and exfiltrate workspace contents.
CVE-2026-54069 is a critical authentication bypass vulnerability in the SiYuan Note personal knowledge management system. The flaw is located in the HTTP server's middleware handling API authorization, which unconditionally trusts requests carrying a 'chrome-extension://' scheme in the Origin HTTP header, granting administrative access without validating API tokens.
CVE-2026-54089 is a critical authentication bypass vulnerability in File Browser affecting instances configured with proxy-based authentication. An unauthenticated remote attacker with direct network access can impersonate arbitrary users or register new accounts by spoofing configured HTTP headers.
The malicious Cargo package 'exploration' was uploaded to the crates.io registry. During compilation or package import, the crate executes code designed to establish an outbound TCP/HTTP connection, download an external second-stage binary, and execute the binary locally on the host machine. This creates an unauthenticated remote code execution vector impacting developer environments and continuous integration pipelines.
CVE-2026-54088 is a critical command injection vulnerability in File Browser prior to version 2.63.6. When Hook Authentication is enabled, the application interpolates unsanitized credentials into a shell command, allowing unauthenticated remote code execution.
An authenticated remote code execution vulnerability exists in NotrinosERP (versions up to and including 1.0.0) within the Human Resource Management (HRM) module. Users with employee management permissions can upload arbitrary file types, including PHP scripts, which are written directly to a web-accessible directory. This allows for arbitrary code execution in the context of the web-server user.