Todos los artículos

Bypass del TokenGuard de Laravel: ¿estás expuesto y qué ejecutar hoy?

Seguridad · 4 min de lectura ·

Laravel News informó el 2026-10-20 de un aviso crítico, GHSA-f9x3-7vq9-cph6 con una puntuación CVSS de 9.2, en Illuminate\Auth\TokenGuard, la clase que hay detrás del driver de guard token. En MySQL y MariaDB, un atacante sin cuenta podía quedar autenticado como un usuario existente sin conocer su token de API. Si usas Laravel, la pregunta útil no es lo grave que suena, sino si tu app usa ese guard, y la respuesta está en un solo archivo.

Qué falló

Según el aviso tal como lo describe Laravel News, el guard solo comprobaba que el token sacado de la petición no estuviera vacío antes de pasarlo al user provider. Un valor fabricado a propósito, que no era una cadena, superaba esa comprobación, y la búsqueda siguiente encontraba un registro de usuario que nunca debió encontrar en lugar de fallar. El hallazgo se atribuye a Hristijan Manasijev. El arreglo añade una comprobación de tipo en user() y en validate(), de modo que lo que no sea una cadena se rechaza antes de lanzar ninguna consulta.

// before (simplified): only emptiness was checked
if (! empty($token)) { ... }

// after (as quoted in the report): the type is checked first
if (is_string($token) && ! empty($token)) { ... }
Token de la petición ¿Está vacío? No, sigue Búsqueda de usuario Entra otro usuario nadie comprueba que sea cadena un valor que no es cadena llega a la base de datos
Antes del arreglo: el único filtro pregunta si el valor está vacío, nunca de qué tipo es.

Por qué un valor que no es cadena es peligroso en una búsqueda

Esta parte explica la clase de fallo en general, no el mecanismo confirmado de este aviso. En PHP, la entrada de una petición no siempre es una cadena. Una query string o un cuerpo JSON pueden traer un array donde tu código espera un único valor, y los query builders suelen tratar un array como "varios valores" o "varias condiciones" en lugar de como un token que comparar. El código que solo pregunta "¿está vacío?" deja pasar ese array, y la búsqueda responde entonces a una pregunta distinta de la que querías hacer. La defensa es aburrida y fiable: comprueba el tipo de cada entrada con pinta de credencial en la frontera, antes de que toque una consulta.

Token de la petición ¿is_string y no vacío? sí Búsqueda con una cadena no Rechazado, sin consulta
Después del arreglo: el tipo se comprueba primero, así que un array nunca llega a la base de datos.

¿Estás expuesto? Abre config/auth.php

Según el aviso, solo te afecta si un guard de config/auth.php usa el driver token, por ejemplo 'api' => ['driver' => 'token', 'provider' => 'users']. Sanctum y Passport registran sus propios drivers de guard y no aparecen en el aviso. Las versiones corregidas son Laravel 12.68.0 y 13.29.0, ambas con fecha 2026-08-25 en el artículo de Laravel News; cualquier versión anterior figura como afectada, y solo hay parches para las ramas 12.x y 13.x. Si estás en una versión mayor más antigua y usas el driver token, la solución es subir de versión mayor.

Ese mismo día llegó un segundo aviso, de gravedad media, GHSA-5wcm-3v2w-8362 con CVSS 6.5, en los recursos JSON:API añadidos en la 12.45: una petición de solo lectura podía construirse para desencadenar una operación destructiva en una tabla relacionada. Laravel News da 12.68.0 y 13.27.0 como versiones corregidas para ese, así que la misma actualización cubre ambos.

Busca 'token' en config/auth.php. Si ningún guard usa ese driver, este aviso no te alcanza, pero actualiza igualmente: el de JSON:API podría hacerlo.

Qué ejecutar

composer update laravel/framework
composer audit

Mete también composer audit en la CI, para que el próximo aviso aparezca como un build fallido y no como un artículo que lees por casualidad. En este sitio comprobé las dos cosas: composer.lock fija laravel/framework en v13.35.0, que es posterior a 13.29.0, y config/auth.php solo define un guard session, así que aquí no hay ningún guard token para empezar. Si estás construyendo una API nueva, Sanctum es una opción por defecto más segura que el guard de tokens a pelo, y uses lo que uses, comprueba que cada credencial es una cadena antes de que llegue a una consulta.

Fuente: Laravel News, «Laravel token guard auth bypass».

Notas de los lectores

  1. Todavía no hay notas. La primera siempre es la más valiente.
¿Estás construyendo algo parecido? Puedo ayudarte. Escríbeme por WhatsApp