1 pontos por GN⁺ 2025-02-09 | 1 comentários | Compartilhar no WhatsApp
  • Ao tentar se integrar ao fluxo de edição remota via SSH do VSCode, a Fly.io constatou que, em vez de aproveitar de forma leve o shell remoto, o VSCode adota uma arquitetura que instala e executa um agente separado
  • A geração de código por LLM é mais útil em um loop de agente conectado ao ambiente de execução, mas isso pode até mexer nas configurações do sistema do notebook de desenvolvimento, o que exige uma instância Linux isolada
  • O Tramp do Emacs amplia suas funcionalidades para o ambiente remoto executando comandos do Bourne shell em ambientes interativos como SSH, mas o VSCode baixa um agente e um binário do Node por meio de um stageador de snippets em Bash
  • O agente do VSCode é executado sobre SSH com encaminhamento de portas e estabelece uma conexão WebSockets com o frontend do VSCode, podendo explorar arquivos, editar arquivos arbitrários, executar um shell PTY e se autopersistir
  • Só permitir edição remota do VSCode em um servidor de desenvolvimento já é um peso considerável, e usar esse método durante um incidente em produção gera preocupação ainda maior, mas em conexões personalizadas para Fly Machines foi possível evitar essa arquitetura

O isolamento necessário para loops de agente com LLM

  • A Fly.io tinha interesse em se integrar ao fluxo do VSCode para edição remota via SSH
    • porque há muitos usuários do VSCode, especialmente usando forks do VSCode para gerar código com LLM
  • Código gerado por LLM é útil quando sabe o que o usuário está fazendo, e fica ainda mais eficaz se puder fechar o loop com o ambiente de execução
    • o LLM gera o código
    • o scaffolding do agente executa o código
    • o código produz erros
    • o agente envia os erros de volta ao LLM
    • esse processo se repete
  • Essa estrutura pode ser um antídoto parcialmente eficaz contra alucinações, mas é arriscado demais executá-la diretamente no notebook de desenvolvimento
    • o LLM pode mexer repetidamente não só no projeto Git em andamento, mas também nas configurações do sistema
  • Uma forma melhor é executar uma configuração de agente em loop fechado dentro de uma instância Linux limpa que sobe imediatamente, impedindo que esse ambiente cause danos ao usuário

Como funciona o agente Remote SSH do VSCode

  • O Tramp do Emacs é um código Elisp que funciona quase como ancestral conceitual dos sistemas de edição remota
    • ao se conectar a um ambiente interativo capaz de executar comandos do Bourne shell, como uma sessão SSH, ele estende os recursos do Emacs para esse ambiente
  • O VSCode também tem algo parecido com o Tramp, mas não é simplesmente uma versão simplificada do Tramp reescrita em TypeScript
  • Em vez de usar apenas as ferramentas já existentes na conexão remota, o VSCode executa um stageador de snippets em Bash para baixar um agente
  • O agente opera sobre SSH com encaminhamento de portas e cria uma conexão WebSockets com o frontend do VSCode em execução
    • o subprotocolo consegue percorrer o sistema de arquivos
    • é possível editar arquivos arbitrários
    • ele pode executar seus próprios processos shell PTY
    • pode persistir a si mesmo
  • Existe um nome que o setor de segurança usa para ferramentas que funcionam assim, mas o autor evita dizê-lo diretamente por considerar injusto com o VSCode
  • Permitir edição remota do VSCode em um servidor de desenvolvimento já causa desconforto, e a preocupação aumenta ainda mais se o mesmo método for usado durante um incidente em produção
  • Ao criar conexões personalizadas para Fly Machines, não foi necessário se preocupar com essa arquitetura, e por isso o autor considera que, em um sentido mais profundo, isso não era uma questão tão importante

