Skip to content

Conversation

@renovate
Copy link
Contributor

@renovate renovate bot commented Sep 22, 2025

This PR contains the following updates:

Package Change Age Confidence
authlib ==1.6.1 -> ==1.6.5 age confidence

GitHub Vulnerability Alerts

CVE-2025-59420

Summary

Authlib’s JWS verification accepts tokens that declare unknown critical header parameters (crit), violating RFC 7515 “must‑understand” semantics. An attacker can craft a signed token with a critical header (for example, bork or cnf) that strict verifiers reject but Authlib accepts. In mixed‑language fleets, this enables split‑brain verification and can lead to policy bypass, replay, or privilege escalation.

Affected Component and Versions

  • Library: Authlib (JWS verification)
  • API: authlib.jose.JsonWebSignature.deserialize_compact(...)
  • Version tested: 1.6.3
  • Configuration: Default; no allowlist or special handling for crit

Details

RFC 7515 (JWS) §4.1.11 defines crit as a “must‑understand” list: recipients MUST understand and enforce every header parameter listed in crit, otherwise they MUST reject the token. Security‑sensitive semantics such as token binding (e.g., cnf from RFC 7800) are often conveyed via crit.

Observed behavior with Authlib 1.6.3:

  • When a compact JWS contains a protected header with crit: ["cnf"] and a cnf object, or crit: ["bork"] with an unknown parameter, Authlib verifies the signature and returns the payload without rejecting the token or enforcing semantics of the critical parameter.
  • By contrast, Java Nimbus JOSE+JWT (9.37.x) and Node jose v5 both reject such tokens by default when crit lists unknown names.

Impact in heterogeneous fleets:

  • A strict ingress/gateway (Nimbus/Node) rejects a token, but a lenient Python microservice (Authlib) accepts the same token. This split‑brain acceptance bypasses intended security policies and can enable replay or privilege escalation if crit carries binding or policy information.

Proof of Concept (PoC)

This repository provides a multi‑runtime PoC demonstrating the issue across Python (Authlib), Node (jose v5), and Java (Nimbus).

Prerequisites

  • Python 3.8+
  • Node.js 18+
  • Java 11+ with Maven

Setup

Enter the directory authlib-crit-bypass-poc & run following commands.

make setup
make tokens

Tokens minted

  • tokens/unknown_crit.jwt with protected header:
    { "alg": "HS256", "crit": ["bork"], "bork": "x" }
  • tokens/cnf_header.jwt with protected header:
    { "alg": "HS256", "crit": ["cnf"], "cnf": {"jkt": "thumb-42"} }

Reproduction

Run the cross‑runtime demo:

make  demo

Expected output for each token (strict verifiers reject; Authlib accepts):

For tokens/unknown_crit.jwt:

Strict(Nimbus): REJECTED (unknown critical header: bork)
Strict(Node jose): REJECTED (unrecognized crit)
Lenient(Authlib): ACCEPTED -> payload={'sub': '123', 'role': 'user'}

For tokens/cnf_header.jwt:

Strict(Nimbus): REJECTED (unknown critical header: cnf)
Strict(Node jose): REJECTED (unrecognized crit)
Lenient(Authlib): ACCEPTED -> payload={'sub': '123', 'role': 'user'}

Environment notes:

  • Authlib version used: 1.6.3 (from PyPI)
  • Node jose version: ^5
  • Nimbus JOSE+JWT version: 9.37.x
  • HS256 secret is 32 bytes to satisfy strict verifiers: 0123456789abcdef0123456789abcdef

Impact

  • Class: Violation of JWS crit “must‑understand” semantics; specification non‑compliance leading to authentication/authorization policy bypass.
  • Who is impacted: Any service that relies on crit to carry mandatory security semantics (e.g., token binding via cnf) or operates in a heterogeneous fleet with strict verifiers elsewhere.
  • Consequences: Split‑brain acceptance (gateway rejects while a backend accepts), replay, or privilege escalation if critical semantics are ignored.

References

  • RFC 7515: JSON Web Signature (JWS), §4.1.11 crit
  • RFC 7800: Proof‑of‑Possession Key Semantics for JWTs (cnf)

CVE-2025-61920

Summary
Authlib’s JOSE implementation accepts unbounded JWS/JWT header and signature segments. A remote attacker can craft a token whose base64url‑encoded header or signature spans hundreds of megabytes. During verification, Authlib decodes and parses the full input before it is rejected, driving CPU and memory consumption to hostile levels and enabling denial of service.

Impact

  • Attack vector: unauthenticated network attacker submits a malicious JWS/JWT.

  • Effect: base64 decode + JSON/crypto processing of huge buffers pegs CPU and allocates large amounts of RAM; a single request can exhaust service capacity.

  • Observed behaviour: on a test host, the legacy code verified a 500 MB header, consuming ~4 GB RSS and ~9 s CPU before failing.

  • Severity: High. CVSS v3.1: AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H (7.5).

Affected Versions
Authlib ≤ 1.6.3 (and earlier) when verifying JWS/JWT tokens. Later snapshots with 256 KB header/signature limits are not affected.

Proof of concept

Local demo (do not run against third-party systems):
Download jws_segment_dos_demo.py the PoC in direcotry authlib/
Run following Command

python3 jws_segment_dos_demo.py --variant both --sizes "500MB" --fork-per-case

Environment: Python 3.13.6, Authlib 1.6.4, Linux x86_64, CPUs=8
Sample output: Refined
image

The compilation script prints separate “[ATTACKER]” (token construction) and “[SERVER]” (Authlib verification) RSS deltas so defenders can distinguish client-side preparation from server-side amplification. Regression tests authlib/tests/dos/test_jose_dos.py further capture the issue; the saved original_util.py/original_jws.py reproductions still accept the malicious payload.

Remediation

  • Apply the upstream patch that introduces decoded size limits:

  • MAX_HEADER_SEGMENT_BYTES = 256 KB

  • MAX_SIGNATURE_SEGMENT_BYTES = 256 KB

  • Enforce Limits in authlib/jose/util.extract_segment and _extract_signature.

  • Deploy the patched release immediately.

  • For additional defence in depth, reject JWS/JWT inputs above a few kilobytes at the proxy or WAF layer, and rate-limit verification endpoints.

Workarounds (temporary)

  • Enforce input size limits before handing tokens to Authlib.

  • Use application-level throttling to reduce amplification risk.

Resources

  • Demo script: jws_segment_dos_demo.py

  • Tests: authlib/tests/dos/test_jose_dos.py

  • OWASP JWT Cheat Sheet (DoS guidance)

CVE-2025-62706

Summary

Authlib’s JWE zip=DEF path performs unbounded DEFLATE decompression. A very small ciphertext can expand into tens or hundreds of megabytes on decrypt, allowing an attacker who can supply decryptable tokens to exhaust memory and CPU and cause denial of service.

Details

  • Affected component: Authlib JOSE, JWE zip=DEF (DEFLATE) support.
  • In authlib/authlib/jose/rfc7518/jwe_zips.py, DeflateZipAlgorithm.decompress calls zlib.decompress(s, -zlib.MAX_WBITS) without a maximum output limit. This permits unbounded expansion of compressed payloads.
  • In the JWE decode flow (authlib/authlib/jose/rfc7516/jwe.py), when the protected header contains "zip": "DEF", the library routes the decrypted ciphertext into the decompress method and assigns the fully decompressed bytes to the plaintext field before returning it. No streaming limit or quota is applied.
  • Because DEFLATE achieves extremely high ratios on highly repetitive input, an attacker can craft a tiny zip=DEF ciphertext that inflates to a very large plaintext during decrypt, spiking RSS and CPU. Repeated requests can starve the process or host.

Code references (from this repository version):

  • authlib/authlib/jose/rfc7518/jwe_zips.pyDeflateZipAlgorithm.decompress uses unbounded zlib.decompress.
  • authlib/authlib/jose/rfc7516/jwe.py – JWE decode path applies zip_.decompress(msg) when zip=DEF is present in the header.

Contrast: The joserfc project guards zip=DEF decompression with a fixed maximum (256 KB) and raises ExceededSizeError if output would exceed this limit, preventing the bomb. Authlib lacks such a guard in this codebase snapshot.

PoC

Environment: Python 3.10+ inside a venv; Authlib installed editable from this repository so source changes are visible. The PoC script demonstrates both a benign and a compressible-bomb payload and prints wall/CPU time, RSS, and size ratios.

  1. Create venv and install Authlib (editable):
    Set current directory to /authlib
    Download jwe_deflate_dos_demo.py in /authlib
python3 -m venv .venv
.venv/bin/pip install --upgrade pip
.venv/bin/pip install -e .
  1. Run the PoC (included in this repo):
.venv/bin/python /authlib/jwe_deflate_dos_demo.py --size 50 --max-rss-mb 2048

Sample output (abridged):

