Ilustração técnica abstrata sobre um fundo azul-marinho escuro: um chassi translúcido sustenta uma pilha de pequenos painéis arredondados, e um único canal escuro sem identificação desce do fundo dessa pilha em linha reta, atravessando o piso do chassi até um compartimento inferior não iluminado. Ao lado do canal, três pequenos portões pálidos permanecem fechados sobre uma prateleira, enquanto o próprio canal passa entre eles sem nenhum portão em seu caminho. Uma fina linha âmbar entra no chassi pela esquerda e desaparece na pilha. Sem texto, sem pessoas, sem logotipos de organizações, sem representação literal de qualquer sistema real.
AI Safety Incidents

MaxKB anexou uma ferramenta de shell a todo assistente habilitado para ferramentas e nunca a restringiu

Autor

Alistair Wren

Data de publicação

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

O MaxKB, uma plataforma de assistente empresarial de código aberto publicada sob a organização 1Panel-dev no GitHub, construiu seus agentes de chat sobre um framework que adiciona silenciosamente uma ferramenta de shell sempre que um back-end compatível com shell é fornecido — e o MaxKB nunca removeu a ferramenta nem pediu a ninguém que aprovasse seu uso. A falha é CVE-2026-77521, publicada como aviso do GitHub GHSA-f36j-f34j-h3rx em 2 de setembro de 2026 e com pontuação 10,0 de 10 sob CVSS 3.1 no caso de um assistente público ou incorporado. Lasso Security, que a encontrou e relatou, demonstrou que uma mensagem de chat — ou um texto que o assistente apenas ingere por meio de recuperação ou de um documento enviado — poderia levar o modelo a executar comandos: em uma implantação bare-metal diretamente no host e no contêiner oficial por meio de um wrapper que, segundo os pesquisadores, pode ser contornado com um ponto e vírgula. Nenhuma fonte citada registra a falha sendo explorada em ambiente real. O grau de severidade, a avaliação de confiança e a lista de fontes do próprio registro estão em o arquivo de incidentes de IA, ao lado das entradas vizinhas sobre MaxKB e ferramentas de agentes do mesmo lote de divulgação.

MaxKB é um produto auto-hospedado para criar assistentes com recuperação aumentada: um operador cria um assistente, anexa capacidades a ele — ferramentas, servidores Model Context Protocol, habilidades, subaplicações —, conecta uma base de conhecimento criada a partir de documentos enviados ou sites rastreados e, em seguida, expõe o assistente por meio de um console autenticado ou como um widget de chat público e incorporável. Essa versatilidade é a exposição. A condição de disparo do aviso não é uma configuração incomum, mas a comum: qualquer assistente com pelo menos uma capacidade anexada encaminha seu chat pelo caminho do agente afetado, enquanto um chat sem capacidades anexadas não o faz. O texto da Lasso descreve o projeto como um dos mais amplamente adotados em sua categoria e observa que o MaxKB normalmente é implantado como um serviço multilocatário — o que coloca um comando executado como o usuário da aplicação sob o modelo de multilocação, e não dentro da fatia de um locatário.

A ferramenta de shell veio com o framework, não com o produto

O MaxKB cria esses agentes com a biblioteca deepagents do LangChain, fixada na versão 0.6.11 no pyproject.toml do projeto tanto na tag vulnerável quanto na atual. Em apps/application/flow/tools.py, na linha 467 da tag v2.10.3-lts, o projeto chama create_deep_agent com backend definido como SandboxShellBackend, uma subclasse do MaxKB que executa comandos no host. De acordo com o aviso, o deepagents injeta automaticamente um conjunto de ferramentas sempre que um backend de shell é passado dessa forma: execute, ls, read_file, write_file, edit_file, glob e grep. Elas não fazem parte do argumento tools=list, que contém apenas as ferramentas do próprio operador, ferramentas MCP e ferramentas de skill. Elas não podem ser removidas da interface nem por meio de configuração.

MaxKB também não passa excluded_tools, o argumento da biblioteca que as removeria. O aviso é cuidadoso sobre por que isso importa mesmo como remédio: excluded_tools "remove a ferramenta daquilo que é informado ao modelo, não do executor". A distinção entre uma ferramenta da qual o modelo não tem conhecimento e uma ferramenta que não pode ser executada é o bug inteiro em miniatura.

Um gate que lista três ferramentas e omite a quarta.

