1 pontos por GN⁺ 3 시간 전 | 1 comentários | Compartilhar no WhatsApp
  • github.dev usa um token OAuth repassado por github.com para abrir arquivos, enviar PRs e fazer commits no VSCode no navegador, e como esse token não é limitado a um repositório específico, ele pode ler e escrever em todos os repositórios aos quais o usuário tem acesso
  • O webview do VSCode é isolado em um iframe vscode-webview://..., mas, por causa da UX de atalhos de teclado, o keydown do webview é encaminhado para a janela principal como uma mensagem did-keydown, permitindo que scripts não confiáveis enviem eventos como se fossem entradas do usuário
  • A entrada de texto arbitrária não funciona por causa do HTML <input>, mas é possível executar o comando de instalação de extensão combinando o atalho padrão Ctrl+Shift+A, a notificação de instalação de extensão recomendada, local workspace extensions e keybindings personalizados
  • O PoC executa JavaScript em uma célula Markdown de um Jupyter notebook para aceitar a instalação da extensão recomendada, instalar a extensão escolhida com um novo keybinding e então exibir o token da API do GitHub e a lista de repositórios privados
  • O VSCode desktop também tem a mesma vulnerabilidade, mas o atacante precisa induzir a clonagem do repositório e a abertura do notebook; usuários do github.dev precisam limpar os dados do site para que a caixa de diálogo inicial de confirmação volte a aparecer

Visão geral da vulnerabilidade

  • O github.dev abre uma versão leve do VSCode executada no navegador quando se troca a URL de um repositório GitHub acessível de github.com para github.dev ou se clica em um item de menu
  • Esse VSCode no navegador pode visualizar arquivos do repositório, abrir repositórios privados e também enviar PRs e criar commits
  • O github.com envia por POST para o github.dev um token OAuth capaz de interagir com o GitHub em nome do usuário, e esse token não é restrito ao repositório específico com o qual o usuário interagiu
  • Um atacante pode roubar um token do GitHub com permissões de leitura e escrita apenas com um clique em um link, e o alcance inclui repositórios privados

Isolamento de Webview e problema no encaminhamento de teclas

  • Os webviews do VSCode usam um <iframe> de origem diferente da janela principal do VSCode para isolar a execução de JavaScript
  • A saída de notebooks Jupyter é renderizada em um <iframe> com origem vscode-webview://..., enquanto a janela principal do Electron usa a origem vscode-file://...
  • Graças a esse isolamento, mesmo que o notebook use exibição em HTML ou widgets interativos baseados em JavaScript, ele não consegue chamar as APIs Node.js do Electron nem a API do VSCode de dentro do iframe
  • Recursos que exigem cooperação entre a janela principal e o webview, como a pré-visualização de Markdown, trocam mensagens por meio da API Window.postMessage()
  • O VSCode encaminha eventos did-keydown para a janela principal para que atalhos como Ctrl+Shift+P funcionem mesmo quando o foco está dentro do webview
  • Scripts não confiáveis dentro do webview podem disparar diretamente eventos keydown e se passar pelo usuário pressionando teclas

Cadeia de ataque

  • É possível abrir a paleta de comandos com Ctrl+Shift+P, mas como ela usa um HTML <input>, a técnica de inserir texto arbitrário não funciona
  • Entradas tratadas como keydown, como setas direcionais e Enter, podem ser usadas, assim como o conjunto padrão de atalhos do VSCode
  • Ctrl+Shift+A é o keybinding padrão de “Notifications: Accept Notification Primary Action” e aciona o botão principal da última notificação do VSCode
  • Se houver extensões recomendadas em .vscode/extensions.json, o VSCode mostra uma notificação para instalação, mas o sistema de confiança de publicador do VSCode 1.97 exibe uma caixa de diálogo separada ao instalar uma extensão de um novo publicador
  • Dá para mover entre botões com Tab, mas como o tratamento de Enter do botão “Trust Publisher & Install” está preso ao keydown do próprio botão, é difícil concluir a instalação só por esse caminho
  • local workspace extensions permitem instalar diretamente extensões presentes em .vscode/extensions dentro de um workspace confiável, e workspaces web do github.dev estão sempre em estado confiável
  • Se tentar executar diretamente uma extensão local do workspace, o worker de extensões espera uma extensão vinda de vscode-cdn.net, gerando um erro de CSP
  • Em vez disso, é possível adicionar um keybinding personalizado no package.json da extensão local do workspace para que esse keybinding invoque workbench.extensions.installExtension com o contexto skipPublisherTrust