LOCAL TEST ONLY – do not send to third-party systems.
Runtime: Python 3.13.6 / Authlib 1.6.4 / zip=DEF via A256GCM
[CASE] normal    plaintext=13B  ciphertext=117B decompressed=13B  wall_s=0.000 cpu_s=0.000 peak_rss_mb=31.0  ratio=0.1
[CASE] malicious plaintext=50MB ciphertext=~4KB decompressed=50MB wall_s=~2.3  cpu_s=~2.2  peak_rss_mb=800+  ratio=12500+

The second case shows the decompression spike: a few KB of ciphertext forces allocation and processing of ~50 MB during decrypt. Repeated requests can quickly exhaust available memory and CPU.

Reproduction notes:

  • Algorithm: alg=dir, enc=A256GCM, header includes { "zip": "DEF" }.
  • The PoC uses a 32‑byte local symmetric key and a highly compressible payload ("A" * N).
  • Increase --size to stress memory; the --max-rss-mb flag helps avoid destabilizing the host during testing.

Impact

  • Effect: Denial of service (memory/CPU exhaustion) during JWE decrypt of zip=DEF tokens.
  • Who is impacted: Any service that uses Authlib to decrypt JWE tokens with zip=DEF and where an attacker can submit tokens that will be successfully decrypted (e.g., shared dir key, token reflection, or compromised/abused issuers).
  • Confidentiality/Integrity: No direct C/I impact; availability impact is high.

Severity (CVSS v3.1)

Base vector (typical shared‑secret scenario where the attacker must produce a decryptable token):

  • CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H → 6.5 (MEDIUM)

Rationale:

  • Network‑reachable (AV:N), low complexity (AC:L), no user interaction (UI:N), scope unchanged (S:U).
  • Attacker must hold or gain ability to mint a decryptable token for the target (PR:L) — common with alg=dir and shared keys across services.
  • No confidentiality or integrity loss (C:N/I:N); availability is severely impacted (A:H) due to decompression expansion.
    If arbitrary unprivileged parties can submit JWEs that will be decrypted (PR:N), the base vector becomes:
  • CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H → 7.5 (HIGH)

Mitigations / Workarounds

  • Reject or strip zip=DEF for inbound JWEs at the application boundary until a fix is available.
  • Fork and add a bounded decompression guard (e.g., zlib.decompress(..., max_length) via decompressobj().decompress(data, MAX_SIZE)), returning an error when output exceeds a safe limit.
  • Enforce strict maximum token sizes and fail fast on oversized inputs; combine with rate limiting.

Remediation Guidance (for maintainers)

  • Mirror joserfc’s approach: add a conservative maximum output size (e.g., 256 KB by default) and raise a specific error when exceeded; document a controlled way to raise this ceiling for trusted environments.
  • Consider streaming decode with chunked limits to avoid large single allocations.

References

  • Authlib source: authlib/authlib/jose/rfc7518/jwe_zips.py, authlib/authlib/jose/rfc7516/jwe.py

Release Notes

authlib/authlib (authlib)

v1.6.5

Compare Source

What's Changed

  • Add a request param to RFC7591 generate_client_info and generate_client_secret methods by @​azmeuk in #​825
  • feat: support list params in prepare_grant_uri by @​lisongmin in #​827
  • chore(deps): bump SonarSource/sonarqube-scan-action from 5 to 6 in /.github/workflows by @​dependabot[bot] in #​828
  • fix(jose): add max size for JWE zip=DEF decompression by @​lepture in #​830

New Contributors

Full Changelog: authlib/authlib@v1.6.4...v1.6.5

v1.6.4

Compare Source

What's Changed

New Contributors

Full Changelog: authlib/authlib@v1.6.3...v1.6.4

v1.6.3: Version 1.6.3

Compare Source

What's Changed

Full Changelog: authlib/authlib@v1.6.2...v1.6.3

v1.6.2: Version 1.6.2

Compare Source

What's Changed

Full Changelog: authlib/authlib@v1.6.1...v1.6.2


Configuration

📅 Schedule: Branch creation - "" in timezone UTC, Automerge - At any time (no schedule defined).

🚦 Automerge: Enabled.

Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@renovate renovate bot added the dependencies Pull requests that update a dependency file label Sep 22, 2025
@github-actions github-actions bot requested a review from mobious999 September 22, 2025 17:44
@renovate renovate bot changed the title chore(deps): update dependency authlib to v1.6.4 [security] chore(deps): update dependency authlib to v1.6.5 [security] Oct 10, 2025
@renovate renovate bot force-pushed the renovate/pypi-authlib-vulnerability branch from dbdcd0a to 63f5ddc Compare October 10, 2025 20:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AnyChange dependencies Pull requests that update a dependency file release root source

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants