Um proxy central em Node pode consumir todo o orçamento mensal de um provedor da noite para o dia quando uma chave de serviço comprometida acessa uma rota de geração (completion) permissiva e o proxy confia em parâmetros de roteamento fornecidos pelo solicitante — como provider=openai e model=$OPENAI_CHAT_MODEL — presentes no corpo da requisição.
Em nosso sistema em operação, o AcmeSupportApp chama o gateway em nome do tenant t_acme_prod; o gateway então encaminha a solicitação para $OPENAI_CHAT_MODEL, $ANTHROPIC_CHAT_MODEL ou $LLAMA_CHAT_MODEL, enquanto um cache semântico compartilhado atua próximo ao gateway para economizar tokens em prompts repetidos.
A falha não envolve uma quebra sofisticada do modelo. O atacante precisa apenas de uma chave que passe pelas verificações superficiais existentes atualmente; em seguida, envia um grande volume de requisições com prompts longos e limites de saída elevados. O gateway encaminha essas solicitações porque nenhum orçamento específico por tenant foi reservado ou aplicado antes do início da chamada ao provedor.
Como o proxy também transmite a saída não filtrada do provedor de volta ao solicitante, a mesma chave comprometida pode resultar na inclusão de conteúdo inseguro em respostas de chamados (tickets) subsequentes, visto que não há aplicação de políticas sobre o texto gerado na fronteira do gateway.
Diante dessa sequência, qual etapa poderia ter recusado a primeira requisição antes de qualquer gasto ou da geração de qualquer saída insegura?
O gateway é o único componente que visualiza simultaneamente a identidade do solicitante e a escolha do provedor; portanto, é nele que podemos vincular o AcmeSupportApp ao tenant t_acme_prod e recusar qualquer modelo ou rota fora de seu escopo antes que a chave do provedor seja utilizada.
Em todas as outras etapas do fluxo, falta uma informação crítica. O provedor enxerga apenas a credencial do próprio gateway, sendo incapaz de distinguir os tenants dentro de nossa plataforma; já o cache enxerga apenas uma chave derivada do conteúdo da requisição, não podendo, portanto, controlar quem tem permissão para gastar ou qual modelo o solicitante pode acessar.
Dados não confiáveis entram em múltiplos pontos, mesmo quando a conexão TLS está correta. Os cabeçalhos da requisição podem conter informações falsas sobre a identidade caso aceitemos IDs de tenant fornecidos pelo solicitante; o corpo da requisição pode enganar quanto ao roteamento e à seleção do modelo se tais parâmetros forem considerados; e a resposta do provedor é uma saída não confiável que pode conter conteúdo que viola políticas ou campos estruturados que quebram o esquema esperado. Abaixo, apresenta-se o caminho da requisição com a indicação dessas fronteiras de confiança e pontos de aplicação de políticas.
Este diagrama mostra a restrição prática em torno da qual construímos o restante do curso. Apenas o gateway pode autenticar o solicitante, avaliar uma política por requisição, reservar cota em um contador compartilhado e aplicar verificações tanto na entrada quanto na saída via streaming, antes que a resposta retorne ao sistema do solicitante.
Um gateway mantém um comportamento previsível sob ataque quando cada ponto de aplicação de regras utiliza um código de recusa único, gerado antes da próxima etapa de alto custo. Utilizamos um único mapa de recusas durante todo o curso para garantir que logs, alertas e o comportamento do cliente permaneçam consistentes entre os diferentes provedores.
Uma credencial de solicitante ausente, inválida, revogada ou comprometida resulta em 401 Unauthorized.
Um solicitante autenticado que requisita uma rota ou modelo fora de sua lista de permissões (allowlist) recebe um 403 Forbidden, e o gateway recusa a requisição antes de contatar qualquer host do provedor.
O esgotamento do limite de taxa (rate limit) ou da cota de tokens e custos resulta em 429 Too Many Requests acompanhado de Retry-After, pois o cliente precisa de um contrato claro de backoff e as tentativas de reenvio não devem aumentar os gastos.
Se o gateway não puder aplicar as regras com segurança — seja porque o armazenamento do contador compartilhado está fora do ar ou porque um circuit breaker aberto bloqueia as verificações —, ele retorna 503 Service Unavailable, em vez de permitir a passagem da requisição (fail-open) e gerar custos sem a devida atribuição.
Se a chamada ao provedor exceder o tempo limite (timeout) do gateway, este retorna 504 Gateway Timeout e não transmite a saída parcial como uma resposta bem-sucedida.
Se exigirmos saída estruturada e a resposta do provedor falhar na validação de esquema, o gateway retorna 422 Unprocessable Content, garantindo que nenhum parser subsequente processe campos não confiáveis.
No cenário inicial, o primeiro ponto de recusa deve ser a autenticação no gateway combinada com a verificação de políticas — antes de qualquer reserva de cota ou chamada ao provedor —, pois as etapas posteriores não dispõem das informações necessárias para vincular gastos e permissões a t_acme_prod uma vez que a requisição já começou a ser enviada para fora.