Seguridad de Errores
Reglas
- Nunca filtres trazas de pila, errores de base de datos o rutas de archivos a los clientes en producción
- Devuelve mensajes de error genéricos con un ID de error único:
{ error: "Algo salió mal", errorId: "abc123" }
- Registra todos los detalles del error en el servidor con el mismo ID de correlación para depuración
- Usa diferentes niveles de detalle de error: desarrollo (traza de pila completa) vs producción (mensaje seguro + ID)
- Captura todos los errores no manejados con manejadores globales — nunca permitas que los errores sin procesar lleguen al cliente
- Sanitiza los mensajes de error de servicios de terceros antes de reenviarlos a los clientes
- Devuelve códigos de estado HTTP apropiados: 400 (entrada incorrecta), 401 (no autenticado), 403 (prohibido), 404 (no encontrado), 500 (error del servidor)
import { randomUUID } from "node:crypto";
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
const errorId = randomUUID();
console.error({ errorId, message: err.message, stack: err.stack, url: req.url });
const statusCode = (err as any).statusCode || 500;
res.status(statusCode).json({
error: statusCode >= 500 ? "Error interno del servidor" : err.message,
errorId,
...(process.env.NODE_ENV === "development" && { stack: err.stack }),
});
});
export default function GlobalError({ error, reset }) {
return (
<div>
<h2>Algo salió mal</h2>
<p>ID de error: {error.digest}</p>
<button onClick={reset}>Intentar de nuevo</button>
</div>
);
}
Evitar
- Devolver
err.message directamente — los errores de base de datos filtran nombres de tablas, nombres de columnas y estructura de consultas
- Trazas de pila en respuestas de producción — revelan rutas de archivos, dependencias y arquitectura interna
- Un 500 genérico para todo — usa códigos de estado adecuados para que los clientes puedan manejar los errores apropiadamente
- Registrar errores sin IDs de correlación — hace que la depuración en producción sea casi imposible
- Tragar errores silenciosamente — siempre registra, incluso si la respuesta es genérica