JKUFactory and X5UFactory follow HTTP redirects when they fetch a key set

Abierto
#762 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
4/5
Tiempo estimado
3-5 días
Aptitud para principiantes
48/100
Tipo de issue
Error
Claridad
Bastante claro
Estado de actividad
Activo
Stack tecnológico
php, symfony

Línea de trabajo

Read the key set documentation and the security recommendations, then inspect UrlKeySetFactory::sendSymfonyRequest() on 4.2 or UrlKeySetFactoryTrait::sendRequest() on 4.3, along with JKUFactory::loadFromUrl() and X5UFactory::loadFromUrl(). Decide how the affected release should handle redirects and document safe URL use; done means the guidance covers the redirect risk and the workaround, without implying that URLs from tokens are safe to load.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

enhancement
Version(s) affected

3.3.0 to 3.4.12, 4.0.0 to 4.0.8, 4.1.0 to 4.1.10, 4.2.0 to 4.2.5, 4.3.x-dev (with a Symfony HTTP client; on 3.4.x the PSR-18 path does whatever the PSR-18 client does)

Description

JKUFactory::loadFromUrl() and X5UFactory::loadFromUrl() send their request with the headers option only (UrlKeySetFactory::sendSymfonyRequest() up to 4.2, UrlKeySetFactoryTrait::sendRequest() on 4.3). The redirect policy of the client therefore applies. With Symfony's defaults (HttpClient::create(), the framework's http_client service), up to 20 redirects are followed, to any host and from https to http, and the body of the last response is used as the key set. The final URL is never compared with the requested one.

As a result:

  • the host behind a configured jku/x5u URL can make the application server send a GET request to an address of its choice, such as a loopback or internal service. The answer does not come back to that host. Headers passed to loadFromUrl() are forwarded to the redirect target, except Authorization and Cookie, which Symfony drops when the host changes;
  • an https key set URL that redirects to http is loaded without TLS;
  • an application that takes the URL from the jku/x5u header of a token and checks its host against a list of allowed hosts is bypassed by any redirect on an allowed host, an open redirect for instance: the key set, and so the key that verifies the token, come from the redirect target.

The library and the bundle only load configured URLs, and the documentation never takes the URL from a token. It does not warn against doing so either.

How to reproduce
use Jose\Component\KeyManagement\X5UFactory;
use Symfony\Component\HttpClient\HttpClient;

// https://keys.example.com/x5u answers "302 Found", "Location: http://127.0.0.1:8080/admin/cache/purge?all=1"
$keySet = (new X5UFactory(HttpClient::create()))->loadFromUrl('https://keys.example.com/x5u');

// The local service receives "GET /admin/cache/purge?all=1" and its "{}" answer becomes an empty key set.
// JKUFactory sends the same request, then throws "Invalid data.".
Possible Solution

Workaround available today: give the factories a client that does not follow redirects, for example a scoped client with max_redirects: 0 (a 3xx answer then fails), possibly wrapped in NoPrivateNetworkHttpClient.

  • 4.x: document the workaround on the key set page, and say in the security recommendations that jku/x5u must not be taken from a token; an application that does it anyway should compare the full URL with an exact list and refuse redirects. An opt-in could come with 4.3.0 (an extra constructor argument read with func_num_args(), or a bundle option).
  • 5.0.0: refuse redirects by default and treat any non-2xx answer as a failure, with an explicit opt-in.

Refusing redirects in a patch release would stop every key set URL that redirects today (http to https, a moved endpoint), so it is not a patch-level change.

Additional Context

Found by the Anthropic OSS Scanner (ANT-2026-5HOQLEPP).

On 4.3, the docblock of UrlKeySetFactoryTrait ("Fetches the document a "jku" or a "x5u" header parameter points to") reads as an invitation to load URLs taken from tokens and is worth rewording.

Lenguaje dominante
PHP
Estrellas
954
Forks
119
Merge medio
48 min
PR fusionados (30 d)
17

Preparar el entorno

Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de web-token/jwt-framework

Todos los issues de web-token/jwt-framework

Issues similares

Más issues de PHP

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.