MEDIUM 4.2

CVE-2026-48522: PyJWT SSRF via Unvalidated URL Schemes in JWKS Fetching

PyJWT, a widely-used Python library for JSON Web Token handling, has a vulnerability in versions before 2.13.0 where it blindly accepts any URL scheme when fetching public key sets (JWKS). An attacker who can influence the URL used to fetch these keys—through JWT headers, configuration, or OAuth parameters—can trick the application into reading local files, attempting unusual protocol connections (FTP, data URIs), or in certain chained scenarios, forging valid tokens. The vulnerability requires specific conditions: the attacker must control the URL source, and token forgery scenarios require additional application-layer flaws like writable filesystem access.

Source data · NVD / CISA · public domain

CVSS
3.1 · 4.2 MEDIUM · CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N
Weaknesses (CWE)
CWE-441, CWE-918
Affected products
1 configuration(s)
Published / Modified
2026-05-28 / 2026-06-17

NVD description (verbatim)

PyJWT is a JSON Web Token implementation in Python. Prior to 2.13.0, PyJWKClient passes its uri argument directly to urllib.request.urlopen() which uses Python stdlib's default OpenerDirector registering HTTPHandler, HTTPSHandler, FTPHandler, FileHandler, and DataHandler. There is currently no documented option to restrict which schemes PyJWKClient will fetch. If an application's jku URL ingestion path accepts attacker-influenced URLs (e.g., from JWT header, configuration file, OAuth flow parameter), the attacker can cause PyJWKClient to read arbitrary local files via file:// (SSRF on local filesystem), cause PyJWKClient to attempt FTP / data-URI fetches (broader SSRF surface), or forge tokens that PyJWT verifies as valid. The library does not directly return non-HTTP(S) URI contents to the attacker; the chained "plant a JWKS to forge tokens" scenario described in the original report requires additional application-layer flaws (attacker write access to a filesystem path, untrusted jku derivation) that this fix does not address. This vulnerability is fixed in 2.13.0.

2 reference(s) · View on NVD →

SEC.co analysis · AI-assisted, reviewed against source

Technical summary

PyJWKClient in PyJWT prior to version 2.13.0 passes user-influenced jku (JWKS URI) arguments directly to urllib.request.urlopen() without URL scheme validation. Python's default OpenerDirector registers handlers for HTTP, HTTPS, FTP, FILE, and DATA schemes. An attacker-controlled jku can exploit this to trigger server-side request forgery (SSRF) against the local filesystem via file:// URIs, or attempt connections via alternative protocols. While PyJWT does not directly exfiltrate non-HTTP(S) content, the vulnerability creates a precondition for token forgery if the attacker also gains write access to a filesystem path that the application uses as a JWKS source or if the application derives the jku from an untrusted, attacker-controlled value without proper validation.

Business impact

Organizations running PyJWT <2.13.0 in applications that accept dynamic JWKS URLs face a chain-of-custody risk. If an attacker controls the jku URL source (e.g., via JWT header manipulation, configuration injection, or OAuth flow parameter tampering), they can perform local file reads on the server or, in conjunction with application-layer misconfigurations, potentially forge authentication tokens. This could lead to unauthorized access, privilege escalation, or information disclosure depending on the application's trust model and how it validates tokens. The impact is amplified in multi-tenant or plugin-based architectures where URL sources are less tightly controlled.

Affected systems

The vulnerability affects PyJWT versions prior to 2.13.0. Any Python application using PyJWT to verify JWT tokens with dynamically supplied or user-influenced JWKS URLs is potentially affected. This includes services leveraging PyJWT for OAuth 2.0 token validation, microservices using configurable key endpoints, or applications that accept jku claims from JWT headers without strict URL validation. Patched version 2.13.0 and later restrict URI schemes to HTTP and HTTPS.

Exploitability

Exploitation requires an attacker to influence the jku URL that PyJWKClient uses. The CVSS score of 4.2 (MEDIUM) reflects this constraint: the attack vector is network-based, but requires user interaction or application-level URL control. Basic SSRF against the local filesystem (file:// scheme) is straightforward once URL control is established. Token forgery scenarios require additional application vulnerabilities—such as the application treating a filesystem location as a trusted JWKS endpoint or the attacker having write access to that location. Public exploit code is not widely documented; successful exploitation depends on the specific application context and how strictly the jku source is validated.

Remediation

Upgrade PyJWT to version 2.13.0 or later, which implements URL scheme validation to allow only HTTP and HTTPS URIs. For applications that cannot upgrade immediately, implement strict URL validation on any jku value before passing it to PyJWKClient: whitelist allowed hosts, enforce HTTPS-only, and avoid accepting jku values from untrusted sources (JWT headers, user input, or unvalidated configuration). Use a deny-by-default approach for protocol schemes and validate the URL structure before instantiating PyJWKClient. Consider pinning JWKS endpoints to a static, internally controlled configuration rather than deriving them dynamically.

Patch guidance

Update PyJWT to version 2.13.0 or later. The fix introduces scheme validation that restricts urlopen() calls to HTTP and HTTPS protocols, blocking file://, ftp://, and data:// attempts. Verify the upgrade using your package manager (pip, poetry, etc.) and confirm the patched version in your requirements file or lock file. After patching, run regression tests on JWT verification flows to ensure no behavioral changes affect your authentication or token validation logic.

Detection guidance

Monitor for suspicious jku values in JWT tokens, particularly those containing non-HTTP(S) schemes (file://, ftp://, data://) or localhost/127.0.0.1 addresses if not expected. Log and alert on PyJWT exceptions related to urlopen() failures, especially when PyJWKClient attempts to fetch from unexpected URIs. Review application configuration for dynamic JWKS URLs and audit whether those values are validated before use. Search your codebase for instances where jku or JWKS endpoints are derived from user input, JWT claims, or configuration files without URL scheme validation. Implement telemetry on successful and failed JWKS fetch attempts to establish a baseline and detect anomalies.

Why prioritize this

Prioritize based on your application's architecture: HIGH if your application accepts dynamically supplied jku values (especially from JWT headers or external config), uses multi-tenant or plugin-based architectures, or runs in a shared hosting environment where local file access could expose sensitive data. MEDIUM if JWKS endpoints are statically configured and not user-influenced, or if your deployment already isolates filesystem access. LOW if you use PyJWT only for internal token verification with hardcoded, trusted endpoints and operate in a well-segmented network. Upgrade within 30 days if you fall into the HIGH category; within 90 days for MEDIUM; routine cycle for LOW.

Risk score, explained

The CVSS 3.1 score of 4.2 (MEDIUM) reflects: (1) network-accessible attack vector, (2) high attack complexity (requires attacker control over the jku source), (3) no authentication required but user interaction needed, (4) limited scope (local SSRF, not cross-boundary), (5) low confidentiality impact (local file reads only, no direct exfiltration), (6) low integrity impact (token forgery requires app-layer flaws). The score appropriately penalizes the requirement for application-level misconfigurations to achieve token forgery, but does not discount the real SSRF and information disclosure risk present in vulnerable deployments.

Frequently asked questions

What if my application uses PyJWT but does not accept dynamic JWKS URLs?

If your JWKS endpoint is hardcoded, static, and never derived from user input or JWT claims, your risk is significantly lower. However, you should still upgrade to 2.13.0 or later as a matter of defense-in-depth, especially if you plan to add dynamic URL handling in the future or if there is any possibility of configuration drift.

Does this vulnerability allow remote code execution?

No. The vulnerability is limited to local file reads (SSRF on the local filesystem) and, in chained scenarios with application-layer flaws, token forgery. It does not directly execute code on the server or allow arbitrary remote command execution.

Can an attacker exfiltrate files directly via this vulnerability?

PyJWT does not directly return the contents of file:// or ftp:// URIs to the attacker over the network. However, an attacker can use the SSRF to read local files and, if the application has other vulnerabilities (e.g., error messages that leak file contents or a writable JWKS path), chain those flaws to forge tokens or cause other harm. The vulnerability is a stepping stone, not a complete exploitation path by itself.

How do I know if my application is vulnerable?

Check your PyJWT version with pip show pyjwt or in your requirements/lock file. If it is earlier than 2.13.0 and your application either (1) accepts jku values from any source, (2) derives JWKS URLs from configuration or JWT claims, or (3) allows user-influenced URL parameters, you are at risk and should upgrade immediately.

This analysis is provided for informational and educational purposes. The information reflects the current understanding of CVE-2026-48522 based on available vendor documentation and technical research. Actual risk and impact vary based on individual application architecture, configuration, and threat model. Organizations should conduct their own risk assessment and penetration testing to determine the appropriate remediation timeline. No guarantee is made regarding the completeness or accuracy of detection logic or patch effectiveness in all environments. Consult official PyJWT security advisories and vendor documentation for authoritative guidance. Source: NVD (public-domain), retrieved 2026-07-07. Analysis generated by SEC.co (claude-haiku-4-5).