O agente SSH do VSCode é um absurdo
(fly.io)- 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
- esse agente inclui uma instalação binária do Node
- um local que parece conter o código relacionado é o diretório server/node no microsoft/vscode
- 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
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
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
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
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
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
sshou pelo PuTTYO 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 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
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
bashrcComo 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
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
Dá para oferecer autocompletar personalizado, diagnósticos etc., e também criar um Go to definition personalizado para suporte entre linguagens
Gostaria que a Microsoft me contratasse por alguns meses, me colocasse sentado num canto e me deixasse desenrolar essa bagunça
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 /homepara mostrar que todo aluno cujo uso de disco no servidor passava de 100 MB era, sem exceção, usuário do VSCodeTambé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-servera cada 10 segundosNuma 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
hexdumpSó 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
hexdumpno servidor Linux da escolaTodo semestre, alguns alunos vinham perguntar por que o código que tinham escrito para ler strings ASCII como
AD DE EF BEencontrava um texto desconhecido; era porque não tinham verificado que os valores reais dos bytes começavam com 0xDE, 0xAD, 0xBE, 0xEFNã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
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”
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
tmuxe 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 rodandoMetade 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
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
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
Eu gostaria que logins na web fossem mais parecidos com o jeito como o SSH faz
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
Além disso, esse método quebra o conhecido SSH agent do macOS: https://github.com/maxgoedjen/secretive/issues/543
Concordo totalmente que usar vscode remote em servidores de produção é loucura
Dito isso, os outros recursos descritos como “absurdos” parecem funcionalidades esperadas
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
watchexec+rsyncDá 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
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
Só abro o vim de vez em quando quando preciso fazer manipulações complexas com regex
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
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
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