Un proxy central basado en Node puede agotar el presupuesto mensual de un proveedor en una sola noche si una clave de servicio comprometida accede a una ruta de generación (completion route) permisiva y el proxy confía en los parámetros de enrutamiento proporcionados por el cliente —como provider=openai y model=$OPENAI_CHAT_MODEL— incluidos en el cuerpo de la solicitud.
En nuestro sistema en funcionamiento, AcmeSupportApp realiza llamadas a la puerta de enlace (gateway) en nombre del inquilino (tenant) t_acme_prod; la puerta de enlace distribuye la carga hacia $OPENAI_CHAT_MODEL, $ANTHROPIC_CHAT_MODEL o $LLAMA_CHAT_MODEL, y una caché semántica compartida se sitúa cerca de la puerta de enlace para ahorrar tokens en prompts repetidos.
El fallo no consiste en una vulnerabilidad sofisticada del modelo. El atacante solo necesita una clave que supere las comprobaciones superficiales actuales; luego envía un gran volumen de solicitudes con prompts extensos y límites de salida elevados. La puerta de enlace reenvía estas solicitudes porque no se reservó ningún presupuesto específico por inquilino que pudiera aplicarse antes de iniciar la llamada al proveedor.
Dado que el proxy transmite la salida del proveedor sin filtrar de vuelta al cliente, la misma clave comprometida puede provocar la inclusión de contenido inseguro en las respuestas a los tickets (tickets), ya que no existe ningún mecanismo que aplique políticas sobre el texto generado en el límite de la puerta de enlace.
Considerando esta secuencia, cabe preguntarse qué etapa podría haber rechazado la primera solicitud antes de incurrir en gastos y antes de que se generara cualquier salida insegura.
La puerta de enlace es el único componente que conoce simultáneamente la identidad del cliente y la elección del proveedor; por tanto, es el lugar donde podemos vincular AcmeSupportApp con t_acme_prod y rechazar cualquier modelo o ruta fuera de su alcance antes de utilizar la clave del proveedor.
A los demás puntos de la cadena (hops) les falta información crítica. El proveedor solo ve sus propias credenciales asignadas a la puerta de enlace, por lo que no puede distinguir entre los inquilinos de nuestra plataforma; por su parte, la caché solo ve una clave derivada del contenido de la solicitud, por lo que no puede controlar quién tiene permiso para gastar ni a qué modelo puede acceder el cliente.
Los datos no fiables pueden entrar en el sistema a través de múltiples puntos, incluso cuando la conexión TLS es correcta. Las cabeceras de la solicitud pueden falsear la identidad si aceptamos los identificadores de inquilino proporcionados por el cliente; el cuerpo de la solicitud puede falsear el enrutamiento y la selección del modelo si damos validez a esa información; y la respuesta del proveedor constituye una salida no fiable que puede contener contenido que infrinja políticas o campos estructurados que rompan el esquema esperado. A continuación, se muestra la ruta de la solicitud con los límites de confianza y los puntos de aplicación de políticas señalados.
Este diagrama muestra la restricción práctica sobre la que construimos el resto del curso. Solo la puerta de enlace (gateway) puede autenticar al solicitante, evaluar una política por solicitud, reservar cuota en un contador compartido y aplicar comprobaciones tanto de entrada como de salida en flujo (streaming) antes de que la respuesta regrese al sistema del solicitante.
Una puerta de enlace mantiene un comportamiento predecible bajo ataque cuando cada punto de control utiliza un código de rechazo único y dicho código se genera antes del siguiente paso costoso. Utilizamos un único mapa de rechazos para todo el curso, de modo que los registros, las alertas y el comportamiento del cliente permanezcan coherentes entre los distintos proveedores.
Una credencial del solicitante ausente, no válida, revocada o comprometida da lugar a un error 401 Unauthorized.
Un solicitante autenticado que pide una ruta o modelo fuera de su lista de permitidos (allowlist) recibe un error 403 Forbidden, y la puerta de enlace rechaza la petición antes de contactar con el host de cualquier proveedor.
El agotamiento del límite de tasa (rate limit) o de la cuota de tokens y costes genera un error 429 Too Many Requests acompañado de una cabecera Retry-After, ya que el cliente necesita una política de espera (backoff) clara y los reintentos no deben incrementar el gasto.
Si la puerta de enlace no puede aplicar las restricciones de forma segura —por ejemplo, porque el almacén de contadores compartidos está caído o un interruptor de circuito (circuit breaker) abierto bloquea las comprobaciones—, devuelve un error 503 Service Unavailable en lugar de permitir el paso (fail-open) y generar gastos sin atribución.
Si la llamada al proveedor supera el tiempo de espera (timeout) de la puerta de enlace, esta devuelve un error 504 Gateway Timeout y no transmite la salida parcial como si fuera una respuesta exitosa.
Si requerimos una salida estructurada y la respuesta del proveedor no supera la validación del esquema, la puerta de enlace devuelve un error 422 Unprocessable Content para evitar que un analizador (parser) posterior procese campos no fiables.
En el escenario inicial, el primer punto de rechazo debe ser la autenticación y la comprobación de políticas en la puerta de enlace, antes de cualquier reserva de cuota o llamada al proveedor; esto se debe a que las etapas posteriores ya no disponen de la información necesaria para vincular el gasto y los permisos a t_acme_prod una vez que la solicitud ha comenzado a fluir hacia el exterior.