Uma ilustração abstrata gerada sobre um fundo azul-marinho escuro: um pequeno cubo de servidor âmbar à esquerda emite uma linha fina ciano de formas semelhantes a glifos que atravessa diretamente uma alta membrana de vidro azul translúcido e continua até um painel de terminal escuro à direita, onde um único bloco de cursor âmbar brilha. A linha é contínua. Não aparecem textos, pessoas nem logotipos de organizações. O logotipo OrcaRouter está composto no canto inferior direito.
AI Safety Incidents

O login MCP do OpenCode entregou a URL de um servidor ao PowerShell — e não há CVE para sinalizar isso

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 19 de outubro de 2026, a Pillar Security divulgou uma falha de execução remota de código no OpenCode, o agente de codificação de código aberto mantido pela Anomaly: um servidor remoto de Model Context Protocol configurado por um desenvolvedor podia executar código arbitrário na própria máquina desse desenvolvedor durante o login OAuth do MCP, sem nenhuma solicitação de consentimento no meio. O bug ficou restrito ao Windows e ao Subsistema Windows para Linux, onde o OpenCode entregava a URL de login fornecida pelo servidor a um comando do PowerShell sem escapá-la. A Pillar situa o intervalo afetado entre 1.0.137 e 1.18.32. A Anomaly corrigiu o problema na versão 1.18.33, publicada no npm em 28 de setembro de 2026, e não solicitou CVE nem publicou qualquer advisory — de modo que nada em um feed normal de vulnerabilidades avisará uma equipe afetada de que precisa atualizar. A Pillar não relatou nenhuma evidência de que a falha tenha sido usada em um ataque. Este é um registro do arquivo de incidentes de IA, no qual cada entrada traz suas próprias fontes, gravidade, grau de confiança e sinalização de disputa.

Qual era realmente a falha

Quando um cliente MCP se conecta a um servidor remoto que exige autorização, ele executa um handshake de descoberta OAuth. O servidor responde com um 401 e um desafio apontando para seus documentos de descoberta, e um campo nesses documentos — authorization_endpoint — informa ao cliente para onde enviar o usuário para fazer login. É uma string de formato livre, e a parte que está sendo autenticada é a parte que a escolhe.

No OpenCode 1.18.32, essa string passou da rede para um shell. O Pillar traçou o caminho do documento de descoberta do servidor, passando pelo SDK do MCP, até oauth-provider.ts, mcp/index.ts e browser.ts, terminando em open, o pequeno pacote que o OpenCode usa para iniciar um navegador. Nada nesse caminho verificou o esquema da URL, e nada o comparou com a origem do servidor que o desenvolvedor havia configurado. O handshake é automático por concepção — o objetivo é justamente enviar você a uma página de login sem que você precise copiar uma URL —, então nenhuma etapa de aprovação ficou entre a resposta do servidor e o lançador.

The launcher is where it broke. On macOS and Linux, open passes the address as an argument vector and no shell is involved. On Windows, version 10.1.2 of open — the version every affected OpenCode release pinned — builds a PowerShell command, base64-encodes it and runs it with powershell -EncodedCommand. Pillar quotes the source: the application name is escaped on one line, and the target URL is not. PowerShell evaluates $(...) subexpressions inside double-quoted strings, so an address of the form https://evil.test/$([IO.File]::WriteAllText('C:\Users\Public\pwned.txt','RCE')) runs before the browser launch fails. OpenCode discards that failure.

Duas propriedades fizeram com que fosse fácil passar despercebido. O payload não contém espaços, então a normalização de URL o deixa intacto, e é um endereço https sintaticamente comum. E o servidor não precisava ser hostil quando foi configurado: Pillar observa que um comprometimento posterior, uma entrada de registro sequestrada, um typosquat ou um domínio expirado transformariam, cada um, uma entrada de configuração confiável em um mecanismo de entrega.

Quem foi exposto

A população exposta é composta por usuários de Windows e WSL que executam o OpenCode com um servidor MCP remoto configurado. A Pillar descreve o OpenCode como tendo aproximadamente 3 milhões de downloads semanais no npm e 211.000 estrelas no GitHub; o relatório da Infosecurity Magazine indica mais de 218.000 estrelas. Nenhum desses números é uma contagem de instalações afetadas, e ninguém publicou uma.