O controle human-in-the-loop nessa mesma chamada é uma única linha, e ela enumera três operações: interrupt_on={"write_file": False, "read_file": False, "edit_file": False}. Escrever um arquivo, ler um arquivo e editar um arquivo estão nomeados. A execução de comandos não é uma chave no dicionário de forma alguma. Na leitura do comunicado, isso significa que nenhuma aprovação é solicitada para execute — as três operações de sistema de arquivos estão nomeadas e explicitamente definidas para não interromper, e a ferramenta de shell não está nomeada de forma alguma.

Juntando tudo, o caminho é: texto não confiável chega ao modelo, o modelo chama execute e o comando é executado. O aviso nomeia duas maneiras de texto não confiável chegar. A direta é o chat — um widget público ou incorporado, ou a conversa de outro tenant. A indireta é conteúdo que o assistente ingere: um documento de RAG, um arquivo enviado ou uma página web que a plataforma rastreia para uma base de conhecimento. O post da Lasso torna a segunda rota concreta, observando que "o conjunto de pessoas que podem colocar texto diante do modelo é maior que o conjunto de pessoas que podem conversar com ele".

Em uma instalação bare-metal, o comando é apenas um comando

Tudo o que o MaxKB faz em termos de contenção ocorre em apps/application/flow/backend/sandbox_shell.py e, na v2.10.3-lts, começa com um padrão. A linha 9 traz _enable_sandbox = bool(int(CONFIG.get("SANDBOX", 0))), e SANDBOX não aparece em Config.defaults em apps/maxkb/conf.py. Na ausência de uma configuração explícita MAXKB_SANDBOX, o valor é zero, o ramo do wrapper na linha 65 é ignorado, e execute chega a subprocess.run com shell=True diretamente no host, como o usuário que executa o serviço — root, na formulação do aviso, se o serviço for executado como root.

Essa é a configuração que os pesquisadores usaram para a prova de conceito no host. Eles executaram o código real do MaxKB a partir do código-fonte com MAXKB_SANDBOX não definida, criaram um assistente com uma ferramenta anexada e pediram a ele, em uma única mensagem de chat, que executasse comandos de informações do sistema. A ferramenta execute foi acionada e gravou um arquivo cujo conteúdo era a própria saída de uname, id e sw_vers do host — saída que, segundo o comunicado, foi confirmada ausente dentro de qualquer contêiner. O Lasso também registra o limite do que o deteve: um arquivo de prova com nome flagrante foi recusado pelo modelo, enquanto uma formulação operacional benigna não foi. O alinhamento do modelo, nas palavras deles, é "um obstáculo parcial, não um controle".

Na imagem oficial, o sandbox rodou e ainda assim vazou.

O contêiner oficial define MAXKB_SANDBOX=1 na imagem base, em installer/Dockerfile-base, linha 48, portanto o wrapper está ativo ali — e o wrapper é a segunda falha. Ele construía uma única string: env -i LD_PRELOAD=/opt/maxkb-app/sandbox/lib/sandbox.so seguido de gosu sandbox e então o comando fornecido pelo modelo, entregue a um shell executado como root. Como o comando era interpolado como texto, apenas o primeiro token dele ficava sob o gosu. Qualquer ponto e vírgula, pipe, redirecionamento ou substituição de comando na saída do modelo era avaliado pelo shell root externo antes que o sandbox sequer o visse.

A análise de Lasso mostra a forma funcional disso: um payload de env -i LD_PRELOAD=... PATH="$PATH" gosu sandbox ls; whoami; id, no qual ls é confinado, whoami não é, e tudo depois dele é executado livremente. Nos testes, os pesquisadores escreveram um arquivo de propriedade do root com um redirecionamento enquanto o comando interno em sandbox era bloqueado. Agravando isso, nem installer/Dockerfile nem installer/Dockerfile-base contém uma diretiva USER, então a imagem da aplicação é executada como UID 0 — o advisory relata a confirmação de root em tempo de execução. O contêiner, portanto, executava comandos de qualquer maneira, e o sandbox apenas decidia quais eram cosmeticamente atribuídos ao usuário de baixo privilégio.

O fluxo completo de ataque descrito pelo Lasso não precisa de nenhum acesso ao alvo. O atacante coloca comandos em uma página web, espera que o agente de uma vítima rastreie essa página e a inclua em uma base de conhecimento, e então a vítima faz uma pergunta comum. A resposta volta correta e legítima; o curl injetado já foi disparado contra o servidor do atacante. O aviso observa que os pesquisadores testaram apenas suas próprias implantações, não qualquer instância MaxKB de terceiros ou hospedada.

O que as fontes estabelecem, e o que simplesmente não é medido

O mecanismo, os dois modos de implantação, o crédito e a versão corrigida coincidem em quatro documentos: o aviso do GitHub, o registro do NVD publicado em 21 de setembro de 2026, o próprio relatório técnico da Lasso de 10 de setembro de 2026 e a reportagem do GBHackers de 22 de setembro de 2026, que é a única cobertura independente encontrada para esta CVE. Nenhuma fonte contesta qualquer parte da constatação, e o arquivo registra a entrada como incontestada em seu grau de confiança mais alto.

O que as fontes não contêm é qualquer medida de exposição. Não há contagem de implantações do MaxKB, nem contagem de assistentes expostos à internet ou embarcados, nenhum resultado de varredura, nenhuma telemetria e nenhuma vítima nomeada. Nada no registro mostra a falha sendo usada contra alguém, e a própria avaliação de exploração da CISA concorda: o bloco SSVC anexado ao registro do NVD em 22 de setembro de 2026 classifica a exploração como "poc", o caráter automatizável como "sim" e o impacto técnico como "total". O modelo EPSS da FIRST estimou a probabilidade de exploração nos próximos 30 dias em 1,05 por cento, o 64º percentil, em 27 de outubro de 2026, e a CVE não aparece no catálogo Known Exploited Vulnerabilities da CISA datado de 27 de outubro de 2026. A própria classificação do arquivo reflete as mesmas evidências: severidade alta, dano real falso.

A pontuação 10.0 merece que seu escopo seja declarado, porque é o número com maior probabilidade de ser citado fora de contexto. É a pontuação para o caso de assistente público ou incorporado, em que o vetor CVSS é AV:N/AC:L/PR:N/UI:N/S:C — acessível pela rede, sem privilégios, sem interação do usuário, com mudança de escopo porque um comando dentro do assistente atravessa para o sistema operacional host. A pontuação é da CNA, e a CNA aqui é o programa de avisos do GitHub, que também é para onde aponta o identificador de origem do registro CVE. A NVD traz o mesmo vetor como métrica secundária e, em 28 de outubro de 2026, lista a entrada com o status "Deferred", o que significa que a NVD publicou a análise do atribuidor, e não a sua própria.

Rendered two-column card with the kicker 'MAXKB · CVE-2026-77521' and the title 'What the sources establish, and what they do not', subtitled with its sources: GHSA-f36j-f34j-h3rx of 2 September 2026, the NVD record of 21 September 2026, Lasso Security's write-up of 10 September 2026, GBHackers of 22 September 2026, FIRST EPSS, the CISA KEV catalogue and the repository tags. The left column, headed 'Established' in blue, lists eight items: CVSS 3.1 base score 10.0 with the vector AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H for a public or embedded assistant; CWE-78 OS command injection, CWE-250 unnecessary privileges and CWE-749 exposed dangerous method; deepagents 0.6.11 auto-adding execute to any shell backend, with no excluded_tools passed by MaxKB; the approval map covering write_file, read_file and edit_file with execute not a key in it; affected at or below 2.10.3-lts per the advisory and at or below 2.10.4-lts per Lasso Security's write-up; fixed in 2.10.5-lts, published 6 August 2026, 27 days before the advisory; the CISA SSVC assessment of 22 September 2026 with exploitation poc, automatable yes and technical impact total; and EPSS 1.05 percent at the 64th percentile on 27 October 2026 with no listing in the CISA KEV catalogue of that date. The right column, headed 'Not established, or not measured' in amber, lists seven items: no exploitation in the wild recorded by any cited source, with the archive recording real harm as false; no count of affected, exposed or internet-facing deployments; no named victim and no evidence of use in any intrusion; NVD status Deferred, so the 10.0 is the assigner's analysis rather than NVD's; disagreement between the two primary sources on the affected range boundary; the researchers' testing confined to their own deployments; and no detection or triage guidance for either deployment mode. A footer reads 'Card rendered by OrcaRouter. The 10.0 is scored for a public or embedded assistant; the archive grades the record high.' The OrcaRouter logo is composited in the bottom-right corner.

O patch foi lançado um mês antes do aviso.

A cronologia corre de trás para frente a partir da publicação, e é a parte menos intuitiva do registro. Lasso relatou a falha de forma privada por meio do canal de avisos de segurança do GitHub em 8 de julho de 2026. A MaxKB respondeu no dia seguinte, limitando o relatório à imagem oficial e pedindo uma prova de conceito em contêiner; os pesquisadores forneceram isso e o bypass do sandbox em 10 de julho. Um commit de correção, 594f50f2, chegou em 9 de julho — um dia após o relato — e reescreveu sandbox_shell.py para que a string de comando do modelo fosse analisada primeiro e o prefixo gosu fosse aplicado a cada comando simples, e não apenas ao primeiro, com cada lista de argumentos colocada novamente entre aspas para que a substituição não pudesse escapar para o shell pai. O texto de Lasso descreve a mudança como a aplicação do prefixo gosu “a cada comando simples, não apenas ao primeiro”.

A versão que o continha, v2.10.5-lts, foi publicada em 6 de agosto de 2026. O aviso do GitHub foi publicado em 2 de setembro, a NVD publicou a CVE em 21 de setembro, o bloco SSVC da CISA foi adicionado e o GBHackers noticiou em 22 de setembro, e o próprio texto do Lasso apareceu em 10 de setembro — no meio dessa sequência, não no início. Um operador que acompanhava tags de versão em vez de feeds de avisos teve o patch cerca de quatro semanas antes do alerta.

O limite de versão merece mais atenção do que o advisory lhe concede, porque as duas fontes primárias divergem e o repositório resolve a questão. O campo de formulário do advisory registra as versões afetadas como "<= 2.10.3-lts", com uma nota de que isso foi verificado na 2.10.3-lts e de que o caminho vulnerável "provavelmente" afeta todas as versões que compilam agentes dessa forma. O próprio texto do Lasso declara o intervalo afetado como "<= 2.10.4-lts". As tags confirmam o intervalo mais amplo: a v2.10.4-lts, lançada em 16 de julho de 2026, traz o mesmo sandbox_shell.py de 75 linhas que a v2.10.3-lts, e o arquivo reescrito de 311 linhas aparece pela primeira vez na v2.10.5-lts. Um operador na 2.10.4-lts que tivesse lido apenas o intervalo do advisory teria concluído que estava fora dele. Não estava.

Rendered vertical timeline card with the kicker 'MAXKB · CVE-2026-77521' and the title 'Reported, fixed, released, disclosed', subtitled that the dates come from Lasso Security's disclosure timeline, the repository's release tags and commit metadata, the NVD record and GBHackers, and that every date is a single day. Ten dated entries run down a single spine: 8 July 2026, reported privately to 1Panel-dev through GitHub's advisory channel; 9 July 2026, fix commit 594f50f2 rewrites sandbox_shell.py and the vendor asks for a container proof of concept; 10 July 2026, the container proof of concept and the sandbox bypass supplied; 16 July 2026, v2.10.4-lts released, still carrying the 75-line unpatched sandbox_shell.py; 6 August 2026, v2.10.5-lts, the fixed release with a 311-line wrapper and gosu applied to every simple command; 2 September 2026, advisory GHSA-f36j-f34j-h3rx published with CVSS 10.0; 10 September 2026, Lasso Security publishes MaxKBypass; 21 September 2026, NVD publishes CVE-2026-77521, with the CISA SSVC added the next day and GBHackers reporting; 15 October 2026, v2.10.7-lts flips the code default SANDBOX from 0 to 1; 22 October 2026, v2.10.8-lts still builds the agent with SandboxShellBackend and still omits execute. A dark band at the foot headed 'The gap' reads that the fixed release preceded the advisory by 27 days, that v2.10.4-lts was released a week after the fix commit and does not contain the fix, and that the execute tool has never been gated because the approval map at v2.10.8-lts still names only write_file, read_file and edit_file. A footer reads 'Card rendered by OrcaRouter.' The OrcaRouter logo is composited in the bottom-right corner.

O que a correção não fez

O que a 2.10.5-lts corrige é o wrapper: ele não constrói mais uma única string de shell sob root. O que ela não faz é nada a respeito da ferramenta. A leitura direta do repositório na tag v2.10.8-lts, publicada em 22 de outubro de 2026, mostra que o agente ainda é construído com backend=SandboxShellBackend e interrupt_on ainda contendo exatamente três chaves — write_file, read_file e edit_file — sem execute. As duas primeiras sugestões de remediação do advisory, de construir sobre um backend sem execução por padrão e de adicionar "execute": True ao mapa de aprovação, não estão presentes nessa versão.

A recomendação fail-closed chegou mais tarde, na v2.10.7-lts, e é importante para o modo de implantação que estava em pior situação. Publicada em 15 de outubro de 2026, ela altera a linha em sandbox_shell.py de CONFIG.get("SANDBOX", 0) para CONFIG.get("SANDBOX", 1). Uma instalação a partir do código-fonte ou bare-metal que nunca definiu a variável agora tem o wrapper ativado por padrão, em vez de desativado, o que é a recomendação de "fail closed on non-container deploys" no sentido restrito. O aviso pedia mais do que isso sob o mesmo título — que o fluxo com capacidade de execução se recusasse a iniciar quando o runtime do sandbox estivesse indisponível — e pedia separadamente que o wrapper nunca construísse uma string de comando para um shell de root. No lado dos contêineres, um fato em vez de uma recomendação: nem installer/Dockerfile nem installer/Dockerfile-base contêm uma diretiva USER na tag v2.10.8-lts, portanto a imagem da aplicação ainda inicia como root.

Lidos em conjunto, o estado do registro em 28 de outubro de 2026 é este. A segunda metade da vulnerabilidade — a sandbox da qual um ponto e vírgula escapou — está fechada, e o padrão fail-open em implantações no host está fechado. A primeira metade, uma ferramenta execute que chega com um objeto de backend e não é uma chave no mapa de aprovação, continua sendo como o MaxKB constrói um assistente com ferramentas habilitadas. O próprio conselho de remediação dos pesquisadores foi o mais restrito: atualizar para 2.10.5-lts ou posterior e executar a versão Docker com a sandbox habilitada. O GBHackers repassou a mesma instrução, além de uma lista mais ampla para administradores — desabilitar backends de agentes com capacidade de shell, a menos que a execução de código seja explicitamente necessária, exigir aprovação humana antes de qualquer ação execute, executar contêineres como não root e tratar páginas rastreadas, documentos RAG e uploads como entrada não confiável.

O outro registro do MaxKB do mesmo lote de setembro

A segunda entrada de MaxKB no arquivo deste lote é um bug diferente, com um desfecho pior. O CVE-2026-77516, também publicado no NVD em 21 de setembro de 2026, é um bypass de permissão, e não uma injeção de comando: da versão 2.0.0 até a 2.9.2, um membro de workspace com o papel mais baixo, explicitamente impedido de acessar uma ferramenta por meio de WorkspaceUserResourcePermission, ainda podia vincular o identificador dessa ferramenta por meio de tool_ids, skill_tool_ids ou mcp_tool_ids e executá-la pelo caminho de despacho do agente ou do fluxo de trabalho. O caminho de despacho não reaplica a concessão por ferramenta que as rotas dedicadas de ferramentas impõem, e a execução da ferramenta descriptografa init_params no lado do servidor, de modo que o chamador recebe credenciais carregadas pela ferramenta à qual teve o acesso negado. Sua pontuação é 5.4, e a descrição do NVD termina com uma frase que o CVE-2026-77521 não precisa carregar: "Nenhuma versão corrigida está disponível até o momento desta análise."

O contraste é a parte útil para quem está triando o par. A falha que recebeu pontuação 10,0 teve uma correção commitada em menos de um dia e lançada um mês antes de ser publicada. A falha que recebeu pontuação 5,4 não tinha versão corrigida publicada no momento do seu CVE.

Abstract illustration on a dark navy field: a tall translucent shelf holds a row of small pale gate symbols, and a wide unbroken corridor runs beneath the shelf from left to right with nothing standing in it. At the corridor's midpoint a thin amber line drops down from the shelf above and joins the corridor floor, and a small cluster of glowing key-shaped tokens rests just past the join, out of reach of the gates. No text, no people, no organisation logos, no literal depiction of any real system.

O que permanece genuinamente em aberto é menor do que a pontuação sugere e maior do que uma nota de correção implica. A descoberta não está em disputa, e o mecanismo foi verificado de ponta a ponta nos dois modos de implantação pela equipe que o descobriu. A exposição é totalmente não mensurada — ninguém publicou quantos assistentes MaxKB possuem uma ferramenta, quantos deles são alcançáveis por uma parte não confiável ou quantos são executados em um host sem o sandbox —, então a consequência real da falha é função de hábitos de implantação que nenhuma fonte citada contabiliza. E a parte do design que levou a pontuação ao máximo ainda está presente na versão atual: uma capacidade que executa comandos, anexada por padrão, ausente do mapa que pergunta primeiro a um humano.