T4 · Handler global de excepciones sin fuga de información (Auditoría Suprema Etapa 3)
Contexto
La API de CreaRack (~509 endpoints Ninja) devolvía en respuestas 500 el mensaje técnico completo del error junto con el nombre de la clase de excepción:
{
"error": "Unhandled API error...<ruta-interna-secreta>/opt/app/...",
"type": "SomeException"
}
Esto exponía:
- Rutas internas del servidor
- Fragmentos de consultas SQL
- Nombres de máquinas / configuración de infraestructura
- Detalles de la pila de tecnología
Hallazgo transversal de blueprints s105 (auditoría de seguridad): afectaba al 100% de los endpoints por ser la política global de manejo de excepciones en config/urls.py.
Decisión
Implementar un handler global de excepciones (global_exception_handler) que:
-
En producción (
DEBUG=False): Devuelve un cuerpo genérico y fijo:{ "error": "Internal server error" } -
Logs del servidor: El traceback completo se registra en
api.errorscon contexto completo (método HTTP, path, stack). -
En desarrollo local (
DEBUG=True): Se conservandetail(str(exc)) ytype(clase) para facilitar debugging. -
Contrato API: El formato
{"error": ...}se mantiene intacto → Sin cambios en el frontend.
Implementación
Archivo: config/urls.py / función global_exception_handler
import logging
_api_logger = logging.getLogger("api.errors")
@api.exception_handler(Exception)
def global_exception_handler(request, exc):
"""500 genérico (T4, Auditoría Suprema): el detalle del error iba al cliente..."""
_api_logger.error("Unhandled API error on %s %s", request.method, request.path, exc_info=exc)
body = {"error": "Internal server error"}
if settings.DEBUG:
body["detail"] = str(exc)
body["type"] = exc.__class__.__name__
return api.create_response(request, body, status=500)
Tests: tests/api/test_t4_exception_handler.py
test_500_body_is_generic: Verifica que conDEBUG=False, el cuerpo no expone información sensible.test_debug_keeps_detail_for_local_dev: Verifica que conDEBUG=True, el detail sigue presente.
Justificación
- Seguridad: Cierra una fuga de información transversal que afectaba a todos los 509 endpoints.
- Auditoría: Requisito s105 de la auditoría de seguridad pre-product-launch.
- Observabilidad: La información se conserva en los logs del servidor (
api.errors), accesibles solo para ops/dev. - Compatibilidad: El frontend no necesita cambios (nadie consumía el campo
typedel 500).
Relacionadas
- [[decision—20260611—t1-cifrado-credenciales-snmp]] — Otra mitigación de T1 en la misma auditoría
- [[concept—security—information-disclosure]] — Concepto de fuga de información
Véase también
- [[entity—config—handler—global-exception]]
- [[concept—security—information-disclosure]]
- [[runbook—security—respond-error-disclosure]]