Ilustração técnica abstrata sobre um fundo azul-marinho escuro: uma porta de entrada brilhante na parede esquerda de uma caixa translúcida admite uma única linha fina e pálida, sem crachá e sem chave. Dentro da caixa, a linha encontra uma pilha de pequenos painéis arredondados e se ramifica em uma curta fileira de traços angulares semelhantes a comandos que descem para um compartimento inferior contendo um conjunto de tokens brilhantes em forma de chave. Um segundo portão fechado, contornado em azul-claro, fica ao lado da porta de entrada. Sem texto, sem pessoas, sem logotipos de organizações.
AI Safety Incidents

Um único POST não autenticado para a API de Gerenciamento do Bifrost iniciou um comando como o usuário do gateway

Autor

Magnus Corvin

Data de publicação

Modelos mais recentes · 20Ver todos os modelos →
Benchmarks: Artificial Analysis · atualizado diariamente
Voltar para todas as publicações

Em 14 de setembro de 2026, a JFrog Security Research publicou a CVE-2026-90898, uma falha de execução de comandos no Bifrost — o gateway de IA de código aberto mantido pela Maxim — e atribuiu-lhe 9,8 de 10. O ataque foi uma única solicitação HTTP. Um POST /api/mcp/client não autenticado registra um cliente MCP stdio, que o Bifrost lê como um nome de programa mais uma lista de argumentos e inicia imediatamente, antes de qualquer handshake MCP, como o usuário que executa o gateway; na imagem oficial, esse usuário é appuser. Um gateway também é onde ficam as chaves de provedor e as chaves virtuais de um operador, então um processo em execução ali tem acesso a credenciais. O que tornou a solicitação anônima foi um padrão de fábrica: governance.auth_config.is_enabled está definido como false e, nas palavras da JFrog, "com a autenticação desativada, todo chamador é um administrador local". Nenhuma fonte citada relata que a falha tenha sido explorada. As próprias fontes do registro, a classificação de gravidade e a avaliação de confiança estão no arquivo de incidentes de IA, ao lado das outras vulnerabilidades documentadas de gateways de IA e MCP do último ano.

Bifrost é um único serviço que fica entre uma aplicação e os modelos de linguagem que ela chama. Seu repositório o descreve como um gateway de código aberto, licenciado sob Apache-2.0, que "unifica o acesso a mais de 23 provedores ... por meio de uma única API compatível com OpenAI", com proxy MCP, chaves virtuais, orçamentos e balanceamento de carga por provedor entre seus recursos, e ele tinha cerca de 9.150 estrelas no GitHub em 28 de outubro de 2026. Essa combinação é o motivo pelo qual um shell neste host específico merece uma pontuação crítica: o processo que encaminha as requisições também é o processo que detém as credenciais de cada upstream para o qual encaminha. O Hacker News, ao noticiar a falha em 22 de setembro, expôs a consequência de forma clara — como o gateway armazena chaves de API para cada provedor conectado, executar comandos no processo do gateway concede ao atacante acesso a essas credenciais.

Todo o ataque foi um único POST

O alerta da JFrog, publicado sob a referência JFSA-2026-001686326, descreve um endpoint que existe para permitir que um administrador adicione um servidor MCP. Um cliente stdio na especificação MCP não é uma URL; é um comando e seus argumentos, que o programa host deve executar. O Bifrost aceita essa configuração por meio da API de gerenciamento e inicia o programa assim que o cliente é adicionado. Nenhuma negociação de capacidades, nenhuma verificação de identidade do servidor, nenhum handshake precisa ser concluído com êxito antes — o alerta é explícito ao afirmar que o handshake não é o que inicia o processo.

A prova de conceito no aviso é um corpo JSON curto enviado a um gateway com a autenticação deixada no padrão. Ele registra um cliente cujo comando é /bin/sh e cujos argumentos gravam um arquivo marcador, depois lê o marcador de volta. A JFrog acrescenta um detalhe operacional que importa durante a resposta a incidentes: a solicitação HTTP pode expirar enquanto o Bifrost aguarda um handshake que nunca chega, e um timeout nos logs não significa que o comando falhou ao iniciar. O processo já está em execução nesse momento.

O registro CVE, atribuído pela JFrog como Autoridade de Numeração CVE, mapeia o defeito para CWE-306, autenticação ausente para uma função crítica, e CWE-284, controle de acesso inadequado, e nomeia os dois arquivos que contêm o handler e seu middleware: transports/bifrost-http/handlers/mcp.go e transports/bifrost-http/handlers/middlewares.go. O módulo afetado é github.com/maximhq/bifrost/transports, em Linux e macOS, para todas as versões anteriores a 2.1.0.

O padrão que tornou a requisição anônima

Nada disso seria explorável sem uma segunda condição, e a segunda condição é o próprio padrão do produto. O middleware de autenticação de gerenciamento do Bifrost é condicionado por governance.auth_config.is_enabled, que vem definido como false. Com ele desativado, o middleware trata todo chamador como administrador local — o próprio resumo do aviso é que a autenticação desativada significa que todo chamador é um administrador local — então a verificação que teria bloqueado a requisição nunca estava no caminho.

A correção, o pull request #6757, foi mesclado ao projeto em 2 de setembro de 2026, doze dias antes da publicação da CVE e seis dias antes da versão que a contém. Sua descrição é incomumente franca sobre a forma do problema: o pull request fecha duas primitivas de acesso não autenticado na mesma API de registro, não apenas uma. A primeira é o cliente stdio. A segunda é um cliente MCP http ou sse apontado para um endereço de loopback ou de rede privada, que a solicitação chama de primitiva SSRF contra serviços internos, “incluindo o endpoint de metadados de nuvem 169.254.169.254”. Ambas agora são recusadas com HTTP 403 quando a solicitação chega ao handler sem uma verificação legítima de credenciais. Administradores autenticados mantêm ambas as capacidades, e operadores ainda podem provisionar clientes stdio por meio do config.json.

Essa segunda primitiva não aparece no texto da CVE. Ela está no patch, e é a razão pela qual a correção é um gate em vez de uma remoção: o recurso nunca foi o bug. Tratar um chamador não autenticado como administrador era.

Onde a API de gerenciamento estava realmente escutando

A alcançabilidade é a parte do registro que as fontes descrevem com mais consistência e medem menos. O aviso da JFrog indica que o padrão do binário original é localhost:8080, o que restringe um atacante ao próprio host. O aviso da mesma equipe para a falha associada afirma que a imagem Docker oficial, em vez disso, se vincula a 0.0.0.0, e o The Hacker News repete isso: a imagem torna a API de gerenciamento alcançável de fora do contêiner se a porta for publicada. O início rápido do próprio README do Bifrost executa "docker run -p 8080:8080 maximhq/bifrost", e a opção -p do Docker publica uma porta do contêiner em todas as interfaces do host, a menos que um endereço seja fornecido. O aviso do GitHub para a falha registra que o caminho relatado foi verificado na imagem publicada maximhq/bifrost:latest, na qual uma solicitação não autenticada iniciou /bin/sh e gravou um marcador como appuser.

O que nenhuma fonte fornece é um número. Não há contagem de instâncias Bifrost expostas à internet, nenhum resultado de varredura, nenhuma telemetria e nenhuma vítima. O registro não traz dano real, e essa ausência é um fato sobre a reportagem, e não uma garantia — a classe de vulnerabilidade só é perigosa onde duas condições coincidem, um listener exposto e um padrão intocado, e ninguém publicou com que frequência isso ocorreu.

Um endpoint, duas falhas, uma causa raiz

Oito dias antes do aviso do MCP, em 6 de setembro de 2026, a mesma equipe de pesquisa publicou CVE-2026-86242, uma segunda via não autenticada para o mesmo processo. Descoberta por Or Peles e com pontuação 8.1, ela explora POST /api/plugins: o Bifrost aceita um plugin personalizado habilitado cujo caminho é uma URL HTTP, o carregador de objetos compartilhados trata um caminho com prefixo http como um download, grava o corpo em um arquivo .so temporário e entrega esse arquivo ao plugin.Open do Go. Se o carregamento for bem-sucedido, uma função Init opcional é executada imediatamente com a configuração do atacante, como o usuário do gateway.

A variante de compilação decide o que um atacante obtém. Nas compilações vinculadas dinamicamente que o projeto documenta para plugins Go personalizados, espera-se que o carregamento seja bem-sucedido, o que o aviso chama de execução remota de código não autenticada. Na imagem Docker vinculada estaticamente publicada, plugin.Open falha com "Dynamic loading not supported", então a mesma solicitação degrada para falsificação de solicitação do lado do servidor. Um plugin carregável também deve corresponder à versão do Go, ao sistema operacional, à arquitetura e à vinculação do host, o que é uma restrição real, e não uma formalidade. A correção é transports/v2.0.0, por meio do pull request #5763, e o intervalo afetado é tudo abaixo dele.

A armadilha está na ordem dos lançamentos. A v2.0.0 corrige o caminho do plugin e não corrige o caminho do MCP — The Hacker News diz isso explicitamente, e o aviso MCP da JFrog confirma que a v2.0.0 ainda permite o registro stdio não autenticado. Um operador que aplicou a correção prontamente após o aviso de 6 de setembro estava, só por esse ponto, ainda exposto até o lançamento de transports/v2.1.0 em 8 de setembro. Ambas as falhas se resumem à mesma frase nos dois avisos e no próprio pull request do fornecedor: a autenticação desativada é o padrão.

O que as fontes estabelecem, e o que não estabelecem

O mecanismo, a faixa de versões, a correção e o crédito estão de acordo entre o advisory, o registro CVE atribuído pela JFrog, o pull request e as notas de versão do próprio projeto, e o The Hacker News. A divergência restante é sobre a severidade, e ela é real.

O 9,8 é a pontuação da JFrog como CNA atribuidora, e é a pontuação que a NVD mantém — o registro da NVD lista reefs@jfrog.com como fonte da métrica e, em 28 de outubro de 2026, ainda mostra a entrada com o status "Awaiting Analysis", o que significa que a NVD publicou o vetor do atribuidor, e não sua própria análise dele. A avaliação SSVC do Coordenador da CISA anexada ao mesmo registro, com data e hora de 14 de setembro de 2026, traz exploração "none", automatizável "yes" e impacto técnico "total". O modelo EPSS da FIRST estimou a probabilidade de exploração nos próximos 30 dias em 2,3% em 27 de outubro de 2026, no 83º percentil entre todos os CVEs pontuados, e nem este CVE nem o CVE-2026-86242 aparecem no catálogo Known Exploited Vulnerabilities da CISA com data de 27 de outubro de 2026.

Em contrapartida, a Maxim contesta a classificação. Em um comunicado ao The Hacker News, Akshay Deo, diretor de tecnologia e cofundador da empresa, afirmou que o risco prático é menor do que a pontuação crítica sugere, porque a exploração exige que a interface de gerenciamento seja acessível a partir de uma rede não confiável e que o operador tenha deixado a autenticação desativada; a implantação padrão e documentada, disse ele, coloca o gateway dentro de uma rede privada. O The Hacker News relata que a Maxim considera a falha de baixa gravidade e está trabalhando com a JFrog, que atribuiu a CVE, para revisar a avaliação. Essa declaração aparece nesse único veículo; não foi encontrada uma segunda publicação citando a posição da Maxim, e nenhuma revisão havia sido publicada até 28 de outubro de 2026 — o registro da CVE foi atualizado pela última vez em 14 de setembro e a entrada do NVD em 18 de setembro, ambos ainda em 9,8.

Vale mais nomear duas lacunas adicionais do que suavizá-las. Os avisos do GitHub do projeto, publicados em 23 de setembro de 2026 e que creditam o pesquisador da JFrog como relator, ainda trazem 9,8 para a falha do MCP e 8,1 para a falha do plugin, sem qualquer sinal da revisão descrita por Maxim. E os intervalos afetados nesses avisos são definidos em relação a versões de módulo Go — abaixo de 1.5.27 e abaixo de 1.6.3 — e não às tags de release dos transports usadas nos avisos da JFrog, de modo que um operador que compara um documento com o outro precisa conciliar dois esquemas de numeração antes de decidir se uma build foi afetada.

Rendered two-column card with the kicker 'BIFROST · CVE-2026-90898' and the title 'What the sources establish — and what they do not', subtitled 'Sources: JFrog JFSA-2026-001686326 (14 September 2026), the CVE record assigned by JFrog, NVD, FIRST EPSS, the CISA KEV catalogue, and the project's pull request 6757 and release tags.' The left column, headed 'ESTABLISHED' in blue, lists eight items: score 9.8 with the vector AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H supplied by the CNA; CWE-306 missing authentication with CWE-284 access control; unauthenticated POST /api/mcp/client starting a program as the gateway user; affected below transports 2.1.0 when management auth is disabled, the default; fixed in transports 2.1.0, PR 6757 merged 2 September, released 8 September 2026; CISA SSVC of 14 September 2026 with exploitation none, automatable yes, impact total; EPSS 2.3 percent at the 83rd percentile on 27 October 2026; and not in the CISA KEV catalogue dated 27 October 2026. The right column, headed 'NOT ESTABLISHED, OR CONTESTED' in amber, lists eight items: no exploitation reported, and the archive records real harm as false; no count of exposed or affected deployments in any cited source; severity contested, the vendor's CTO telling The Hacker News it is low; no published revision to the score as of 28 October 2026; NVD still Awaiting Analysis, so the 9.8 is the assigner's and not NVD's; affected ranges stated in two numbering schemes across the advisories; no detection or triage guidance in either advisory; and no evidence tying the flaw to any intrusion. A footer reads 'Card rendered by OrcaRouter'. The OrcaRouter logo is composited in the bottom-right corner.

O que mudou e o que os operadores foram instruídos a fazer

A cronologia corre ao contrário a partir da divulgação, que é a parte menos intuitiva do registro. O pull request #6757 foi mesclado em 2 de setembro de 2026. transports/v2.1.0, a versão que o aviso aponta como a primeira a conter a correção, foi publicada em 8 de setembro — seis dias antes de CVE-2026-90898 ser publicado em 14 de setembro. A correção do plugin do projeto precedeu seu próprio aviso da mesma forma: transports/v2.0.0 foi lançado em 26 de agosto, onze dias antes do CVE de 6 de setembro. Operadores que acompanham lançamentos em vez de feeds tiveram os patches antes dos alertas.

O que a atualização proporciona é restrito e específico. No 2.1.0 e posteriores, um registro stdio não autenticado retorna 403 e o comando não é iniciado; administradores autenticados mantêm a capacidade, e o provisionamento via config.json continua funcionando. A medida paliativa do aviso para quem não pode migrar é definir governance.auth_config.is_enabled como true, usar credenciais de administrador fortes e manter o listener de gerenciamento fora de redes não confiáveis. A instrução da JFrog para instâncias que operaram expostas com a autenticação desativada não é investigar e torcer: trate-as como comprometidas e rotacione chaves virtuais e credenciais de provedores.

A aritmética de versões é a parte mais provável de ser mal interpretada. v2.0.0 não corrige esta falha. A linha 1.6.x até 1.6.11 também não contém a correção, e a tag mais recente da série 1.6 do projeto é transports/v1.6.11, publicada em 14 de agosto de 2026, sem nenhuma linha 1.7 no repositório em 28 de outubro de 2026 — portanto, não há versão corrigida dentro dessa série, e um operador da 1.6.x precisa migrar para a 2.1.0 ou posterior em vez de esperar por um backport. A linha de lançamento atual está bem além desse ponto: transports/v2.3.2 foi publicada em 20 de outubro de 2026.

Rendered release-timeline card with the kicker 'BIFROST · RELEASE TIMELINE', the title 'The fix shipped six days before the advisory' and the subtitle 'Dates from the project's release tags and pull request metadata, the JFrog advisories and The Hacker News. Every date below is a single day.' A horizontal timeline carries seven dated markers: 26 Aug 2026, transports 2.0.0 published; 2 Sep 2026, PR 6757 merged; 6 Sep 2026, CVE-2026-86242 published, 8.1; 8 Sep 2026, transports 2.1.0, the fix; 14 Sep 2026, CVE-2026-90898 published, 9.8; 22 Sep 2026, vendor statement reported; 23 Sep 2026, GitHub advisories published. Below it, three bars show release lines: a hatched amber bar labelled '1.6.x line' reading 'affected — no patched release in the series; newest tag 1.6.11, 14 August 2026'; a bar labelled '2.0.0' split between a pale blue segment reading 'plugin flaw fixed' and a red segment reading 'MCP flaw still open'; and a solid blue bar labelled '2.1.0 and later' reading 'MCP fix — unauthenticated stdio registration returns 403'. A foot band headed 'THE PART THAT IS EASY TO GET WRONG' notes that 2.0.0 was the patched release on 6 September and did not close the MCP path, that for the two days before 2.1.0 an operator who patched on the day of the warning was still exposed, and that the 1.6.x series has no fixed release at all. A footer reads 'Card rendered by OrcaRouter'. The OrcaRouter logo is composited in the bottom-right corner.

Duas coisas aconteceram após a publicação que um defensor pode usar. Os avisos de segurança do GitHub do projeto — GHSA-86gf-xh3g-rvxq para a falha do MCP, em nível crítico, e GHSA-2qp8-4xgm-fw6g para a falha do plugin, em nível alto — foram publicados em 23 de setembro de 2026, dando aos feeds de dependências e de avisos um segundo identificador para fazer correspondência. E, em 13 de outubro de 2026, um template de detecção para CVE-2026-90898 foi incorporado ao repositório público nuclei-templates, o que significa que a verificação de uma tentativa de registro não autenticada agora é algo que um pipeline de varredura pode executar, em vez de algo que cada equipe precisa escrever.

Abstract illustration on a dark navy field: a wide translucent slab representing a credential store, filled with evenly spaced glowing key-shaped tokens, stands behind a low wall. A narrow gateway aperture in the wall holds a fresh, brighter set of tokens, a blank card-shaped slip lies pushed aside on the ground in front of it, and a thin amber arc sweeps from the aperture around to the store. A second gateway aperture in the background remains closed and unlit. No text, no people, no organisation logos.

O que permanece em aberto é a gravidade, e isso será ou não resolvido pelas duas organizações que ainda discutem o assunto. A posição da Maxim, conforme noticiado, é que um 9,8 superestima uma falha que precisa de um listener exposto e de um padrão não definido para ter relevância — uma alegação testável em princípio e não testada publicamente, porque ninguém publicou quantas implantações atenderam a essas duas condições. A posição da JFrog é a pontuação que atribuiu como CNA, ainda vigente no registro CVE e no NVD. Até que uma delas publique uma revisão, a leitura operacional é a mesma de qualquer forma: a falha é real e foi verificada de ponta a ponta na imagem de contêiner publicada, a correção foi lançada antes do aviso, a série 1.6 não tem correção alguma, e qualquer instância que tenha sido executada com autenticação desativada em um listener acessível deve ser tratada como um incidente de credenciais, e não como um patch a agendar.