Tema 17
Cuando una API falla, no solo importa que responda algo útil; también importa cuánto revela sobre su estructura interna, sus datos y sus reglas. Los errores son una superficie de observación privilegiada para atacantes: muestran diferencias de comportamiento, validaciones, estados de negocio, existencia de recursos y detalles técnicos que pueden convertirse en un mapa del sistema.
Los errores son inevitables en cualquier API. Habrá validaciones fallidas, recursos inexistentes, tokens vencidos, conflictos de negocio, timeouts, dependencias caídas y excepciones inesperadas. El desafío no está en evitar que algo falle, sino en fallar de forma controlada.
Una API insegura suele responder errores demasiado expresivos: revela stack traces, nombres internos, diferencias sutiles entre estados, o devuelve mensajes que permiten inferir usuarios válidos, existencia de objetos o lógica operativa. En cambio, una API madura distingue entre lo que necesita saber el cliente legítimo y lo que solo debe quedar registrado internamente.
Este tema estudia cómo diseñar respuestas de error útiles, consistentes y seguras.
Los errores pueden revelar mucho más de lo que parece. No solo exponen texto; también exponen estructura, timing, diferencias entre caminos de ejecución y detalles del entorno.
Ejemplos de información filtrable:
Una respuesta de error segura debería cumplir varios objetivos al mismo tiempo:
La consistencia no es solo una cuestión estética o de DX. También es una defensa. Cuando una API responde de forma muy distinta ante casos equivalentes, ofrece señales útiles para enumeración y profiling.
Por ejemplo:
Estas diferencias pueden facilitar reconocimiento del sistema incluso sin acceso válido.
Una API debería distinguir claramente entre problemas causados por la solicitud y fallos internos del sistema. Esta separación ayuda al cliente y evita mezclar errores de uso con problemas operativos.
| Tipo de error | Ejemplo | Qué conviene mostrar |
|---|---|---|
| Entrada inválida | Formato incorrecto, campo faltante | Qué parte del contrato falló |
| Autenticación/autorización | Token inválido, acceso denegado | Mensaje controlado sin exceso de detalle |
| Conflicto de negocio | Estado incompatible, operación no permitida | Regla funcional relevante, no internals |
| Fallo interno | Excepción, dependencia caída | Mensaje genérico y trazabilidad interna |
Los errores de validación suelen requerir más detalle porque el cliente necesita corregir la solicitud. Sin embargo, ese detalle debe limitarse al contrato de entrada, no a la lógica interna del backend.
Es razonable indicar:
No es razonable devolver:
Los flujos de autenticación son especialmente sensibles a errores informativos. Diferenciar demasiado entre “usuario inexistente”, “contraseña incorrecta”, “cuenta bloqueada” o “MFA pendiente” puede facilitar enumeración y profiling de cuentas.
Esto no significa responder siempre igual en todo sentido, pero sí evitar mensajes que confirmen información innecesaria a actores no confiables. Muchas veces conviene devolver respuestas más uniformes externamente y guardar el detalle real en logs internos.
En algunos casos, responder `403 Forbidden` confirma implícitamente que el recurso existe, pero que el actor no puede acceder. En otros contextos puede ser preferible usar `404 Not Found` para no confirmar existencia de recursos sensibles.
No hay una única respuesta correcta para todas las APIs. Lo importante es que la política sea consciente, consistente y alineada con el modelo de amenaza. La inconsistencia es lo que más ayuda al atacante.
Las excepciones no controladas son una fuente clásica de fuga de información. Cuando la API deja que una excepción suba hasta el borde sin manejo central, puede terminar devolviendo stack traces, nombres de clases, consultas, rutas de archivo o detalles de infraestructura.
Esto suele ocurrir por:
Una práctica recomendable es centralizar la traducción de errores internos a respuestas HTTP. Esto permite:
La centralización reduce exposición y mejora la mantenibilidad del comportamiento de error.
Un cliente legítimo o un operador puede necesitar reportar un fallo sin que la respuesta incluya información técnica sensible. Para eso son útiles los identificadores de correlación: valores que permiten encontrar el evento exacto en logs internos sin exponer internals al exterior.
Esto permite mantener el mensaje externo simple, mientras el equipo de soporte conserva suficiente trazabilidad para investigar.
Cuando fallan servicios externos o dependencias internas, la API debe decidir cómo comunicarlo. Un error demasiado verboso puede exponer arquitectura; uno demasiado ambiguo puede dificultar la operación del cliente.
En estos casos conviene:
Los errores no deberían incluir secretos, tokens, payloads completos, documentos ni datos personales salvo que exista una razón muy fuerte y controlada. Esto vale también para sistemas de tracing, debugging y pantallas de soporte.
Una práctica peligrosa es “ecoar” el request fallido entero en la respuesta o en herramientas de soporte. Eso puede convertir un error común en una fuga directa de información sensible.
No toda fuga viene del texto. También puede surgir del tiempo de respuesta o del patrón observable. Si una API tarda claramente distinto cuando un usuario existe o cuando un recurso pertenece a otro tenant, el atacante puede usar esas señales para inferir información.
Por eso la seguridad de errores también incluye prestar atención a:
Usar un formato uniforme para errores ayuda tanto al cliente como a la seguridad. Una estructura consistente puede incluir:
Lo importante es que el formato no obligue a volcar detalle técnico excesivo para ser útil.
En desarrollo suele ser útil ver más detalle. El problema aparece cuando esa misma verbosidad se arrastra a staging público o producción. La configuración de errores debe diferenciar claramente ambientes y minimizar exposición en cualquier entorno accesible fuera del equipo controlado.
También conviene evitar que capturas, trazas o payloads reales de producción terminen en documentación o canales informales por costumbre de debugging.
Manejar errores de forma segura es una parte esencial de la seguridad de APIs REST porque el sistema revela mucho sobre sí mismo precisamente cuando algo sale mal. Diseñar respuestas consistentes, útiles y cuidadosamente limitadas evita que un mecanismo orientado a soporte se convierta en una herramienta de reconocimiento para atacantes. La clave está en separar claramente lo que necesita el cliente de lo que solo debe saber el sistema.
En el próximo tema estudiaremos seguridad en diseño: versionado, idempotencia y minimización de exposición, para ver cómo decisiones arquitectónicas tempranas condicionan la superficie de ataque de la API.