L’agent SSH de VSCode est aberrant
(fly.io)- En cherchant à s’intégrer au flux d’édition distante en SSH de VSCode, Fly.io a constaté que VSCode n’exploite pas simplement le shell distant de façon légère, mais adopte une architecture qui installe et exécute un agent distinct
- La génération de code par LLM est plus utile dans une boucle d’agent reliée à l’environnement d’exécution, mais comme elle peut aussi modifier les réglages système du laptop de développement, une instance Linux isolée est nécessaire
- Le Tramp d’Emacs étend ses fonctionnalités à l’environnement distant en exécutant des commandes du shell Bourne dans un environnement interactif comme SSH, tandis que VSCode télécharge un agent et un binaire Node via un Bash snippet stager
- L’agent VSCode s’exécute sur une connexion SSH avec redirection de port et établit une connexion WebSockets avec le frontend de VSCode, ce qui lui permet d’explorer le système de fichiers, d’éditer des fichiers arbitraires, d’exécuter un shell PTY et d’assurer sa propre persistance
- Autoriser simplement l’édition distante VSCode sur un serveur de développement représente déjà une lourde contrainte, et l’usage de cette méthode pendant un incident en production est encore plus préoccupant, mais cette architecture a pu être évitée pour les connexions personnalisées à Fly Machine
L’isolation nécessaire pour une boucle d’agent LLM
- Fly.io s’est intéressé à l’intégration au flux par lequel VSCode effectue l’édition distante via SSH
- parce que beaucoup de personnes utilisent VSCode, notamment des forks de VSCode servant à générer du code avec des LLM
- Le code généré par LLM est utile lorsqu’il sait ce que fait l’utilisateur, et l’efficacité augmente encore si l’on peut fermer la boucle avec l’environnement d’exécution
- le LLM génère du code
- le scaffolding de l’agent exécute le code
- le code produit des erreurs
- l’agent retransmet les erreurs au LLM
- le processus se répète
- Cette structure peut constituer un antidote à moitié efficace contre les hallucinations, mais elle est risquée si on l’exécute telle quelle sur un laptop de développement
- le LLM peut modifier de façon répétée non seulement le projet Git en cours, mais aussi la configuration du système
- Une meilleure approche consiste à exécuter une configuration d’agent en boucle fermée dans une instance Linux propre démarrée à la demande, en empêchant cet environnement de nuire à l’utilisateur
Comment fonctionne l’agent SSH distant de VSCode
- Tramp d’Emacs est un code Elisp qui se rapproche d’un ancêtre conceptuel des systèmes d’édition distante
- lorsqu’il se connecte à un environnement interactif capable d’exécuter des commandes du shell Bourne, comme une session SSH, il y étend les fonctionnalités d’Emacs
- VSCode propose lui aussi une fonction proche de Tramp, mais ce n’est pas simplement une version simplifiée de Tramp portée en TypeScript
- Au lieu de se contenter d’outils existants pour la connexion distante, VSCode exécute un Bash snippet stager qui télécharge un agent
- cet agent inclut une installation binaire de Node
- l’emplacement des sources associées semble être le répertoire server/node de microsoft/vscode
- L’agent fonctionne au-dessus d’une connexion SSH avec redirection de port et crée une connexion WebSockets vers le frontend VSCode en cours d’exécution
- le sous-protocole peut parcourir le système de fichiers
- il peut éditer des fichiers arbitraires
- il peut exécuter ses propres processus shell PTY
- il peut se rendre persistant
- Il existe dans le secteur de la sécurité un nom pour les outils qui fonctionnent de cette façon, mais l’auteur ne le dit pas explicitement pour ne pas être injuste envers VSCode
- Autoriser l’édition distante VSCode sur un serveur de développement est source d’inquiétude, et l’usage de la même méthode pendant un incident en production est encore plus préoccupant
- Lors de la création d’une connexion personnalisée à une Fly Machine, il n’a pas été nécessaire de se préoccuper de cette architecture, et l’auteur considère donc que ce n’était pas un problème important au sens profond
1 commentaires
Avis de Hacker News
J’essayais depuis environ un mois d’écrire un long billet sur un logiciel que je bricolais depuis 3 ou 4 ans, mais Kurt s’inquiétait que je n’aie rien publié sur le blog depuis août, alors j’ai fini par décider d’écrire le billet le plus simple possible.
L’idée était de faire l’inverse de ce que je faisais jusque-là : écrire un billet à faible effort ; je me disais que je pouvais en produire un en 30 minutes. Ce n’était que la mise par écrit de ce que je bricolais, et j’y ai probablement moins réfléchi que les lecteurs.
La phrase du README, “A compromised remote could use the VS Code Remote connection to execute code on your local machine.”, était bien plus claire, et j’ai l’impression qu’un numéro de CVE devrait être accolé à cet avertissement de sécurité.
Les deux premiers billets visibles actuellement — celui de McCord-Valim sur FLAME-Livebook-GPU et celui-ci avec “murid” — montrent vraiment bien la trajectoire psychologique d’un développeur.
On pourrait autoriser les binaires système, mais cela se compliquerait et VSCode devrait peut-être pousser davantage de choses côté client. En cherchant rapidement, on trouve des options chroot côté serveur ssh, mais le manuel du client ssh n’en parle pas vraiment.
Ou alors la solution serait peut-être de télécharger un conteneur Docker côté distant, de lancer un conteneur avec le répertoire distant monté, puis de se connecter en ssh à ce conteneur.
Le problème avec une approche qui ne synchronise que les fichiers des sous-répertoires, c’est que VSCode a aussi besoin de lancer et déboguer du code à distance. Les plugins doivent donc aussi avoir un accès distant, ou s’exécuter à distance ; et pour certaines observations de code, les faire tourner en local peut rendre le coût de présynchronisation de tout le sous-répertoire beaucoup trop élevé.
Cela va peut-être paraître naïf, mais je ne vois pas bien pourquoi c’est un problème de sécurité. Si je peux me connecter en ssh à une machine et faire du transfert de ports par socket, j’ai déjà le droit de faire tout le reste, et le protocole VSCode semble simplement exposer cela d’une manière qui leur convient.
Je me demande si la raison pour laquelle c’est un problème de sécurité est qu’une personne présente sur le même réseau que la machine distante, mais sans accès SSH, pourrait se connecter au port transféré via SSH. En tant qu’utilisateur, j’aime bien le système SSH de VSCode, il fonctionne plutôt bien.
sshou PuTTY.VSCode installe un agent distant sur la machine cible, utilise ssh comme protocole de transport et dit vouloir partager ce canal de transport avec l’utilisateur. Tant qu’il ne fait que ce qui est attendu, pas de problème ; mais un système basé sur un agent qui expose des API arbitraires crée une surface d’attaque et des risques bien plus importants que la méthode familière, mais toujours délicate, consistant à imiter un terminal au-dessus de ssh.
Le protocole sur cette connexion peut parcourir le système de fichiers, modifier des fichiers arbitraires, lancer son propre processus PTY de shell et se rendre persistant. Ce n’est pas parce qu’un client s’est connecté en ssh à un serveur distant que ce serveur peut exécuter du code arbitraire sur le client ; au minimum, le client doit accomplir explicitement une action.
Mais c’est un problème de sécurité au même sens que “curl | bash” est un problème de sécurité. Une analogie plus proche serait peut-être curl | bash dans
bashrc.Comme l’agent est connecté au réseau et tourne en permanence, un trou dans le pare-feu du serveur de développement devient aussitôt un trou dans le pare-feu de l’ordinateur portable.
Plus j’en apprends sur le fonctionnement de VSCode, plus j’ai l’impression que c’est tenu par du ruban adhésif et les idées les plus maudites auxquelles des développeurs JavaScript pouvaient penser.
Rien que pour l’extension SSH, il existe deux formats d’URI d’espace de travail : l’un qui contient pratiquement seulement le nom d’hôte, et l’autre qui est un document JSON encodé en hexadécimal. Le second est utilisé quand des informations supplémentaires sont nécessaires, comme un nom d’utilisateur spécifique, ou quand le nom d’hôte contient des majuscules.
La vraie raison pour laquelle c’est nécessaire, c’est que, pour une raison obscure, le nom est converti en minuscules lorsqu’il est enregistré dans les espaces de travail récents.
Les connexions SSH prennent aussi en charge des paramètres d’extensions à installer sur le serveur, mais si on en met trop, impossible de se connecter à un hôte Windows. Ils passent ça en arguments de ligne de commande via CMD, qui a une limite de 8191 caractères, et ce CMD appelle ensuite PowerShell.
On peut fournir de l’autocomplétion personnalisée, des diagnostics, etc., et même créer un Go to definition personnalisé pour la prise en charge entre langages.
J’aimerais que Microsoft m’embauche quelques mois, me mette dans un coin et me laisse démêler ce bazar.
J’ai administré les serveurs de cours pour des cours de réseaux, d’exploitation de binaires et d’introduction à la programmation système, et ce truc est une vraie plaie. À cause de ce stupide cheval de Troie d’accès distant, les étudiants ne comprennent pas comment utiliser le client OpenSSH
J’ai essayé plusieurs choses pour corriger ça. Dans le motd des serveurs de cours, j’ai indiqué de ne pas utiliser le plugin de serveur distant de VSCode, et devant la classe j’ai lancé
ncdu /homepour montrer que tous les étudiants dont l’utilisation du disque serveur dépassait 100 Mo étaient, sans exception, des utilisateurs de VSCodeJ’ai aussi fixé une limite de 45 processus utilisateur, parce que le cheval de Troie d’accès distant de VSCode utilise, allez savoir comment, une cinquantaine de processus Node. Quand les étudiants ignoraient le motd et les avertissements en cours, ils atteignaient la limite et devaient nous demander de tuer leurs processus pour pouvoir se reconnecter
Au final, au lieu d’une limite de processus, je suis passé à un script qui tue tous les chevaux de Troie d’accès distant
.vscode-servertoutes les 10 secondesDans un cours où j’étais assistant, il y avait un devoir consistant à traiter du langage machine très basique pour imiter les outils d’assemblage et d’exécution de l’ISA étudiée, et les étudiants devaient comprendre la structure en octets des fichiers avec des outils comme
hexdumpOr Sublime rendait « gentiment » les fichiers objets comme une représentation textuelle de hexdump, en ajoutant des espaces pour la lisibilité, et les affichait dans un ordre d’endianess différent de celui obtenu avec
hexdumpsur le serveur Linux de l’écoleChaque semestre, quelques étudiants venaient demander pourquoi leur code, écrit pour lire une chaîne ASCII comme
AD DE EF BE, cherchait du texte incompréhensible ; ils n’avaient tout simplement pas vérifié que les valeurs d’octets réelles commençaient par 0xDE, 0xAD, 0xBE, 0xEFJe ne vois pas bien quelle est l’alternative ici. L’édition SSH de VSCode fonctionne étonnamment bien, et j’ai arrêté depuis longtemps de bricoler avec vim, nano ou micro sur des machines distantes
L’agent me laisse travailler tranquillement sans me gêner. On a presque l’impression de travailler sur une machine locale, et pour moi c’est un gros avantage
Ça peut représenter un risque de sécurité, mais l’expérience de développement est sans équivalent. Je ne me soucie pas vraiment de savoir quels autres éditeurs VSCode est en train de tuer ; je veux juste que l’outil me laisse faire mon travail sans me gêner
Il ne déploie pas de binaires, lit et écrit des octets via des pipes, et toute exécution significative se fait en local. Surtout, il ne crée pas de persistance : « le plugin VSCode est accessible pendant que l’on est connecté en SSH » et « le plugin VSCode est accessible pour toujours », ce n’est pas la même chose
Quand ils travaillent sur plusieurs machines distantes, ils ne savent souvent pas où ils sont connectés ni quel est l’état de la connexion. Le terminal est lent et la persistance de l’état des sessions est très inégale
C’est une expérience bien pire qu’avec
tmuxet un véritable éditeur de texte. En plus, le serveur est très lourd et ne se ferme pas correctement, si bien qu’il est courant de se retrouver avec six instances de serveur lancéesLa moitié des mises à jour cassent, et ils perdent parfois une heure parce qu’ils ne savent pas se connecter à l’hôte avec un vrai client ssh pour nettoyer un serveur vscode cassé
Qu’a-t-on appris ? Que l’exécution de code à distance existe ? Que la confiance mal placée dans les outils de développement finit souvent par se payer ? Que la conception logicielle moderne est un bazar ? Avec un minimum d’attention, tout cela était évident
SSH est une solution des années 90. C’est Telnet avec quelques fonctionnalités ajoutées, et même si on l’appelle un shell « secure », il est littéralement moins sûr que Telnet+TLS
Des gens se sont dit que, puisqu’on avait déjà un tunnel avec une session utilisateur sur le serveur, il n’était pas nécessaire de créer un protocole de transport réseau et de connexion sécurisée séparé pour les applications ; ils ont donc empilé sur SSH toutes sortes de trucs étranges mais applaudis
C’est le résultat de l’abandon des concepts appris avec les systèmes d’exploitation distribués, de l’ignorance de l’authentification et de l’autorisation avancées développées entre-temps, puis de l’adoption de la solution la plus médiocre et la plus facile
Ce genre d’« agent SSH » n’a rien d’absurde. Nous n’avons pas fait l’effort de créer les bons outils pour la tâche, et nous avons donc continué à entasser toujours plus de choses dans des outils existants qui n’avaient pas été conçus pour ça. Nous n’avons pas le droit de faire semblant d’être surpris
C’est le monde que nous avons construit. Nous l’avons tous construit, par notre travail ou par notre consentement silencieux. Même sans SSH, c’est pareil en politique, dans le commerce, à l’école et partout ailleurs. Chaque jour, nous vivons dans le tas que nous avons nous-mêmes accumulé, et chaque journée où nous ne faisons rien ajoute encore un coup de pelle. On ne peut pas tenir la pelle et faire semblant que c’est surprenant ou fou
Donc, en général, si l’on autorise les connexions HTTPS sortantes, il vaut mieux autoriser aussi toutes les connexions sortantes sauf SMTP. Le trafic réellement malveillant sera de toute façon tunnelisé via HTTPS, et le seul effet restant est d’entraver le déploiement de nouveaux protocoles qui éviteraient la complexité et l’inefficacité des tunnels
J’aimerais que les connexions web ressemblent davantage à ce que fait SSH
Sortir de temps en temps toucher de l’herbe, c’est bon pour l’âme. Et ce serait bien de proposer aussi comment concevoir un meilleur protocole SSH. Se plaindre sans critique constructive ne sert pas à grand-chose
Le terme « SSH agent » est déroutant ici. Normalement, il désigne un démon qui met en cache des jetons d’authentification
En plus, cette approche casse le célèbre agent SSH de macOS : https://github.com/maxgoedjen/secretive/issues/543
Je suis totalement d’accord pour dire qu’utiliser vscode remote sur des serveurs de production est insensé
En revanche, les autres fonctionnalités décrites comme « absurdes » ressemblent à des fonctionnalités auxquelles on peut s’attendre
Je suis arrivé jusqu’au niveau staff engineer chez MAANG, et je pense que c’est un niveau difficile à atteindre avec seulement un Vim ordinaire. Pourtant, je constate que d’autres profils très performants ont toujours tendance à utiliser Vim ou Emacs
Il y a beaucoup d’excellents développeurs qui utilisent VCode, JetBrains, etc., mais je pense que la tendance à rechercher les barrières à l’entrée, à décortiquer la magie des outils par l’exploration, et à valoriser les projets entièrement open source, hautement modifiables et portés par la communauté explique mieux ce phénomène que les fonctionnalités ou la facilité d’utilisation
Lire à quel point l’édition à distance de VSCode est complexe me donne plutôt envie d’utiliser VSCode encore moins. Il suffit de se connecter à la machine en ssh et d’utiliser l’éditeur qui s’y trouve
La solution de VSCode fonctionne, mais elle n’est ni élégante, ni universellement applicable, et elle est plus fragile. Et désolé pour les utilisateurs d’Emacs, mais Tramp reste assez atroce, et netrw ne fait pas mieux
watchexec+rsyncOn peut surveiller certains chemins de fichiers et synchroniser précisément uniquement ce qui est nécessaire. On travaille toujours sur le système de fichiers local, donc il n’y a pas de latence d’édition, on peut utiliser tous ses outils locaux, et la synchronisation se termine en quelques millisecondes
On peut faire en sorte que les fichiers supprimés localement soient aussi supprimés à distance, et il reste toujours une copie locale après avoir terminé de travailler sur la machine distante. Avec Tramp, c’était toujours quelque chose qu’il fallait synchroniser manuellement. En plus, c’est indépendant de l’éditeur
Cette fonctionnalité de VS Code m’inquiète maintenant que je sais ce qu’elle fait réellement
J’ai activé Copilot : la barre d’outils s’est encore allongée, et du texte est venu se projeter à l’endroit où j’essayais d’écrire. Vim me laisse simplement regarder le code, réfléchir et écrire. Avec VSCode, j’ai du mal à entrer en état de flow
J’ai la trentaine bien entamée ; à l’université j’utilisais emacs, puis je suis passé à vim dans mon premier emploi. Pour un projet Java très ésotérique, j’ai utilisé IntelliJ, mais sinon je suis resté sur vim
Je ne lance vim qu’occasionnellement quand j’ai besoin de manipulations complexes avec des regex
Au lieu de fonctionner avec les outils distants existants, VSCode déploie un agent complet comprenant l’installation d’un binaire Node.js, une connexion WebSocket qui revient vers le frontend VSCode, ainsi que de vastes capacités d’accès au système
Cet agent VSCode dispose de permissions étendues, notamment l’exploration du système de fichiers, l’édition de fichiers, la création de processus PTY de shell, et même la capacité de se maintenir lui-même
Si c’est côté distant, je comprends qu’elisp Tramp soit plus léger en matière de dépendances, mais je me demande si la surface d’attaque est vraiment si différente. Autrement dit, je ne sais pas si le binaire Node distant dispose de permissions que n’aurait pas l’utilisateur exécutant des commandes ssh arbitraires
Si l’objectif initial était de donner à un LLM toutes les clés d’une machine virtuelle temporaire et jetable, je me demande si cela signifie que, à cause du socket ouvert par l’agent, il pourrait aussi toucher la machine de développement qu’on cherchait à isoler
Cela peut sembler une idée folle, mais le noyau lui-même pourrait fournir un serveur web ou un autre protocole doté de chiffrement et d’authentification, et permettre de contrôler directement toute la machine via eBPF. Cela pourrait constituer un paradigme complètement différent de contrôle distant client/serveur
Bien sûr, cela pourrait aussi devenir une faille de sécurité assez grande pour laisser passer l’Étoile de la Mort