O gatilho é o único ponto em que as duas principais fontes divergem, e isso importa tanto para o risco quanto para a gravidade. A Pillar descreve a exploração como algo que não exige interação ou consentimento adicional do usuário. O The Hacker News, em seu relatório de 22 de outubro, diz que a etapa do navegador só é executada quando um desenvolvedor inicia o login — executando opencode mcp auth ou fazendo a solicitação correspondente — e que apenas ter o servidor configurado, ou abrir uma sessão, não chega a ela. De qualquer forma, o desenvolvedor não faz nada incomum; iniciar a autenticação contra um servidor já presente na configuração é rotina. Mas "nenhuma interação" e "uma interação rotineira" são afirmações diferentes, e a diferença influencia diretamente a pontuação.

A correção chegou descrita como uma refatoração.

A Pillar relatou a falha de forma privada por meio de um GitHub Security Advisory em 29 de agosto de 2026, com material completo de reprodução. Em 25 de setembro, ela deu seguimento fora da thread do advisory; a Anomaly confirmou que o relatório havia chegado à sua equipe e respondeu que servidores MCP maliciosos estavam fora do seu modelo de ameaças. No mesmo dia, o pull request #51414 — mesclado como commit 29f07e0c — foi integrado. Ele é descrito como a consolidação de oito pontos de chamada de inicialização do navegador em um único helper. A versão 1.18.33 chegou ao npm três dias depois, em 28 de setembro.

O patch tem três camadas. A dependência open mudou para 11.0.4, que envolve o alvo em aspas simples, e o PowerShell não expande nada dentro de aspas simples. Um novo openUrl() helper rejeita esquemas que não sejam HTTP(S). Uma verificação de esquema foi incluída no próprio redirectToAuthorization, no limite que a Pillar havia nomeado em seu relatório. Nem o pull request nem as notas de versão mencionam uma falha de segurança, e a Anomaly não solicitou CVE.

O The Hacker News informa que a política de segurança publicada pela Anomaly declara que os servidores MCP que um usuário configura estão "fora da nossa fronteira de confiança", e que a empresa emitiu avisos para outras falhas de execução de código do OpenCode este ano, incluindo uma corrigida em agosto. O relato da Pillar sobre a resposta que recebeu é mais direto: "atualizamos a dependência, mas, de modo geral, tentar lidar com um servidor MCP malicioso está fora do nosso modelo de ameaças."

An HTML timeline card titled 'How a five-year-old escaping bug reached OpenCode', subtitled 'Dated entries from Pillar Security's report and the open package's own issue history', listing nine rows: 22 October 2020, open issue #202 reports that a URL containing a dollar sign breaks on WSL 2; 18 October 2023, issue #323 titles 'OS command injection on windows when opening urls'; 9 July 2025, CVE-2025-6514 in mcp-remote, same sink, CVSS 9.6; 15 November 2025, open 11.0.0 quotes the PowerShell target; 7 December 2025, OpenCode calls open() with a server-supplied URL; 29 August 2026, Pillar reports privately via GitHub Security Advisory; 25 September 2026, pull request #51414 merged; 28 September 2026, OpenCode 1.18.33 published to npm, no CVE and no advisory; 19 October 2026, Pillar publishes. A footer cites Pillar Security and the open repository.

Lida em sequência, a linha do tempo coloca o bug do OpenCode no fim de uma trajetória de cinco anos, e não no início dela. O defeito que o produziu já era público, e sua correção já havia sido lançada, antes que a linha que o utilizava fosse escrita.

Por que a validação do esquema não teria impedido isso

O remédio acordado para esta classe de bugs é a validação do esquema de URL: bloquear os esquemas estranhos, permitir http e https, e pronto. É o que o MCP TypeScript SDK entrega, e é o que o OpenCode adicionou na 1.18.33. O payload do Pillar passa em todas essas verificações, porque é https. A lista de bloqueio do SDK bloqueia javascript:, data: e vbscript:; uma lista de permissões http/https mais estrita foi proposta no pull request #841 do SDK em agosto de 2025 e encerrada sem mesclagem, enquanto o pull request #877 entregou a lista de bloqueio de três esquemas na v1.17.4 — e a Pillar diz que essa ainda era a política no SDK 1.32.0 quando publicou. O que realmente fechou a brecha no OpenCode foi a atualização de dependência, não as verificações que parecem a correção de segurança.

O histórico argumenta contra tratar isso como um deslize de um único projeto. O pacote open carrega um aviso no README desde 2021 de que não oferece garantias de segurança e que sanitizar a entrada é responsabilidade de quem o chama. Em outubro de 2020, um usuário abriu a issue #202 relatando que uma URL contendo um cifrão perdia parte de si mesma no WSL 2 — a expansão da string, registrada como um incômodo de link quebrado. Em outubro de 2023, um engenheiro da Adobe abriu a issue #323, “injeção de comando do SO no Windows ao abrir URLs”, com uma prova de conceito de uma linha: open('https://$(calc.exe)'). O mantenedor citou o README e disse que pull requests melhorando o escape eram bem-vindos; a issue foi fechada como não planejada três dias antes de o open 11.0.0 lançar o escape mesmo assim, em 15 de novembro de 2025. O OpenCode escreveu sua chamada de abertura do navegador em 7 de dezembro de 2025, três semanas depois de a versão corrigida do open existir, com base em um pin que já tinha meses.

Nos meses anteriores à redação dessa chamada, o ecossistema MCP registrou três CVEs no mesmo sink ou no mesmo campo: CVE-2025-6514 em mcp-remote (CVSS 9.6, divulgado pela JFrog em 9 de julho de 2025), CVE-2025-58062 em openmcp-client, e CVE-2025-10619 em sequa-mcp. O contraste de Pillar se dá com clientes que nunca constroem um comando de shell a partir de uma string remota: ele cita gemini-cli, Claude Code, github-mcp-server e o mcp-gateway da Docker como exemplos que passam a URL como um vetor de argumentos, o que faz com que a questão sobre o que a string contém deixe de ser determinante.

A generated abstract illustration on a dark navy field: a long cyan ribbon of abstract glyph shapes runs left to right and splits in two at a hollow chrome ring, which the upper branch passes straight through while the lower branch curves downward into a glowing amber terminal rectangle at bottom right. A faint dotted outline of an empty browser window floats in the upper right. No text, people or organisation logos appear. The OrcaRouter logo is composited in the bottom-right corner.

O que está estabelecido e o que não está

O registo é classificado com confiança A pelo arquivo, e a reportagem que está por trás dele é sólida. A Infosecurity Magazine publicou, a 20 de outubro, a sua própria entrevista com Eilon Cohen, da Pillar; a The Hacker News publicou o seu próprio relato a 22 de outubro; a DKCERT, CERT nacional da Dinamarca, resumiu a descoberta a 21 de outubro, citando a Infosecurity; e o laboratório de investigação da Cloud Security Alliance publicou uma análise que acrescenta a única ressalva substancial abaixo. Nenhum destes é o veículo que fez a reportagem original, e todos concordam quanto ao mecanismo, às versões e à correção silenciosa. A própria Anomaly não publicou nada sobre a falha.

Estabelecido, para constar:

• O defeito, seu mecanismo e seu escopo de plataforma. A Pillar identifica linhas específicas do código-fonte e a correção é visível no diff público de 1.18.32 para 1.18.33; as duas reportagens independentes descrevem o mesmo fluxo de dados.

• O intervalo afetado, de 1.0.137 a 1.18.32, e a versão corrigida, 1.18.33, publicada em 28 de setembro de 2026.

• Que não existe nenhuma CVE nem nenhum aviso. Isso é verificável e é o fato fundamental para os defensores.

• Que nenhuma exploração foi relatada. A Pillar afirma que não viu sinais de uso em ataques, e o The Hacker News observa que nenhum indicador de comprometimento foi publicado. A ausência de indicadores publicados não é prova de ausência, e sem telemetria do fornecedor nenhuma das duas leituras pode ser confirmada.

Não estabelecido, ou em tensão:

• O 9.8. Esse número é a pontuação CVSS v3.1 proposta pela Pillar, não uma oficial: sem CVE, não há pontuação do NVD nem pontuação de fornecedor. A nota de pesquisa da Cloud Security Alliance observa que 9.8 pressupõe nenhuma interação do usuário e que, se o relato do The Hacker News sobre o gatilho estiver correto, uma classificação que exija interação do usuário — aproximadamente 8.8 — se encaixaria melhor. Este texto não resolve essa questão; a própria etiqueta de alta severidade do arquivo é uma classificação, não uma pontuação.

• A data de publicação. O relatório da Pillar está datado de 19 de outubro de 2026 no seu cabeçalho, e ambas as reportagens usam essa data; a cronologia de divulgação no rodapé do próprio relatório da Pillar indica a publicação como 4 de outubro. O arquivo registra 19 de outubro com precisão de dia.

• O tamanho da população exposta. Nenhuma contagem foi publicada. Os números de downloads e estrelas acima são métricas do repositório, não instalações.

• Se alguma máquina foi realmente comprometida. Nada do que foi publicado sustenta isso, e o registro não traz nenhum dano real.

An HTML card titled 'Established, and not', split into two columns. The left column, headed 'Established', lists: affected versions 1.0.137 to 1.18.32, Windows and WSL only; fixed in 1.18.33 on 28 September 2026; no CVE and no security advisory issued; no exploitation reported and no indicators published. The right column, headed 'Not established', lists: official severity, since 9.8 is Pillar's proposed score with no CVE to attach it to; the publication date, 19 October in the report header and 4 October in its own timeline; the number of exposed installations; whether any host was compromised. A footer cites Pillar Security, The Hacker News and the Cloud Security Alliance research note.

O que mudou e o que fazer

A remediação é uma verificação de versão, porque nada mais informará isso. O OpenCode 1.18.33 ou posterior está corrigido. As instalações afetadas precisam ser encontradas inventariando o pacote diretamente: a recomendação da Pillar é inventariar o próprio OpenCode em vez de esperar por um feed, e a nota da Cloud Security Alliance sugere consultar a versão do pacote opencode-ai, já que não há identificador para um feed corresponder. Equipes que não podem atualizar e executam Windows ou o Subsistema Windows para Linux devem remover servidores MCP remotos que não verificaram da sua configuração do OpenCode; opencode mcp list mostra quais servidores estão presentes.

Para quem mantém um cliente MCP, a orientação da Pillar é mais restrita do que o conselho usual: passe URLs como um vetor de argumentos e nunca construa uma linha de comando a partir de uma string remota, vincule a descoberta de OAuth à origem do servidor que o usuário configurou e trate documentos de descoberta, metadados de servidor e descritores de ferramentas como entrada não confiável, e não como configurações. A nota da Cloud Security Alliance acrescenta heurísticas de hunting — um processo OpenCode gerando powershell.exe com -EncodedCommand, por exemplo — enquanto enfatiza que estas são sugestões para engenharia de detecção, e não indicadores de comprometimento publicados.

Não é a violação do Console

A divulgação da Pillar ocorreu dias depois de a Anomaly confirmar uma violação separada do Console hospedado da OpenCode, que pode ter exposto chaves de provedores de API armazenadas. Os dois eventos não estão conectados, e Eilon Cohen, da Pillar, foi explícito sobre a diferença em sua entrevista à Infosecurity Magazine. "A violação atingiu um sistema legado por trás de um proxy de chaves hospedado e expôs chaves de provedor que os usuários haviam armazenado ali", disse ele. "A vulnerabilidade que relatamos segue o sentido oposto: um servidor MCP remoto malicioso executando código na própria máquina de um desenvolvedor durante o handshake OAuth. Alvo e posição do atacante diferentes." A violação do Console é um registro separado no arquivo, e os dois devem ser lidos como entradas separadas.

O que os conecta, na formulação de Cohen, é a pergunta por trás de ambos: "Quem você deixa entregar credenciais e insumos a uma ferramenta de codificação com IA, e o que essa ferramenta faz com eles."

A lacuna de divulgação é a parte que sobrevive ao bug. Uma falha que seus descobridores classificam como crítica, corrigida dentro de uma atualização de dependência e ausente de todos os sinais automatizados nos quais um defensor normalmente confia deixa o inventário direto como o único método de detecção — e o fornecedor não publicou nenhum aviso instruindo alguém a realizar um inventário.