Funcionamento do PoC e impacto

  • A configuração necessária é um repositório com um Jupyter notebook e uma local workspace extension
  • A célula Markdown do notebook pode executar JavaScript por meio do atributo onerror de uma imagem
  • O payload espera até que o VSCode mostre a notificação de instalação da extensão recomendada e então envia um evento Ctrl+Shift+A para aceitar a ação principal da notificação
  • Depois, espera a extensão ser instalada e ativada e o keybinding personalizado ficar disponível, e então dispara Ctrl+F1 para acionar a instalação da extensão escolhida
  • A extensão instalada no PoC obtém o token da API do GitHub, consulta https://api.github.com/user/repos para recuperar os repositórios privados acessíveis e então mostra o token e a lista de repositórios em uma caixa de informação
  • Após executar o PoC, é preciso limpar os dados do github.dev ou remover a extensão do PoC; se ela não for removida, continuará presente em todas as páginas do github.dev
  • O VSCode desktop também é afetado pela mesma vulnerabilidade, mas o atacante precisa convencer a vítima a clonar o repositório e abrir o notebook com o payload de script no webview
  • Se o webview aberto pela vítima tiver outro XSS, isso pode na prática evoluir para execução remota de código quase total também no desktop

Defesa e fatores de mitigação

  • Se você nunca usou o github.dev antes, existe uma caixa de diálogo inicial que precisa ser clicada ao entrar no site, criando uma chance de sair da página de ataque
  • Ao limpar os cookies e os dados locais do site do github.dev, essa caixa de diálogo inicial pode voltar a aparecer
  • No Chrome, é possível clicar no ícone da barra de endereço e ir em Cookies and site data > Manage on-device site data para remover os dados dos domínios relacionados
  • Se o usuário já passou pela caixa de diálogo do github.dev e não limpou o armazenamento local do navegador, o github.dev não tem proteções como token CSRF, então qualquer link na internet pode redirecionar para o ataque
  • O VSCode não depende apenas do isolamento por iframe e também usa uma Content Security Policy rígida e o DOMPurify
  • Como a pré-visualização de Markdown da página de extensões usa script-src 'none' para impedir execução arbitrária de JavaScript, o impacto maior de um RCE desktop com 1 clique apenas por um link de extensão acaba bloqueado

Contexto da divulgação e cronograma

  • O MSRC no passado corrigiu silenciosamente relatos de bugs do VSCode sem dar crédito e os marcou como sem impacto de segurança
  • Um relato recente do bug de XSS no VSCode da Starlabs também foi marcado como inelegível e de baixa severidade
  • Pode ser que a equipe do VSCode precisasse de mais tempo para equilibrar UI/UX e segurança, mas a divulgação completa foi escolhida porque o tempo e o esforço de pesquisadores de segurança não devem ser tratados como algo garantido
  • A divulgação planejada foi informada uma hora antes da publicação, em 2 de junho de 2026, para um contato existente da equipe de segurança do GitHub
  • A vulnerabilidade foi publicada no mesmo dia e também registrada no issue tracker do VSCode

1 comentários

 
GN⁺ 3 시간 전
Comentários do Hacker News
  • Foi um bom resumo e, no panorama geral, é lamentável o próprio fato de o editor VSCode embutido na web estar logado no GitHub
    Independentemente de haver defesa em profundidade, esse pecado original já cria uma superfície de ataque enorme. É parecido com deixar em texto puro na workstation um token da API do GitHub com todas as permissões, para qualquer pacote NPM malicioso conseguir encontrar
    No cenário ideal, a IDE no navegador rodaria com um escopo temporário por repositório ou um token que só permitisse pull/push naquele repositório, e não teria nenhuma sessão web do github.com. Se precisar da UI web completa do GitHub, volta para o github.com, e o github.dev fica como um serviço de repositório único
    Mas isso seria incômodo para o usuário, difícil de implementar, e provavelmente entra em conflito com premissas históricas espalhadas por todo o ferramental do github.dev

    • O Codespaces realmente faz isso. O token só tem permissão de leitura/escrita no repositório do Codespace ativado [1]
      O github.dev também deveria considerar seriamente essa abordagem
      [1] https://orca.security/resources/blog/hacking-github-codespac...
    • O problema de pacotes NPM maliciosos provavelmente só vai piorar. Recentemente vi ferramentas de execução com IA como o OpenCode baixando pacotes npm arbitrários em segundo plano e espalhando-os pelo diretório home e pelo diretório do projeto sem nem avisar nem perguntar ao usuário
      O pior é que parece que até os próprios desenvolvedores não ligam muito para isso
    • Estar logado ao abrir o próprio repositório tudo bem, mas ao abrir o repositório de outra conta isso nunca deveria acontecer. E os atalhos de teclado do webview também deveriam ser corrigidos para só permitir keybindings inofensivos e não se propagarem para nenhum handler de keydown
      No desktop, parece melhor fazer o Electron interceptar isso diretamente e remover esse recurso; na web, o certo seria deixar desativado por padrão
    • Dá para chegar em algo parecido usando chaves SSH e GitHub deploy key. Não posso garantir a segurança, mas nunca usei uma configuração do GitHub com acesso a todos os repositórios
      Também não sei se outros hostings Git têm algo parecido
    • Talvez fosse melhor permitir pull nesse repositório, mas fazer o push ir não para um token e sim apenas para uma área de staging da qual o usuário possa fazer o push final
      Sinceramente, agentes com LLM também deveriam funcionar assim. Deixar o LLM fazer push direto parece imprudente
  • O que torna esse ataque especialmente complicado é que extensões do VSCode rodam com o mesmo nível de confiança do próprio editor, e a maioria dos desenvolvedores instala dezenas de extensões sem revisar permissões
    Se uma extensão maliciosa ou comprometida vazar silenciosamente o token do GitHub, é difícil perceber sem monitoramento de rede, o que reforça a ideia de que extensões deveriam rodar em perfis isolados

    • Mesmo com monitoramento de rede, é muito difícil bloquear se o vazamento for para o próprio GitHub. Especialmente sem interceptação SSL e uma lista de URLs permitidas muito rígida
      O melhor caminho é sair do GitHub e migrar para um GitLab/Forgejo interno self-hosted, bloqueando completamente o GitHub
  • Recentemente passei por algo parecido. Roubaram meu token do GitHub e meu token da Cloudflare
    Acho que, por mais a sério que se leve segurança, se o tempo for longo o bastante, uma hora você vai ser atingido. O melhor é isolar e controlar o alcance do dano
    Não confie em ninguém nem em nada, use OrbStack e sempre trabalhe assumindo que seus tokens vão vazar algum dia
    Meu fluxo de trabalho foi completamente interrompido, mas felizmente quem pegou os tokens parecia mais um bot de spam. Criaram um monte de páginas falsas de spam e tentaram minerar criptomoeda
    O sentimento que mais fica é o de violação. Tomem cuidado

    • Fico curioso se eram páginas como no GitHub Pages. Criaram repositórios na sua conta? E também queria saber como você descobriu que o token tinha vazado
  • A parte sobre ter reportado o bug do VSCode ao MSRC e eles simplesmente corrigirem em silêncio foi uma experiência horrível bem típica do MSRC. Parece que perceberam que os pesquisadores vão reportar de graça de qualquer jeito, então não veem motivo para mudar

    • O MSRC não é quem corrige os bugs
      Não conheço os detalhes específicos deste caso, mas no passado já administrei programas de bug bounty via Bountysource e HackerOne. Às vezes, antes de a equipe de segurança terminar a avaliação, o relatório acaba chegando primeiro à equipe de desenvolvimento
      Nesse ponto, o desenvolvedor pode corrigir em silêncio. Às vezes por receio, racional ou não, de que, por estar associado a um bug de segurança, isso fique mal para ele ou afete chances de promoção. O resultado é que, quando a equipe de segurança vai tentar reproduzir, a vulnerabilidade já desapareceu
      Do ponto de vista do MSRC, eles só veem que os passos de reprodução fornecidos já não funcionam mais. Não têm visibilidade do histórico interno do bug nem de que alguém já aplicou um patch. Então o relatório é encerrado como inválido, mesmo que a descoberta original tenha sido legítima
    • Por muito tempo esse foi o status quo, até que pesquisadores de segurança inconvenientes começaram a exigir recompensa em vez de reputação
  • Obrigado por praticamente doar o tempo gasto neste exploit e, com isso, mostrar a necessidade de melhorar a resposta de segurança do VS Code. Você poderia simplesmente ter desistido, mas continua ajudando

    • Não pretendo vender nem guardar essa vulnerabilidade. Só que levar algumas horas para montar uma prova de conceito e depois o fornecedor apenas corrigir em silêncio, sem dar crédito nem reconhecimento, realmente deixa um gosto muito ruim
  • Não entendo muito bem por que mais desenvolvedores não tentam usar Neovim
    Pode ser questão de preferência, mas gosto de uma configuração pequena em que dá para entender o que está instalado e o que está em execução. Quando VSCode, IDE no navegador, extensões, sincronização, tokens e plugins aleatórios se misturam, fica difícil saber o que tem acesso a quê

    • Alguns anos atrás, larguei o VS Code e migrei para o Neovim. Foi depois de descobrir que o VS Code instalava automaticamente um pacote Python aleatório para bibliotecas sem definições de tipos padrão
      Era um recurso da extensão oficial de Python da Microsoft e, em outros aspectos, era a única extensão minimamente utilizável, mas ela instalou definições de tipos para uma versão da biblioteca diferente da usada pelo meu projeto. Parecia estar executando código de terceiros não verificado com a maior naturalidade, o que me deixou muito desconfortável, e não parecia haver nem como desativar isso nas configurações
      Eu gostaria de dizer que “nunca mais olhei para trás”, mas, sinceramente, nos últimos 1~2 anos o Neovim começou a quebrar minha configuração regularmente em quase todo upgrade. Já dava para sentir que isso poderia acontecer um dia. Tecnicamente, já se passaram 10 anos, mas o nvim ainda não lançou sua primeira versão estável, então não dá para culpar a instabilidade, mas é algo a se ter em mente
      Estou pensando em voltar para o Vim puro. Vou perder muitos recursos de conveniência, mas queria pelo menos reduzir as vezes em que preciso depurar funcionalidades quebradas no meio do trabalho
    • Estou gostando bastante do Helix. Não explorei o Neovim a fundo, mas o Helix já vem com vários recursos estilo IDE que sempre senti falta no Vim
      Não precisa instalar um monte de plugins nem usar algo como SpaceVim. Talvez valha a pena dar uma olhada, pode ser que você goste
    • Tenho sentido que é bem difícil mudar hábitos de software. Há atalhos para aprender, e no começo tudo parece mais lento, o que reforça a sensação de que “não é melhor”
      Leva tempo para se acostumar com o nvim, mas, depois que você se acostuma, ele fica mais rápido. Ainda assim, dá para entender por que tanta gente permanece na zona de conforto
  • Tornar isso público publicamente foi uma boa decisão. Muita gente está insatisfeita com o MSRC, e isso agora começa a transbordar, como no caso Nightmare Eclipse
    Se divulgações assim se acumularem, talvez o MSRC faça uma autocrítica e perceba que ele mesmo é o problema. Parece improvável, mas dá para ter esperança

    • Ainda não tenho certeza se essa continua sendo a melhor abordagem. Parece que ele nem tentou submeter porque esperava receber classificação “baixa”, comparando com um envio anterior de XSS
      Mesmo assim, acho que ele deveria ao menos ter tentado, ou avisado alguns dias antes de publicar. Nunca se sabe o que pode acontecer
  • O texto foi muito bom, mas fiquei um pouco confuso na parte final. Quero confirmar se entendi certo
    O autor disse que, por causa do novo sistema de confiança de publicador, não é possível instalar diretamente uma extensão maliciosa só com o truque de atalhos, e que isso pode ser contornado com uma extensão local de workspace, que não passa por verificação de publicador, mas que o CSP bloqueia
    A solução parece ser instalar uma extensão local de workspace que vincula um atalho para “instalar extensão sem verificação de publicador”
    Então, 1) isso quer dizer que são necessárias duas extensões? A primeira seria uma extensão local que só faz o keybinding, e a segunda seria a extensão realmente maliciosa, que por causa do CSP nem precisa ser local e, na prática, nem pode ser local? E 2) o CSP só bloqueia o JS da extensão local, mas não bloqueia o package.json nem a capacidade de adicionar atalhos?

    • 1 e 2 estão corretos. É só ver o repositório de prova de conceito: https://github.com/ammaraskar/github-dev-token-steal-poc/tre...
      Você pode tentar colocar my-extension/extension.js para a execução mais direta, mas o CSP bloqueia. Porém, como o script-src do CSP bloqueia apenas scripts, buscar o package.json continua permitido. Então isso é usado para contribuir com o keybinding
  • A situação do MSRC é realmente inacreditável
    Pode haver materiais melhores, mas acho que este vídeo do The Primeagen é um bom material de introdução
    https://www.youtube.com/watch?v=9kxx5xp5nTQ

  • Tenho uma pequena implicância com a parte que diz “a única maneira de permitir esse comportamento é duas páginas web de origens diferentes cooperarem via a API Window.postMessage()
    Também dá para se comunicar fazendo o iframe ou a janela pai alterarem a propriedade location.anchor