Skip Content

A10: Mal Manejo de Condiciones Excepcionales (Blog)

¿Que es el mal manejo de condiciones excepcionales?

Ocurre cuando fallos (excepciones, timeouts, reintentos, errores de queue) no se disenan como caminos de primera clase. Esto termina en stack traces filtrados, corrupcion silenciosa o comportamiento "fail-open" en flujos sensibles.

OWASP 2025 lo incluye como categoria distinta, y Laravel 12 ofrece manejo y reporte centralizado de excepciones.

Fallo tipico en Laravel

  • Stack traces expuestos a usuarios.
  • Excepciones tragadas en silencio.
  • Comportamiento fail-open.
  • Rutas null/timeout/retry no disenadas.
  • Fallos de queue ignorados.
  • Errores de servicios externos dejan estados inconsistentes.

Impacto

  • Divulgacion de informacion sensible.
  • Invariantes rotas (billing/authz/permisos) por fallos parciales.
  • Inconsistencia de datos por side-effects parciales.
  • Ataques mas faciles cuando el sistema "falla abierto".

Remediacion en Laravel 12

  • Centraliza manejo de excepciones en bootstrap/app.php.
  • Falla cerrado para authz, billing y flujos sensibles.
  • Estandariza excepciones de dominio y respuestas seguras hacia el usuario.
  • Agrega retry/backoff/circuit-breaker para servicios externos.
  • Asegura monitoreo de failed jobs y acciones compensatorias.
  • Prueba paths negativos, no solo el happy path.

Arreglo concreto

Reemplaza catch-all genericos que ocultan fallos. Devuelve respuestas controladas mientras reportas excepciones internamente.

try {
$isSpam = $spamDetectionService->isSpam($commentBody);
} catch (SpamServiceTimeout $e) {
report($e);
 
return response()->json([
'message' => 'Falla temporal.',
], 503);
} catch (DomainException $e) {
report($e);
 
return response()->json([
'message' => 'Solicitud rechazada.',
], 422);
}

Enfoque de patron de diseno

  • Usa State para workflows criticos con transiciones validas explicitas.
  • Usa Chain of Responsibility o Pipeline para pasos guardados.
  • Usa Factory Method para mapear excepcion -> respuesta de forma estandar.

Ejemplo: factory de excepcion a respuesta (seguro y consistente):

use Throwable;
 
interface ExceptionResponseFactory
{
public function from(Throwable $e): \Illuminate\Http\JsonResponse;
}
 
final class ApiExceptionResponseFactory implements ExceptionResponseFactory
{
public function from(Throwable $e): \Illuminate\Http\JsonResponse
{
report($e);
 
return match (true) {
$e instanceof SpamServiceTimeout => response()->json(['message' => 'Falla temporal.'], 503),
$e instanceof DomainException => response()->json(['message' => 'Solicitud invalida.'], 422),
default => response()->json(['message' => 'Error del servidor.'], 500),
};
}
}

Referencias