Skip to content

Bump PyJWT to 2.15.1 and test real token validation - #11

Merged
warheart1984-ctrl merged 1 commit into
mainfrom
fix/pyjwt-2.15
Oct 2, 2026
Merged

warheart1984-ctrl merged 1 commit into
mainfrom
fix/pyjwt-2.15

Conversation

@warheart1984-ctrl

Copy link
Copy Markdown
Owner

What

  • PyJWT[crypto] goes from 2.10.1 to 2.15.1. 2.15.1 is the first release clear of all 14 open Dependabot alerts on main (1 critical, 4 high, 8 moderate, 1 low). All 14 are PyJWT.
  • tests/test_oauth_tokens.py is the first real coverage of validate_access_token.

How much of this applied to us

Not all of it, and it's worth being precise:

  • The critical alert and the HS256 key-confusion highs didn't apply. These are a public key accepted as an HMAC secret in PEM, CRLF-mutated PEM, or DER form. They need a decode that allows mixed algorithm families. validate_access_token passes algorithms=["RS256", "ES256"], so an HS256 token is refused before any key handling. The new tests confirm these forgeries fail on both 2.10.1 and 2.15.1.
  • The PyJWKClient advisories did apply. validate_access_token hands an attacker-supplied token to PyJWKClient.get_signing_key_from_jwt before any signature check. That's where unbounded JWKS re-fetches on unknown kid values happen, along with the pre-verification RecursionError DoS. On a public OAuth deployment (render.yaml), anyone can send those tokens.
  • Other moderate alerts are hardening. These cover the scheme allowlist, redirects, the PEM ReDoS, and revocation-bypass via non-canonical signatures. They're fixed by the upgrade whether or not today's code reaches them.

Tests

The existing OAuth tests replace validate_access_token with a fake, so the real verification path had no coverage. The new tests drive it with RS256 tokens and an in-memory JWKS, through the real PyJWKClient (only fetch_data is stubbed). They cover:

  • Accepted: a valid token gives a principal with its subject, scopes and issuer.
  • Rejected with 401: expired, wrong audience, wrong issuer, a different key under the same kid, missing sub, alg=none, and garbage.
  • Rejected with 403: missing the required scope.
  • Rejected with 401, algorithm confusion: HS256 signed with the public key as PEM, CRLF PEM, and DER.

Results:

  • Full suite, 2.15.1: 252 passed and 2 skipped (the embedding floors, without the extra) on both Python 3.11 and 3.12.
  • The 11 new tests: pass on 2.15.1, and also on 2.10.1. That's expected, given the algorithm allowlist. They guard this path against regressions; they don't demonstrate the upgrade's fixes, which live in PyJWKClient internals.

After merge

The running local service uses API-key auth, not OAuth, so it never reaches this code. It'll pick up the new version on its next reinstall. The Render deployment should be redeployed.

🤖 Generated with Claude Code

PyJWT 2.10.1 carries 14 open advisories (1 critical, 4 high). 2.15.1 is the
first release clear of all of them.

Not all apply here. validate_access_token decodes with
algorithms=["RS256", "ES256"], so the HS256 key-confusion forgeries (the
critical one included) need a mixed algorithm list this code does not use;
the new tests confirm they fail on both versions. What does apply is
PyJWKClient handling attacker tokens before any signature check: JWKS
re-fetches on unknown `kid` values and the RecursionError in
get_signing_key_from_jwt.

The existing OAuth tests replace validate_access_token with a fake, so the
real verification path had no coverage. tests/test_oauth_tokens.py drives it
with RS256 tokens and an in-memory JWKS through the real PyJWKClient: valid,
expired, wrong audience/issuer, another key under the same kid, missing
sub, missing scope (403), HS256 signed with the public key as PEM, CRLF PEM
and DER, alg=none, and garbage.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your trial has ended. Reactivate Greptile to resume code reviews.

@warheart1984-ctrl
warheart1984-ctrl merged commit d5157ba into main Oct 2, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant