🛡️ CVE-2026-49852 — joserfc

🟠 CVSS 8.0 — High ✅ No Known Exploit CWE-1391 NVD
8.0
CVSS Score
0 Low4 Medium7 High9 Critical10

Description

joserfc: HS256/HS384/HS512 verify accepts empty/nil HMAC key (cross-language sibling of CVE-2026-45363)

Summary

joserfc.jwt.decode accepts attacker-forged HMAC-signed tokens when the

caller-supplied verification key is the empty string or None.

HMACAlgorithm.sign and HMACAlgorithm.verify in

[src/joserfc/_rfc7518/jws_algs.py:62-70](https://github.com/authlib/joserfc/blob/1ddca8f3c73ff47e3bc3ac06cb0c08a9535677ec/src/joserfc/_rfc7518/jws_algs.py#L62-L70) feed whatever

OctKey.get_op_key(...) produced into hmac.new(...), and OctKey.import_key

only emits a SecurityWarning when the raw key is shorter than 14 bytes

without rejecting zero-length input. Any application whose JWT secret is

sourced from an unset environment variable, an unset Redis / DB row, a key

finder fallback that returns "", or a Hash.new("")-style default verifies

attacker tokens forged with HMAC(key=b"", signing_input) because the

attacker trivially reproduces the same digest with no secret knowledge.

This is a cross-language sibling of jwt/ruby-jwt GHSA-c32j-vqhx-rx3x /

CVE-2026-45363 (HS256/HS384/HS512 verify accepted an empty/nil HMAC key,

filed 2026-05-13). ruby-jwt v3.2.0 added an ensure_valid_key! precondition

that rejects empty keys at both sign and verify entry; joserfc has no

equivalent. (The same primitive lives in the deprecated authlib.jose

module by the same maintainer; filing this advisory against joserfc

alongside a separate authlib advisory because the codebases are

independent shipping artifacts on PyPI.)

Affected versions

joserfc (PyPI) <= 1.6.7 (latest published release reproduces). No

patched release.

Privilege required

Unauthenticated. Any HTTP / RPC endpoint that calls joserfc.jwt.decode

with a verification key sourced from configuration is reachable. The

condition that makes the bug observable is operator-side: the configured

secret resolves to "" or None. Common patterns that produce this state

in production:

  • OctKey.import_key(os.environ.get("JWT_SECRET", ""))
  • A key finder callable that returns "" / None for an unknown kid
  • Default values like os.getenv("SECRET") or "", cfg.get("secret", "")
  • Database / Redis row lookup that returns "" for a missing row

Vulnerable code

[src/joserfc/_rfc7518/jws_algs.py:43-70](https://github.com/authlib/joserfc/blob/1ddca8f3c73ff47e3bc3ac06cb0c08a9535677ec/src/joserfc/_rfc7518/jws_algs.py#L43-L70):

```python

class HMACAlgorithm(JWSAlgModel):

SHA256 = hashlib.sha256

SHA384 = hashlib.sha384

SHA512 = hashlib.sha512

def __init__(self, sha_type, recommended=False):

self.name = f"HS{sha_type}"

self.description = f"HMAC using SHA-{sha_type}"

self.recommended = recommended

self.hash_alg = getattr(self, f"SHA{sha_type}")

self.algorithm_security = sha_type

def sign(self, msg: bytes, key: OctKey) -> bytes:

op_key = key.get_op_key("sign")

return hmac.new(op_key, msg, self.hash_alg).digest()

def verify(self, msg: bytes, sig: bytes, key: OctKey) -> bool:

op_key = key.get_op_key("verify")

v_sig = hmac.new(op_key, msg, self.hash_alg).digest()

return hmac.compare_digest(sig, v_sig)

```

[src/joserfc/_rfc7518/oct_key.py:52-63](https://github.com/authlib/joserfc/blob/1ddca8f3c73ff47e3bc3ac06cb0c08a9535677ec/src/joserfc/_rfc7518/oct_key.py#L52-L63):

```python

@classmethod

def import_key(cls, value, parameters=None, password=None) -> "OctKey":

key: OctKey = super(OctKey, cls).import_key(value, parameters, password)

if len(key.raw_value) < 14:

# https://csrc.nist.gov/publications/detail/sp/800-131a/rev-2/final

warnings.warn("Key size should be >= 112 bits", SecurityWarning)

return key

```

The < 14 check only warns; len(key.raw_value) == 0 falls through and is

returned to the caller. HMACAlgorithm.verify then calls

hmac.compare_digest(sig, hmac.new(b"", signing_input, sha256).digest()),

and Python's hmac.new(b"", ...) accepts the empty key.

Cross-language sibling of ruby-jwt's fix in [lib/jwt/jwa/hmac.rb](https://github.com/authlib/joserfc/blob/1ddca8f3c73ff47e3bc3ac06cb0c08a9535677ec/lib/jwt/jwa/hmac.rb):

```ruby

def ensure_valid_key!(key)

raise_verify_error!('HMAC key expected to be a String') unless key.is_a?(String)

raise_verify_error!('HMAC key cannot be empty') if key.empty?

end

```

invoked from both sign(signing_key:) and verify(verification_key:).

PyJWT landed an equivalent guard in 2.13.0 (HMACAlgorithm.prepare_key

raises InvalidKeyError("HMAC key must not be empty.") for len(key_bytes) == 0).

firebase/php-jwt rejects empty material in Key.__construct. jjwt enforces a

256-bit minimum in DefaultMacAlgorithm.validateKey. joserfc has the

strongest existing length-warning logic but stops at < 14 bytes warn

rather than == 0 reject.

How an empty JWT_SECRET reaches hmac.new

1. The application calls `joserfc.jwt.decode(value, key, algorithms

How this vulnerability can be exploited

This issue can be reached over the network, attack complexity is low, an attacker needs no privileges on the target. No user interaction is required. Rated impact: confidentiality none, integrity high, availability none.

Weakness class

CVE-2026-49852 is classified as CWE-1391: Use of Weak Credentials. The product uses weak credentials (such as a default key or hard-coded password) that can be calculated, derived, reused, or guessed by an attacker.

Affected software

CVE-2026-49852 is recorded against 2 packages.

  • joserfc (fixed in 1.6.8)
  • unknown

Timeline and source

Published on 2 July 2026 and last revised on 16 July 2026. No public exploit is currently recorded for this entry. Record sourced from NVD.

References

github.com (Web)
github.com (Web)
github.com (Package)
github.com (Web)

Details

Severity HIGH
CVSS Score 8.0
CVSS Vector CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N
CWE CWE-1391
Public Exploit ✅ No
Source NVD
Published 2026-07-02
Updated 2026-08-12
Modified 2026-07-16
Fix URL N/A

Affected Packages

Software From version Fixed in
joserfc 1.6.8
unknown

Site Security Check

Is joserfc part of your stack?

CVE-2026-49852 is rated CVSS 8.0 High. BotEraser scans your installation against known CVE records and tells you whether this vulnerability applies to the versions you actually run.

Scan My Site Free →

No credit card required  ·  Results in minutes

ⓘ Data Notice: The information presented above has been compiled from publicly available internet sources. Boteraser aggregates this data solely for informational purposes and does not independently classify, evaluate, or endorse any findings about the vulnerabilities listed. The accuracy and completeness of this information is the sole responsibility of the original publishers. Boteraser and its operators accept no liability for any decisions made based on this data.

Browse related advisories

All advisoriesCVECVE 2026