JWT Sin Expiración
JWTs firmados sin el claim `exp` que nunca expiran, lo que significa que un token robado da acceso permanente sin forma de revocarlo.
Cómo Funciona
Los JWTs son stateless por diseño — el servidor no los almacena. La expiración (`exp`) es el mecanismo principal para limitar su vida útil. Sin ella, un token robado hoy sigue siendo válido años después. No puedes invalidarlo sin construir una blacklist, lo que anula el propósito stateless.
// MAL: sin expiración
const token = jwt.sign(
{ userId: user.id, role: user.role },
process.env.JWT_SECRET!
);// BIEN: expiración corta + patrón de refresh token
const token = jwt.sign(
{ userId: user.id, role: user.role },
process.env.JWT_SECRET!,
{ expiresIn: '15m' }
);Ejemplo Real
Una app SaaS emitía JWTs sin expiración para acceso a su API. Cuando un empleado dejó la empresa, su token siguió funcionando indefinidamente porque no había expiración ni mecanismo de revocación.
Cómo Prevenirlo
- Siempre pon expiresIn al firmar JWTs — 15 minutos para access tokens, 7 días para refresh tokens
- Implementa un patrón de refresh token rotation para que los tokens de corta vida sigan siendo usables
- Guarda los refresh tokens server-side para poder revocarlos al hacer logout o en caso de breach
- Usa una librería como jose o jsonwebtoken que valide exp automáticamente al verificar
Tecnologías Afectadas
Data Hogo detecta esta vulnerabilidad automáticamente.
Escanea Tu Repo GratisVulnerabilidades Relacionadas
API Keys Hardcodeadas
criticalAPI keys, tokens o secretos escritos directo en el código fuente, visibles para cualquiera con acceso al repo — incluyendo repos públicos de GitHub.
Sin Validación de Inputs
mediumDatos enviados por el usuario pasados directo a bases de datos o APIs externas sin ninguna validación de tipo, formato o contenido.
Contraseñas en Texto Plano
criticalContraseñas de usuarios guardadas como strings crudos en la base de datos en lugar de hashearse con bcrypt o Argon2.
Lógica de Auth Solo en Frontend
highMostrar u ocultar elementos de UI basándose en el rol del usuario en React, sin ninguna validación server-side — fácilmente bypasseable abriendo DevTools.