1 comentários

 
GN⁺ 2025-02-09
Opiniões do Hacker News
  • Depois de tentar por cerca de um mês escrever um texto longo sobre um software em que vinha mexendo havia uns 3 ou 4 anos, Kurt ficou ansioso porque eu não postava nada no blog desde agosto, então no fim decidi escrever o texto mais simples possível
    A ideia era fazer o oposto do que eu vinha fazendo: escrever um post de baixo esforço, achando que daria para produzir um em 30 minutos. Isto é só algo em que eu vinha mexendo colocado em forma de texto, e provavelmente pensei menos sobre ele do que quem vai ler

    • Ao ler o post, só agora entendi que essa arquitetura não faz sentido nenhum, mas isso não ficou imediatamente evidente só pelo texto do blog. Quando vi a lista do que o agente podia fazer, acabei assumindo que não poderia ser nessa direção
      A frase do README “A compromised remote could use the VS Code Remote connection to execute code on your local machine.” foi muito mais clara, e acho que esse aviso de segurança deveria vir acompanhado de um número de CVE
    • Acho que o primeiro parágrafo do comentário no HN teria ficado mais legível se não tivesse nenhum ponto final. Fico feliz em ver que um blog de que gosto ainda está vivo; eu estava um pouco preocupado
      Os dois primeiros posts visíveis agora — o texto de McCord-Valim sobre FLAME-Livebook-GPU e este texto com “murid” — mostram muito bem a trajetória psicológica de um desenvolvedor
    • Gostaria que publicasse mais posts de baixo esforço
    • O problema talvez seja o próprio ssh. Parece que deveria haver uma forma de pedir, ao se conectar por ssh, uma experiência parecida com Docker, e seria bom poder especificar o uso de uma API que bloqueie processos ou acesso ao sistema de arquivos fora de uma pasta específica
      Também daria para permitir binários do sistema, mas isso ficaria complexo e talvez obrigasse o VSCode a empurrar mais coisas para o cliente. Procurando por alto, aparecem opções de chroot no lado do servidor ssh, mas não há muita menção no manual do cliente ssh
      Ou talvez a solução seja baixar um contêiner Docker no remoto, executar um contêiner com o diretório remoto montado e então conectar por ssh a esse contêiner
      O problema de sincronizar apenas arquivos de subdiretórios é que o VSCode também precisa de execução remota e depuração iniciadas por ele. Por isso, plugins também precisam de acesso remoto ou precisam rodar no remoto, e certa observação de código, se rodada localmente, pode ter um custo grande demais de pré-sincronizar todo o subdiretório
    • O caminho certo é exatamente a abordagem de “decidimos simplesmente voltar a ser um blog. Então tivemos que aprender isso, e agora você também vai ter que aprender”
  • Pode soar ingênuo, mas não entendo bem por que isso é um problema de segurança. Se você consegue se conectar por ssh a uma máquina e fazer encaminhamento de portas por socket, então já tem permissão para fazer todo o resto, e o protocolo do VSCode parece apenas expor isso de um jeito conveniente para eles
    Fico me perguntando se o motivo de ser um problema de segurança é que alguém na mesma rede da máquina remota, mas sem credenciais SSH, poderia se conectar à porta encaminhada por SSH. Como usuário, gosto do sistema de SSH do VSCode porque ele funciona muito bem

    • A diferença é que o que o VSCode faz não é uma sessão SSH obtida pelo comando ssh ou pelo PuTTY
      O VSCode instala um agente remoto na máquina de destino, usa ssh como protocolo de transporte e diz que vai compartilhar esse transporte com o usuário. Se ele fizer apenas o que você quer, tudo bem, mas um sistema baseado em agente que expõe APIs arbitrárias cria uma superfície de ataque e um risco muito maiores do que o método familiar, embora ainda complicado, de imitar um terminal por cima de ssh
    • O ponto central é que o agente roda sobre SSH com encaminhamento de porta e estabelece uma conexão WebSocket com o frontend do VSCode em execução
      O protocolo em cima dessa conexão pode navegar pelo sistema de arquivos, editar arquivos arbitrários, iniciar seus próprios processos de shell PTY e manter a si mesmo persistente. O fato de o cliente se conectar por ssh ao servidor remoto não significa que esse servidor possa executar código arbitrário no cliente; no mínimo, o cliente precisa realizar explicitamente alguma ação
    • Basicamente, isso está certo. Essencialmente, não é uma vulnerabilidade nem um problema de atravessar uma fronteira de segurança
      Mas é um problema de segurança no mesmo sentido em que “curl | bash” é um problema de segurança. Uma analogia mais próxima talvez seja curl | bash dentro do bashrc
    • O agente no servidor de desenvolvimento passa a ser um vetor reverso de volta para o VS Code no notebook
      Como o agente fica conectado à rede e sempre em execução, um buraco no firewall do servidor de desenvolvimento vira também um buraco no firewall do notebook
    • Claro que as permissões já existem. O problema é que agora um agente de terceiros pode usar essas permissões como quiser, e o usuário talvez nem perceba
  • Quanto mais se entende como o VSCode funciona, mais ele parece algo mal colado com fita adesiva e as ideias mais amaldiçoadas que um desenvolvedor JavaScript poderia imaginar
    Só olhando a extensão SSH, há dois formatos de URI de workspace. Um é basicamente só o nome do host; o outro é um documento JSON codificado em hexadecimal, usado quando é preciso informação extra, como um nome de usuário específico, ou quando o nome do host contém letras maiúsculas
    O motivo de isso ser realmente necessário é que, por alguma razão, ele é convertido para minúsculas quando salvo nos workspaces recentes
    A conexão SSH também suporta configurações de extensões a serem instaladas no servidor, mas, se você colocar extensões demais, não consegue se conectar a um host Windows. Elas são passadas como argumentos de linha de comando via CMD, que tem um limite de 8191 caracteres, e esse CMD chama o PowerShell

    • O VS Code era melhor que o Eclipse. Nunca precisei de SSH via IDE, então não sei sobre essa parte; normalmente eu me conectava por SSH com PuTTY e, se precisasse trabalhar no servidor, usava Vi
    • Se você conhece JavaScript/TypeScript, é ótimo porque fica muito fácil adicionar suporte personalizado a linguagens ou ferramentas ao editor
      Dá para oferecer autocompletar personalizado, diagnósticos etc., e também criar um Go to definition personalizado para suporte entre linguagens
    • Há algumas linhas extremamente infelizes que fazem pensar em fita adesiva: https://github.com/microsoft/vscode/blob/6dbde2a3ed308f88164...
      Gostaria que a Microsoft me contratasse por alguns meses, me colocasse sentado num canto e me deixasse desenrolar essa bagunça
    • Parecia algo amarrado com lixo e barbante, então voltei para o vim
  • Eu mantinha servidores para aulas de redes, exploração de binários e programação de sistemas introdutória, e essa coisa era uma grande dor de cabeça. Por causa desse trojan idiota de acesso remoto, os alunos não entendiam como usar o cliente OpenSSH
    Tentei algumas coisas para corrigir isso. Coloquei no motd dos servidores da disciplina para não usarem o plugin de servidor remoto do VSCode e, na frente da turma, rodei ncdu /home para mostrar que todo aluno cujo uso de disco no servidor passava de 100 MB era, sem exceção, usuário do VSCode
    Também limitei os processos de usuário a 45, porque, sabe-se lá como, o trojan de acesso remoto do VSCode usa cerca de 50 processos Node. Quando os alunos ignoravam o motd e os avisos em aula, batiam no limite e tinham de pedir para nós matarmos os processos para conseguirem se conectar de novo
    No fim, troquei o limite de processos por um script que mata todos os trojans de acesso remoto .vscode-server a cada 10 segundos

    • Isso me lembra muito a época da faculdade, quando eu contornava as restrições anacronicamente rígidas que os administradores de sistemas da escola colocavam na rede
    • Isso não acontece só porque o VSCode é popular. Mesmo há mais de 10 anos, na minha época de faculdade, havia alunos usando o Sublime com plugin de SFTP ou programando localmente e transferindo arquivos com clientes GUI como o FileZilla
      Numa disciplina em que fui monitor, havia uma tarefa de processar código de máquina básico para imitar as ferramentas de montagem e execução da ISA estudada, e os alunos precisavam entender a estrutura de bytes dos arquivos com coisas como hexdump
      Só que o Sublime “gentilmente” renderizava arquivos-objeto como se fossem a representação textual de um hexdump, adicionando espaços para legibilidade, e mostrava em uma ordem de endianness diferente da exibida pelo hexdump no servidor Linux da escola
      Todo semestre, alguns alunos vinham perguntar por que o código que tinham escrito para ler strings ASCII como AD DE EF BE encontrava um texto desconhecido; era porque não tinham verificado que os valores reais dos bytes começavam com 0xDE, 0xAD, 0xBE, 0xEF
    • Fico curioso por que era preciso chegar a esse ponto. Entendo que houve muito esforço para bloquear o VSCode, mas não fica claro o que exatamente o VSCode causava
    • 50 processos Node; estamos nos afastando cada dia mais de Deus
    • Se você ficou se perguntando a que “murid” se refere aqui e também nunca tinha ouvido RAT, RAT é a sigla de Remote Access Trojan
  • Não sei bem qual é a alternativa aqui. A edição via SSH do VSCode funciona surpreendentemente bem, e faz muito tempo que parei de ficar mexendo em vim, nano ou micro em máquinas remotas
    O agente não atrapalha e me deixa trabalhar em paz. É quase como trabalhar na máquina local e, para mim, isso é uma grande vantagem
    Pode ser um risco de segurança, mas a experiência de desenvolvimento não tem comparação. Não me importo muito com quais outros editores o VSCode está matando; só quero que a ferramenta não atrapalhe e me deixe trabalhar

    • A alternativa se aproxima do modelo proposto pelo TRAMP. Até onde sei, o TRAMP trata o remoto como um sistema de arquivos de rede, não como um host de execução
      Ele não distribui binários; lê e escreve bytes por pipes, e toda execução significativa acontece localmente. Em especial, ele não cria persistência, e há diferença entre “o plugin do VSCode pode acessar enquanto você está conectado por SSH” e “o plugin do VSCode pode acessar para sempre”
    • O risco de segurança vem de plugins não verificados terem acesso irrestrito ao editor
    • Pelo que vi, colegas que usam VSCode ficam limitados de maneiras que nem percebem, e não têm noção de quão melhor uma abordagem melhor poderia ser
      Ao trabalhar em vários remotos, muitas vezes não sabem a que estão conectados nem qual é o estado da conexão. O terminal é lento, e a persistência do estado da sessão é irregular
      É uma experiência muito pior do que usar tmux e um editor de texto de verdade. Além disso, o servidor é muito pesado e não encerra corretamente, então é comum acabar com seis instâncias de servidor rodando
      Metade das atualizações quebra, e eles chegam a perder uma hora porque não sabem entrar no host com um cliente ssh de verdade e limpar um servidor vscode quebrado
    • Não sei exatamente quais recursos o VSCode oferece, mas sshfs se encaixa bastante bem em vários trabalhos de edição remota. Em princípio, deve ser parecido com o VSCode
    • O TRAMP do Emacs também é bem ruim, mas ainda assim é mais estável e amigável ao usuário do que a bagunça que é a edição remota do VSCode
  • O que aprendemos? Que execução remota de código existe? Que confiar de forma equivocada em ferramentas de desenvolvimento costuma gerar arrependimento? Que o design de software moderno é uma bagunça? Tudo isso era óbvio com um mínimo de atenção
    SSH é uma solução dos anos 90. É um Telnet com alguns recursos acrescentados e, embora seja chamado de shell “seguro”, é literalmente menos seguro que Telnet+TLS
    Como já tinham um túnel com uma sessão de usuário no servidor, algumas pessoas concluíram que não havia necessidade de criar um transporte de rede e um protocolo de conexão segura separados para aplicações, e empilharam em cima do SSH todo tipo de coisa estranha, porém elogiada
    É o resultado de jogar fora conceitos aprendidos com sistemas operacionais distribuídos, ignorar mecanismos avançados de autenticação e autorização desenvolvidos nesse meio-tempo e adotar a coisa mais ruim e fácil
    Esse tipo de “agente SSH” não é algo absurdo. Nós não nos movemos para criar a ferramenta certa para a tarefa, então continuamos enfiando cada vez mais coisas em ferramentas existentes que não foram projetadas para isso. Não temos o direito de fingir surpresa
    Este é o mundo que criamos. Todos nós o criamos, seja pelo trabalho, seja pela conivência silenciosa. Mesmo que não seja o SSH, o mesmo vale para política, comércio, escolas e todo o resto. Vivemos todos os dias dentro do monte que nós mesmos empilhamos e, a cada dia em que não fazemos nada, é como jogar mais uma pazada por cima. Não dá para segurar a pá e fingir que isso é surpreendente ou insano

    • Quem criou isso não foram desenvolvedores, mas o pessoal de segurança de rede. Se você bloqueia todas as portas de saída exceto HTTPS e ssh, tudo depois disso inevitavelmente acaba tunelado sobre HTTPS ou ssh
      Então, em geral, se você permite conexões HTTPS de saída, faz mais sentido permitir também todas as conexões de saída, com exceção de SMTP. O tráfego realmente malicioso será tunelado por HTTPS de qualquer forma, e o único efeito restante é dificultar a implantação de novos protocolos que não carregariam a complexidade e a ineficiência do túnel
    • Por outro lado, acho que a autenticação por par de chaves SSH e certificados é o melhor método de autenticação que conheço. Ela também se integra ao FIDO2 sem configuração prévia
      Eu gostaria que logins na web fossem mais parecidos com o jeito como o SSH faz
    • Isso soa muito como teoria da conspiração. Nem tudo no mundo acontece por malícia; na maior parte das vezes, pessoas sob pressão tentam fazer o melhor que conseguem imaginar
      Sair de vez em quando e tocar na grama faz bem para a alma. E também seria bom propor como criar um protocolo SSH melhor. Reclamar sem crítica construtiva não serve para muita coisa
  • O termo “SSH agent” aqui é confuso. Normalmente ele significa um daemon que faz cache de tokens de autenticação

    • Exato. O VSCode não fornece um SSH Agent; ele se comunica com o SSH Agent local. Na prática, é uma versão própria do ForwardAgent, com as mesmas implicações de segurança
      Além disso, esse método quebra o conhecido SSH agent do macOS: https://github.com/maxgoedjen/secretive/issues/543
    • Como há “VSCode” antes de “SSH Agent”, a distinção fica razoavelmente clara
  • Concordo totalmente que usar vscode remote em servidores de produção é loucura
    Dito isso, os outros recursos descritos como “absurdos” parecem funcionalidades esperadas

    • Pensando nas implicações de segurança, fico curioso sobre qual seria o caso de uso desse recurso. Talvez algo como uma instância de staging suficientemente isolada de outros ambientes
  • Cheguei a staff engineer em uma MAANG, e acho que isso é um nível difícil de alcançar só com Vim puro. Ainda assim, vejo que outros profissionais de alta performance continuam tendendo a usar Vim ou Emacs
    Há muitos ótimos desenvolvedores usando VCode, JetBrains etc., mas acho que a tendência de procurar barreiras de entrada, tentar desmontar a “mágica” das ferramentas por meio da investigação e valorizar projetos totalmente open source, altamente modificáveis e conduzidos pela comunidade explica melhor esse fenômeno do que recursos ou facilidade de uso
    Ler sobre o quanto a edição remota do VSCode é complexa me dá ainda menos vontade de usar VSCode. Basta entrar na máquina via ssh e usar o editor que existe nela
    A solução do VSCode funciona, mas não é elegante, não é universalmente aplicável e também é mais fácil de quebrar. E, com desculpas aos usuários de Emacs, o Tramp ainda é bem terrível, e o netrw não é melhor

    • Concordo que o Tramp não é ótimo, mas existe uma solução simples que funciona melhor: watchexec + rsync
      Dá para monitorar caminhos específicos de arquivos e sincronizar exatamente só o necessário. Você continua trabalhando no sistema de arquivos local, então não há latência de edição, pode usar todas as ferramentas locais, e a sincronização termina em milissegundos
      Dá para fazer com que arquivos apagados localmente também sejam apagados no remoto, e você sempre fica com uma cópia local depois de terminar o trabalho na máquina remota. No Tramp, essa era uma parte que sempre precisava ser sincronizada manualmente. Além disso, é independente do editor
      Esse recurso do VS Code, agora que sei o que ele realmente faz, me deixa desconfortável
    • Depois de entrar em uma nova equipe centrada em VSCode, venho pensando bastante por que ainda prefiro o vim. Uma observação recente é que as barras de ferramentas e outros elementos que enchem a tela são visualmente barulhentos demais
      Liguei o Copilot e a barra de ferramentas cresceu ainda mais, e texto começou a voar para onde eu estava tentando escrever. O Vim simplesmente me deixa olhar para o código, pensar e escrever. Com o VSCode, é difícil entrar em estado de fluxo
      Tenho trinta e poucos anos; na faculdade usei emacs e, no primeiro emprego, mudei para vim. Em projetos Java muito obscuros usei IntelliJ, mas fora isso continuo usando vim
    • Quando eu programava por hobby, gostava de explorar ferramentas e desmontar a mágica. Agora que isso virou profissão, gosto do VSCode. Não preciso ficar mexendo muito nele e posso me concentrar em terminar o trabalho
      Só abro o vim de vez em quando quando preciso fazer manipulações complexas com regex
    • O principal engineer e o distinguished engineer da nossa equipe usavam Vim e Emacs
  • Em vez de funcionar junto com as ferramentas remotas existentes, o VSCode distribui um agente abrangente que inclui a instalação de um binário Node.js, uma conexão WebSocket de volta para o frontend do VSCode e amplos recursos de acesso ao sistema
    Esse agente do VSCode tem permissões amplas, incluindo navegação pelo sistema de arquivos, edição de arquivos, criação de processos PTY de shell e até capacidade de autopersistência

    • Não parece haver uma alternativa razoável para dar suporte ao que o VSCode faz, como executar extensões que não estão instaladas localmente. Você pode não querer esse tipo de funcionalidade, mas ela faz parte do conjunto de recursos do produto
    • Não está claro se esse problema é da instância local do VS Code ou da instância remota
      Se for da remota, entendo que o Tramp do elisp é mais leve em termos de dependências, mas fico curioso se a superfície de ataque é realmente tão diferente assim. Ou seja, não sei se um binário Node remoto tem permissões que um usuário executando comandos ssh arbitrários não teria
      Se o objetivo original era entregar a um LLM todas as chaves de uma máquina virtual temporária e descartável, fico me perguntando se, por causa do socket aberto pelo agente, ele poderia acabar mexendo também na máquina do desenvolvedor que se queria isolar
    • De um ponto de vista, dá para ver essas coisas como algo que sistemas operacionais modernos deveriam oferecer como recursos padrão, e o VSCode estaria contornando a falta dessas funcionalidades
      Parece uma ideia maluca, mas o próprio kernel poderia oferecer um servidor web com criptografia e autenticação, ou algum outro protocolo, e permitir o controle direto da máquina inteira via eBPF. Poderia ser um paradigma totalmente diferente de controle remoto cliente/servidor
      Claro, também poderia ser uma falha de segurança grande o bastante para a Death Star passar por ela