Skip to content

Conversation

@ArvinAlizadehGitHub
Copy link

Summary

This PR fixes issue #1051 where PyJWKClient with cache_keys=True serves potentially revoked keys indefinitely.

Problem

When cache_keys=True is enabled, PyJWKClient applies @lru_cache to the get_signing_key method. This caches keys permanently until LRU eviction or process restart. If an identity provider removes a key from their JWKS, applications continue accepting tokens signed with that key.

Solution

  • Replace lru_cache with TTL-aware caching
  • Keys now expire after the configured lifespan (default 300 seconds)
  • Maintains full backward compatibility with existing API
  • Uses same expiration logic as existing JWKSetCache

Changes

  • jwt/jwks_client.py: Replace lru_cache with TTL cache implementation
  • tests/test_jwks_client.py: Add test demonstrating the fix works

Testing

All existing tests pass. New test verifies that:

  • Old implementation serves cached keys indefinitely
  • New implementation properly rejects expired keys

Backward Compatibility

No breaking changes. All existing parameters work identically:

  • cache_keys=True still enables individual key caching
  • max_cached_keys still limits cache size
  • Performance characteristics maintained

Fixes #1051

Replace functools.lru_cache with TTL-aware cache to prevent
indefinite caching of potentially revoked signing keys.

- Remove lru_cache which cached keys forever
- Implement TTL-based individual key caching
- Keys now expire after configured lifespan
- Maintains backward compatibility with existing API
- Add test demonstrating fix works

Fixes jpadilla#1051
@ArvinAlizadehGitHub ArvinAlizadehGitHub force-pushed the fix-lru-cache-security-vulnerability branch from 4eaa549 to 11b357a Compare June 23, 2025 09:32
@auvipy auvipy requested a review from Copilot June 24, 2025 16:13
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR fixes issue #1051 by replacing the permanent lru_cache with a TTL-aware cache for individual keys, ensuring that revoked keys are no longer served indefinitely.

  • Replaces lru_cache with a TTL-based caching mechanism in jwt/jwks_client.py.
  • Adds tests in tests/test_jwks_client.py to verify key expiration and proper cache eviction.
  • Updates the CHANGELOG to document the change.

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
tests/test_jwks_client.py Adds new tests verifying that expired keys are rejected and cache eviction works correctly.
jwt/jwks_client.py Refactors caching logic by adding TTL-based caching methods and removing lru_cache.
CHANGELOG.rst Updates changelog to capture the new TTL-aware key caching fix.
Comments suppressed due to low confidence (1)

CHANGELOG.rst:12

  • The issue reference in the changelog appears to be inconsistent with the PR title (#1051). Please update the issue reference to #1051 if that is the correct identifier.
- Fix indefinite key caching in PyJWKClient by replacing lru_cache with TTL-aware cache in `#1070 <https://github.com/jpadilla/pyjwt/pull/1070>`__

auvipy and others added 4 commits June 24, 2025 22:17
@ArvinAlizadehGitHub
Copy link
Author

ArvinAlizadehGitHub commented Jul 7, 2025

Hi @auvipy (or @jpadilla)
The pre-commit checks are failing on an unrelated mypy error in jwt/algorithms.py line 796 (redundant type cast). This error exists in the main branch and is unrelated to my changes.

My changes only touch jwt/jwks_client.py and the test file. The failing mypy check is for code I didn't modify.

Could you advise if I should:

  1. Fix the unrelated mypy error in algorithms.py, or
  2. Have this merged as-is since it's a pre-existing issue?

The actual functionality tests are all passing - it's just the linting that's catching this pre-existing issue.

Would appreciate any feedback on next steps to move this forward. Happy to make any adjustments needed!

@github-actions github-actions bot added the stale Issues without activity for more than 60 days label Nov 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stale Issues without activity for more than 60 days

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PyJWKClient with cache_keys=True serves potentially revoked keys

2 participants