Skip to content

[Security] python-jose ignores the JWS crit header (RFC 7515) #413

Description

@kpatsakis

Summary

RFC 7515 §4.1.11 requires that a JWS recipient that does not understand and process every Header Parameter named in the crit (Critical) list must reject the JWS.

RFC Requirement

RFC 7515 §4.1.11:

The "crit" (critical) Header Parameter indicates that extensions to
this specification and/or [JWA] are being used that MUST be
understood and processed. Its value is an array listing the Header
Parameter names present in the JOSE Header that use those extensions.
If any of the listed extension Header Parameters are not understood
and supported by the recipient, then the JWS is invalid. Producers
MUST NOT include Header Parameter names defined by this specification
or [JWA] for use with JWS, duplicate names, or names that do not
occur as Header Parameter names within the JOSE Header in the "crit"
list.

Evidence

The token has a valid HS256 signature; its only deviation is a crit header naming an extension parameter (myparam) that no general-purpose verifier understands:

header  = {"alg":"HS256","typ":"JWT","crit":["myparam"],"myparam":1}
payload = {"sub":"attacker","exp":<future>}        # signed with a shared 32-byte HMAC key

Affected version

python-jose 3.5.0 (not tested in older versions)

PoC

Tested on Ubuntu 26.04 LTS, Linux 7.0.0-22-generic, Python 3.14.4, and python-jose 3.5.0

import jose.jwt, base64, hmac, hashlib, json, time
SECRET=b"0123456789abcdef0123456789abcdef"
b64u=lambda b: base64.urlsafe_b64encode(b).rstrip(b"=").decode()
seg=lambda o: b64u(json.dumps(o,separators=(",",":")).encode())
h=seg({"alg":"HS256","typ":"JWT","crit":["myparam"],"myparam":1})
p=seg({"sub":"attacker","exp":int(time.time())+3600})
s=b64u(hmac.new(SECRET,f"{h}.{p}".encode(),hashlib.sha256).digest())
print(jose.jwt.decode(f"{h}.{p}.{s}", SECRET, algorithms=["HS256"])) 

Impact

An attacker can craft a signed token with a critical header (for example, bork or cnf) that strict verifiers reject but python-jose accepts

  • Security policy bypass when crit carries enforcement semantics
    (MFA, token binding, scope restrictions)
  • Token binding bypass

Similar CVEs

The same issue has been reported and patched in other libraries:

CWE

  • CWE-345: Insufficient Verification of Data Authenticity
  • CWE-863: Incorrect Authorization

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions