Voltar para todas as publicações
Publicado em · por Renaud Deraison

O IDE na aba entregou um token do GitHub num clique

Um zero-day no github.dev permitiu que um painel de pré-visualização malicioso saísse do seu sandbox, instalasse silenciosamente uma extensão e lesse um token OAuth do GitHub com acesso a cada repositório privado que a vítima conseguisse tocar. A correção é honesta quanto aos seus limites — a jogada mais afiada é nunca levar o seu token ao repositório de um estranho, para começar.

Abra um repositório no github.dev, clique num link, e um editor a correr dentro de uma aba do navegador instalou silenciosamente uma extensão, leu o seu token OAuth do GitHub e começou a listar os seus repositórios privados. Sem download. Sem botão «Permitir». O IDE inteiro vive numa página web — que é exatamente a razão pela qual o raio de explosão é uma pergunta sobre o navegador, não sobre o IDE.

Em 2 de junho de 2026, o investigador de segurança Ammar Askar publicou uma prova de conceito para um zero-day no github.dev — a versão no navegador do Visual Studio Code que se alcança premindo . em qualquer repositório do GitHub. Um zero-day é um bug que o fornecedor não teve tempo de corrigir porque se tornou público no mesmo momento em que se tornou conhecido. Neste caso, segundo o relato de Askar, os detalhes públicos saíram cerca de uma hora depois de a Microsoft ter sido notificada. Ele disse ter passado para a divulgação pública total das descobertas sobre VS Code por frustração com a forma como relatórios anteriores ao Centro de Resposta de Segurança da Microsoft tinham sido tratados.

A mecânica merece que abrandemos sobre ela, porque é um exemplo limpo de uma categoria — não um bug isolado, mas uma forma de ataque que as ferramentas de desenvolvimento baseadas em navegador vão continuar a produzir.

Um painel de pré-visualização não devia ser uma rampa de lançamento.

Os editores de código renderizam muito conteúdo não confiável. Um ficheiro Markdown que abriu recebe uma pré-visualização renderizada. Um notebook Jupyter mostra a sua saída. Estas pré-visualizações correm dentro de um webview — um mini-navegador em sandbox embutido no editor, deliberadamente isolado dos próprios privilégios do editor para que um README malicioso não possa simplesmente tomar conta da sua máquina.

Esse muro é a questão toda. O exploit de Askar passou por cima dele.

O webview comunica com o editor principal através de um canal de troca de mensagens — um cano estreito que os dois lados usam para se coordenar. Abusando desse canal, o JavaScript malicioso a correr no webview não confiável conseguiu simular toques de tecla — eventos keydown sintéticos — na janela principal do editor. Os toques que escolheu foram Ctrl+Shift+P, o atalho que abre a Command Palette, a caixa de texto a partir da qual o VS Code pode correr essencialmente qualquer comando que conheça.

A partir daí o ataque usou uma funcionalidade legítima contra si própria. O VS Code suporta extensões de workspace local: extensões colocadas na pasta .vscode/extensions de um projeto, pensadas para que um repositório possa trazer as suas próprias ferramentas. Como um repositório malicioso controla os seus próprios ficheiros, pode trazer a sua própria extensão — e o aviso de confiança que normalmente pergunta «quer mesmo correr o código deste publicador?» foi contornado fabricando keybindings personalizados no package.json da extensão. O diálogo de confiança no publicador, o único ponto de controlo humano da cadeia, nunca apareceu.

1 · WEBVIEWPainel depreview maliciosoJS não confiável corre2 · TECLASForjaCtrl+Shift+Ppelo cano de mensagens3 · PALETTECommandPalette abrecorre qualquer comando4 · EXTENSÃOInstala workspacelocalaviso de confiança salta5 · TOKENToken OAuthlido + enviadoenumera repos privadosUm clique para abrir o repo. Tudo a partir daí é automático.
A cadeia de um clique do github.dev. Um painel de pré-visualização (um webview em sandbox) conduz o editor onde vive: forja um toque Ctrl+Shift+P, abre a Command Palette e dispara uma extensão de workspace local cujos keybindings saltam o aviso de confiança no publicador. A extensão lê então o token OAuth do GitHub que a página estava a segurar.

O prémio não era o repo que abriu.

A carga útil desta cadeia é um token. O github.dev autentica-o no GitHub e segura um token OAuth — uma credencial que o navegador apresenta aos servidores do GitHub para provar que está a agir em seu nome. O objetivo do OAuth é que o token possa ser limitado em escopo: uma app só deve receber o acesso estreito de que precisa.

Este token não era estreito. Como Askar colocou, o token «não está limitado ao repositório em particular com que interagiu, o que significa que tem acesso total a todos os outros repos a que tem acesso» — leitura e escrita, incluindo repositórios privados. Por isso o atacante não ficou com o projeto público em que clicou. Ficou com uma chave para tudo o que a sua conta consegue alcançar: os seus repos privados, os repos privados do seu empregador se tiver acesso, as deploy keys e segredos parados nesses repos, o código-fonte que nunca mostrou a ninguém. A prova de conceito usou-o para enumerar os repositórios privados da vítima — uma lista que, para a maioria dos programadores em ativo, é ela própria sensível.

Esta é a parte que generaliza. Os IDEs baseados em navegador e os ambientes de desenvolvimento na nuvem são convenientes precisamente porque carregam as suas credenciais por si. O github.dev segura um token do GitHub. Um IDE na nuvem segura um token da nuvem. Um assistente de codificação agêntico a correr numa aba do navegador segura o que quer que precise para enviar código e chamar APIs. Cada um deles é um segredo de alto valor parado a um escape-de-sandbox de distância de uma página web que você não escreveu.

A parte honesta: está corrigido?

Dois relatórios, dois retratos diferentes, e a lacuna importa.

A BleepingComputer, à data de escrita, descreveu o problema como não tendo nenhum patch oficial e nenhum CVE atribuído, e ofereceu uma solução manual: limpar os cookies e os dados de site locais do github.dev para que o aviso inicial de início de sessão reapareça.

A The Hacker News transportou declarações de engenheiros da Microsoft. Alexandru Dima, um Partner Software Engineering Manager, disse «este problema não afeta o VS Code Desktop» — o bug é específico do github.dev hospedado no navegador, não da app que se instala na sua máquina. A Microsoft afirmou mais tarde que a vulnerabilidade «foi mitigada para os nossos serviços e nenhuma ação do cliente é necessária», o que aponta para uma alteração do lado do servidor em vez de um patch de cliente que se descarrega.

Não estamos em posição de verificar a mitigação de forma independente, por isso não lhe vamos dizer que a ameaça acabou. Aquilo de que podemos falar é onde o estrago cai quando uma cadeia como esta funciona — porque essa é uma pergunta de arquitetura, e a arquitetura é a parte que não depende de confiar num comunicado à imprensa.

Onde o IDE corre realmente.

Eis o que torna o github.dev interessante para nós: o editor inteiro é uma página web. O webview, a Command Palette, o host de extensões, o token OAuth — tudo isso vive dentro de uma aba do navegador. O que significa que a pergunta «quanto dano isto pode causar» é, por uma vez, a mesma pergunta que o Bromure foi construído para responder sobre qualquer aba.

No Bromure, cada aba corre dentro da sua própria máquina virtual descartável — um convidado Linux descartável no Mac, sem caminho para os seus ficheiros, o seu keychain ou as suas outras abas. Corra o github.dev num perfil Bromure e o token OAuth roubado, o webview malicioso e a extensão de workspace local instalada silenciosamente estão todos limitados a essa única VM. Feche a janela numa sessão não persistente e o mundo em que viveram é apagado: a cache do token, os cookies, a extensão, o convidado inteiro, tudo.

Navegador convencionalUM PERFIL PARTILHADOaba github.devrepo malicioso abertotoken OAuth roubadoalcança o mesmo pote que:GitHub do trabalhoRepos privadosOutros loginsFeche a aba e o token,cookies e extensão sobrevivem.A persistência é o padrão.BromureUMA VM DESCARTÁVELPERFIL SELADOaba github.devrepo malicioso abertotoken OAuth roubadoCONTIDO SÓ NESTA VMGitHub trabalhooutra VMBancooutra VMPessoaloutra VMFeche a janela:token, extensão e VM são apagados.
O mesmo exploit do github.dev, dois navegadores. À esquerda, um navegador convencional: a aba partilha um pote de cookies e um perfil com cada outra sessão GitHub que tem, e o token roubado é de longa duração. À direita, o Bromure: a aba é uma VM descartável. O token, o webview e a extensão plantada estão limitados a um perfil que é descartado quando o fecha. E a versão mais afiada não está retratada — abra os repos de estranhos num perfil que nunca iniciou sessão, e não há token nenhum para roubar.

Duas coisas que esta geometria muda, e uma que não muda.

Muda o que o token consegue alcançar. Num navegador convencional, cada sessão GitHub que tem partilha um pote de cookies e um perfil. Um token tirado da sua aba github.dev fica ao lado de tudo o resto que esse navegador segura. No Bromure, pode correr o github.dev no seu próprio perfil — a sua própria VM, os seus próprios cookies, o seu próprio armazenamento — separado do seu banco, do seu email e das suas outras identidades GitHub. O comprometimento do perfil descartável não dá ao atacante os cookies dos outros. Não estão na mesma máquina.

Muda quanto tempo o ponto de apoio dura. A jogada mais valiosa nesta cadeia é a extensão instalada silenciosamente — um ponto de apoio que persiste cada vez que reabre o editor. Contra uma sessão descartável, não há nada a que voltar. A extensão foi instalada numa VM que já não existe.

O que não resolve.

Não torna o token roubado em não-roubado. Enquanto a sessão maliciosa estiver viva, o token OAuth é real e o atacante pode usá-lo para enumerar e ler os seus repositórios privados em tempo real, a partir da sua própria infraestrutura. O isolamento contém onde o segredo vive; não atravessa a internet até aos servidores do GitHub para revogar uma credencial que o atacante já segura. As mitigações aí são as comuns: tokens de curta duração e estritamente limitados em escopo, revogar sessões depois de qualquer coisa suspeita, e um fornecedor — a Microsoft, aqui — a fechar o escape para que o token nunca seja alcançável, para começar.

Vale a pena ser preciso sobre uma comparação, porque é fácil baralhá-la. O Bromure não permite de todo que se instalem extensões do Chrome — nem em sandbox, nem curadas, nem de loja nenhuma. Essa é uma postura de produto deliberada: a extensão de navegador é um dos pontos de apoio mais abusados da web moderna, por isso o Bromure remove a categoria. Mas a extensão desta história é uma extensão VS Code, instalada pela web app github.dev no seu próprio editor — uma coisa diferente de uma extensão do Chrome, vivendo dentro da página em vez de à sua volta. A regra de zero-extensões do Bromure não chega até dentro do github.dev para a parar. O que o Bromure faz é conter o editor inteiro, token e extensão e tudo, dentro de uma VM que pode deitar fora.

A menos que não haja token para roubar.

Há uma forma mais afiada de usar a mesma arquitetura, e não custa nada: separar quem você é de o que visita.

A cadeia inteira existe para alcançar um segredo — o token OAuth que o github.dev segura porque iniciou sessão. Esse token só precisa de existir onde trabalha no seu próprio código. Por isso dê-lhe exatamente esse território: um perfil Bromure dedicado, com sessão iniciada no GitHub, onde abre os seus repositórios e os repositórios em que já confia. O token vive ali, e o código de estranhos não.

Tudo o resto — o repo interessante de um link, a prova de conceito que alguém publicou, a dependência que está a avaliar — abre-se algures onde você não é ninguém: um perfil que nunca iniciou sessão no GitHub. Leia o código no github.com como um visitante anónimo; se for à procura do editor, o github.dev sem início de sessão não tem nada que valha a pena entregar. Uma sessão não autenticada não pode vazar um token que não segura. A cadeia de exploit corre, se é que corre de todo, dentro de uma VM descartável com os bolsos vazios.

Isso muda a forma da defesa. A contenção limita o estrago no passo cinco, depois de o token ser levado. A separação decapita a cadeia no passo um: o repositório malicioso nunca encontra a credencial. A disciplina cabe numa linha — tenha sessão iniciada onde trabalha, seja ninguém onde vagueia — e os perfis Bromure tornam-na um hábito de dois ícones em vez de uma política de segurança.

A lição geral sobrevive a este bug em particular. À medida que mais do desenvolvimento se muda para o navegador — IDEs na nuvem, github.dev, agentes de codificação agênticos que correm numa aba e carregam acesso de push — as credenciais que essas ferramentas seguram tornam-se um alvo permanente, a um escape-de-webview de distância de uma página que você não escreveu. A postura defensável não é «confie no sandbox dentro do IDE». É assumir que esse sandbox acabará por vazar, e arranjar as coisas de modo que a página para onde ele vaza seja ao mesmo tempo descartável e sem fundos.

Corra a aba arriscada no seu próprio mundo — um mundo onde você não é ninguém. Quando algo entra, não há nada a levar, e você fecha o mundo de qualquer forma.

É para isso que serve o Bromure. Instale-o, dê ao seu próprio GitHub um perfil só dele, visite o código de toda a gente como um estranho, e torne o pior caso numa janela que pode fechar.