ruby-jwt CVE-2026-45363
CRITICALAttack ChainAIDerived
Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain
-
AccessIdentify Ruby app accepting JWTs
-
DeliveryProbe for HS256 acceptance and key-lookup miss behavior
-
ExploitCraft token signed with empty-string HMAC key
-
ExecutionSubmit forged JWT to authenticated endpoint
-
PersistLibrary verifies under empty key
-
ImpactImpersonate arbitrary user or role
Vulnerability Assessment
| Weakness |
CWE
OWASP Top 10:2025
A07:2025 - Authentication Failures
ASVS 5.0
V6 - Authentication Authentication mechanism validation
MITRE ATT&CK
2 techniques across 2 tactics: Defense Evasion, Initial Access The technique list with ATT&CK links and the kill-chain view is part of the Basic plan and up. |
| Exploitation Conditions | Exploitation requires the target application to be running ruby-jwt < 3.2.0 with HS256/HS384/HS512 verification AND to supply an empty string ('') or nil as the verification key - either as the positional argument to JWT.decode, as the return value of a keyfinder block, or via the key_finder: argument to JWT::EncodedToken#verify_signature!. Concretely vulnerable patterns named in the advisory: |
| Impact | CVSS 7.4 (AV:N/AC:H/PR:N/UI:N/C:H/I:H/A:N) reflects high confidentiality and integrity impact against unauthenticated network attackers, with AC:H acknowledging that exploitability depends on a specific application-side condition (the verification key resolving to '' or nil). No EPSS, KEV, or POC data was provided, so per policy this is treated as no public exploit identified at time of analysis - not a contradiction of the high CVSS, but a signal that mass exploitation is not yet observed. Real-world risk is bimodal: applications passing a non-empty static secret are unaffected, but those using Redis-backed kid lookups ( |
| Exploit ScenarioDerived | An attacker crafts a JWT with header |
Get an e-mail when this CVE is exploited, patched or re-scored. Free account.
Alert meAnalysisAIv1 – May 18, 2026
Authentication bypass in the ruby-jwt gem (versions < 3.2.0) allows remote attackers to forge valid HS256/HS384/HS512 tokens when an application supplies an empty string or nil as the verification key. Because OpenSSL::HMAC.digest happily computes a digest under an empty key and JWT::JWA::Hmac coerces nil to '' without validating, any application whose key lookup degrades to '' (common with Redis misses, ORM string defaults, or ENV['SECRET'] || '' patterns) will accept attacker-signed tokens. No public exploit identified at time of analysis, but the vendor advisory (GHSA-c32j-vqhx-rx3x) and the v3.2.0 patch confirm the issue and the trivial forgery primitive.
RemediationAI
Upgrade the jwt gem to the vendor-released patch version 3.2.0 or later (gem 'jwt', '>= 3.2.0' in the Gemfile, then bundle update jwt); the fix is commit db560b769a07bd9724e77ff505011ac01872106f, which adds an ensure_valid_key! check that rejects non-String and empty keys before any HMAC computation. Until the upgrade can be deployed, enable the existing enforce_hmac_key_length option (off by default) which rejects short keys including '', though this changes behavior for any code that legitimately relied on short keys for testing. Audit all JWT.decode and EncodedToken#verify_signature! call sites to ensure the key source cannot degrade to '' or nil - fix patterns such as redis.get(...).to_s, ENV['SECRET'] || '', ORM string columns with default: '', Hash.new('') lookups, and [primary, fallback]-with-nil arrays by raising on missing keys instead of substituting an empty string. See the GHSA advisory at https://github.com/jwt/ruby-jwt/security/advisories/GHSA-c32j-vqhx-rx3x for full details.
Affected Packages
Source: OSV (Open Source Vulnerabilities)
Affects your stack
Affects 1 package in rubygems
Checking this CVE against your own stacks and servers is part of the Basic plan and up.
Technical ContextAI · show details
ruby-jwt is the canonical Ruby implementation of RFC 7519 JSON Web Tokens, widely used by Rails and Sinatra applications for session and API authentication. The root cause maps to CWE-287 (Improper Authentication): JWT::JWA::Hmac#verify accepted an empty verification key, and signing_key ||= '' silently substituted '' for nil before delegating to OpenSSL::HMAC.digest. On OpenSSL 3.0 the underlying call previously raised an EVP_PKEY_new_mac_key malloc failure, which the library caught and converted to a decode error - an accidental defense - but on OpenSSL ≥ 3.5 that call no longer raises, removing the implicit guard. JWT::Decode#find_key further compounded the issue by rejecting only literal nil and empty arrays, so a keyfinder block returning '' was treated as a valid key. The CPE pkg:rubygems/jwt identifies the affected package, and the fix introduces an ensure_valid_key! helper that rejects non-String and empty keys before any HMAC computation.
Know when OpenSSL gets its next vulnerability
- Watch products and get an email when something new is published
- Check this CVE against your own stack and servers
- Exploit and PoC references, threat intelligence from 22 sources
No credit card · 7-day full trial
Severity by source
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N
AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N
Primary rating from Vendor (https://github.com/jwt/ruby-jwt).
CVSS VectorVendor: https://github.com/jwt/ruby-jwt
Lifecycle Timeline
2DescriptionCVE.org
JWT.decode(token, '', true, algorithm: 'HS256') accepts an attacker-forged token. OpenSSL::HMAC.digest('SHA256', '', payload) returns a valid digest under an empty key, and no raise InvalidKeyError if key.empty? precondition exists in the HMAC algorithm.
JWT.decode(token, "", true, algorithm: 'HS256')
-> JWA::Hmac.verify(verification_key: "", ...)
-> OpenSSL::HMAC.digest('SHA256', "", signing_input) == signatureThe same path is reached when a keyfinder block or key_finder: argument returns "", nil, or an array containing nil for an unknown key. JWT::Decode#find_key only rejects literal nil and empty arrays, and JWT::JWA::Hmac silently coerces nil to "" (signing_key ||= '') before signing.
JWT.decode(token, nil, true, algorithms: ['HS256']) { |_h| "" }
-> find_key returns ""
# "" && !Array("").empty? == true
-> JWA::Hmac.verify(verification_key: "", ...)
-> verifiesCommon application patterns that produce the unsafe value: redis.get("kid:#{kid}").to_s, ORM string columns with default: '', ENV['SECRET'] || '', Hash.new('') lookups, [primary, fallback] where fallback may be nil. Applications passing a non-empty static key:, or whose keyfinder returns nil / raises on miss, are not affected.
The existing enforce_hmac_key_length option would block this but defaults to false. On OpenSSL ≥ 3.5 the empty-key HMAC.digest call no longer raises, so the OpenSSL-3.0 rescue in JWA::Hmac#sign does not fire.
Affects HS256/HS384/HS512 via both JWT.decode (positional key and block keyfinder) and JWT::EncodedToken#verify_signature!(key_finder:)
Executive ViewAI
The ruby-jwt library (versions prior to 3.2.0) contains an authentication bypass vulnerability allowing remote attackers to forge cryptographic tokens used for API authentication and session management. Applications relying on this library-particularly those with empty or nil key fallback patterns (common in Redis caching, ORM defaults, and environment variable fallbacks)-face significant risk of unauthorized system access and data exposure. This affects any Ruby-based service using vulnerable versions for token verification.
Apply vendor patch.
Threat Intelligence Overview
How this decision was reached
The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.
What every action level means
SSVC AssessmentENISA
Priority Score
Attack Technique
Authentication bypass attacks exploit flaws in the verification mechanisms that control access to systems and applications.
Affected Products (CPE)CVE.org
The (1) TLS and (2) DTLS implementations in OpenSSL 1.0.1 before 1.0.1g do not properly handle Heartbeat Extension packe
In order to decrypt SM2 encrypted data an application is expected to call the API function EVP_PKEY_decrypt(). Rated cri
The dtls1_reassemble_fragment function in d1_both.c in OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0
OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph
The SSLv2 protocol, as used in OpenSSL before 1.0.1s and 1.0.2 before 1.0.2g and other products, requires a server to se
The ssl3_get_key_exchange function in s3_clnt.c in OpenSSL before 0.9.8zd, 1.0.0 before 1.0.0p, and 1.0.1 before 1.0.1k
In addition to the c_rehash shell command injection identified in CVE-2022-1292, further circumstances where the c_rehas
The TLS protocol 1.2 and earlier, when a DHE_EXPORT ciphersuite is enabled on a server but not on a client, does not pro
The SSL protocol 3.0, as used in OpenSSL through 1.0.1i and other products, uses nondeterministic CBC padding, which mak
The AES-NI implementation in OpenSSL before 1.0.1t and 1.0.2 before 1.0.2h does not consider memory allocation during a
The X509_verify_cert function in crypto/x509/x509_vfy.c in OpenSSL 1.0.1n, 1.0.1o, 1.0.2b, and 1.0.2c does not properly
A buffer overrun can be triggered in X.509 certificate verification, specifically in name constraint checking. Rated hig
GHSA-c32j-vqhx-rx3x
NVD
CVE.org
EPSS
VulDB
Exploit-DB