Skip to main content
VulnerabilityPublished Updated

CVE-2026-28498: Authlib · Fail-Open Cryptographic Verification in OIDC Hash Binding

Affects weaviate-cliSource GCVE Database

0
Compare

Not known to be exploited · CVSS 8.2 High : upgrade to 3.3.0_3 soon.

Data as of 30 Oct 2026, 07:30 UTC

CVSS 4.0 base score
8.2High
How severe the flaw is on the 0–10 CVSS scale.
Patch
Available – fixed in 3.3.0_3
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N

Exploitation evidence

  1. Disclosed: evidence found.

    CVE published 13 Aug 2026

  2. Detectable: no evidence on record.

    No public nuclei template indexed

  3. Weaponized: no evidence on record.

    No public exploit code indexed in Metasploit or Exploit-DB

  4. Exploited in the wild: no evidence on record.

    Not in CISA KEV and no source reports exploitation

  5. Observed by OffSeq Mirage: no evidence on record.

    No attack traffic recorded by OffSeq Mirage sensors

A missing step is not evidence of safety. Sources: cve.org (opens in a new tab), the Metasploit, Exploit-DB and nuclei-templates index as of 29 Oct 2026.

What to do

Upgrade weaviate-cli to 3.3.0_3.

Affected software

ProductAffectedFixed in
Homebrewweaviate-clipkg:brew/weaviate-cliOther threatsAffected
  • >=3.0.2 <3.3.0_3
Fixed in
  • 3.3.0_3

Check your own hosts for these packages with threat-finder (opens in a new tab), our free open-source scanner.

Description

## 1. Executive Summary A critical library-level vulnerability was identified in the **Authlib** Python library concerning the validation of OpenID Connect (OIDC) ID Tokens. Specifically, the internal hash verification logic (`_verify_hash`) responsible for validating the `at_hash` (Access Token Hash) and `c_hash` (Authorization Code Hash) claims exhibits a **fail-open** behavior when encountering an unsupported or unknown cryptographic algorithm. This flaw allows an attacker to bypass mandatory integrity protections by supplying a forged ID Token with a deliberately unrecognized `alg` header parameter. The library intercepts the unsupported state and silently returns `True` (validation passed), inherently violating fundamental cryptographic design principles and direct OIDC specifications. --- ## 2. Technical Details & Root Cause The vulnerability resides within the `_verify_hash(signature, s, alg)` function in `authlib/oidc/core/claims.py`: ```python def _verify_hash(signature, s, alg): hash_value = create_half_hash(s, alg) if not hash_value: # ← VULNERABILITY: create_half_hash returns None for unknown algorithms return True # ← BYPASS: The verification silently passes return hmac.compare_digest(hash_value, to_bytes(signature)) ``` When an unsupported algorithm string (e.g., `"XX999"`) is processed by the helper function `create_half_hash` in `authlib/oidc/core/util.py`, the internal `getattr(hashlib, hash_type, None)` call fails, and the function correctly returns `None`. However, instead of triggering a `Fail-Closed` cryptographic state (raising an exception or returning `False`), the `_verify_hash` function misinterprets the `None` return value and explicitly returns `True`. Because developers rely on the standard `.validate()` method provided by Authlib's `IDToken` class—which internally calls this flawed function—there is **no mechanism for the implementing developer to prevent this bypass**. It is a strict library-level liability. --- ## 3. Attack Scenario This vulnerability exposes applications utilizing Hybrid or Implicit OIDC flows to **Token Substitution Attacks**. 1. An attacker initiates an OIDC flow and receives a legitimately signed ID Token, but wishes to substitute the bound Access Token (`access_token`) or Authorization Code (`code`) with a malicious or mismatched one. 2. The attacker re-crafts the JWT header of the ID Token, setting the `alg` parameter to an arbitrary, unsupported value (e.g., `{"alg": "CUSTOM_ALG"}`). 3. The server uses Authlib to validate the incoming token. The JWT signature validation might pass (or be previously cached/bypassed depending on state), progressing to the claims validation phase. 4. Authlib attempts to validate the `at_hash` or `c_hash` claims. 5. Because `"CUSTOM_ALG"` is unsupported by `hashlib`, `create_half_hash` returns `None`. 6. Authlib's `_verify_hash` receives `None` and silently returns `True`. 7. **Result:** The application accepts the substituted/malicious Access Token or Authorization Code without any cryptographic verification of the binding hash. --- ## 4. Specification & Standards Violations This explicit fail-open behavior violates multiple foundational RFCs and Core Specifications. A secure cryptographic library **MUST** fail and reject material when encountering unsupported cryptographic parameters. **OpenID Connect Core 1.0** * **§ 3.2.2.9 (Access Token Validation):** "If the ID Token contains an `at_hash` Claim, the Client MUST verify that the hash value of the Access Token matches the value of the `at_hash` Claim." Silencing the validation check natively contradicts this absolute requirement. * **§ 3.3.2.11 (Authorization Code Validation):** Identically mandates the verification of the `c_hash` Claim. **IETF JSON Web Token (JWT) Best Current Practices (BCP)** * **RFC 8725 § 3.1.1:** "Libraries MUST NOT trust the signature without verifying it according to the algorithm... if validation fails, the token MUST be rejected." Authlib's implementation effectively "trusts" the hash when it cannot verify the algorithm. **IETF JSON Web Signature (JWS)** * **RFC 7515 § 5.2 (JWS Validation):** Cryptographic validations must reject the payload if the specified parameters are unsupported. By returning `True` for an `UnsupportedAlgorithm` state, Authlib violates robust application security logic. --- ## 5. Remediation Recommendation The `_verify_hash` function must be patched to enforce a `Fail-Closed` posture. If an algorithm is unsupported and cannot produce a hash for comparison, the validation **must** fail immediately. **Suggested Patch (`authlib/oidc/core/claims.py`):** ```python def _verify_hash(signature, s, alg): hash_value = create_half_hash(s, alg) if hash_value is None: # FAIL-CLOSED: The algorithm is unsupported, reject the token. return False return hmac.compare_digest(hash_value, to_bytes(signature)) ``` --- ## 6. Proof of Concept (PoC)

References

Community reviews

Loading reviews…