- Fly.io intentó integrarse con el flujo de edición remota por SSH de VSCode y comprobó que VSCode, en lugar de usar de forma ligera el shell remoto, instala y ejecuta un agente aparte
- La generación de código con LLM es más útil dentro de un bucle de agente conectado al entorno de ejecución, pero como puede llegar a tocar incluso la configuración del sistema de la laptop de desarrollo, hace falta una instancia Linux aislada
- Tramp de Emacs amplía sus funciones a entornos remotos ejecutando comandos de Bourne shell en entornos interactivos como SSH, pero VSCode descarga un agente y un binario de Node mediante un stager de snippets Bash
- El agente de VSCode se ejecuta sobre SSH con reenvío de puertos y establece una conexión WebSockets con el frontend de VSCode, lo que le permite explorar archivos, editar archivos arbitrarios, ejecutar una PTY de shell y mantenerse persistente
- Solo permitir edición remota de VSCode en un servidor de desarrollo ya implica una carga considerable, y si este enfoque se usa durante un incidente en producción la preocupación es mayor; aun así, para la conexión personalizada de Fly Machine se pudo evitar esta estructura
El aislamiento necesario para los bucles de agentes con LLM
- Fly.io se interesó en integrarse con el flujo con el que VSCode realiza edición remota por SSH
- Porque hay muchos usuarios de VSCode y, en especial, porque se están usando forks de VSCode que generan código con LLM
- El código generado por LLM es útil cuando sabe qué está haciendo el usuario, y se vuelve aún más eficaz si puede cerrar el bucle con el entorno de ejecución
- El LLM genera código
- El andamiaje del agente ejecuta el código
- El código genera errores
- El agente devuelve los errores al LLM
- Este proceso se repite
- Esta estructura puede ser un antídoto a medias efectivo contra las alucinaciones, pero es riesgosa para ejecutarla tal cual en una laptop de desarrollo
- El LLM puede tocar repetidamente no solo el proyecto Git en el que se está trabajando, sino también la configuración del sistema
- Una mejor forma es ejecutar una configuración de agente de bucle cerrado en una instancia Linux limpia que se levanta al instante e impedir que ese entorno pueda perjudicar al usuario
Cómo funciona el agente SSH remoto de VSCode
- Tramp de Emacs es código Elisp que se acerca a ser el ancestro espiritual de los sistemas de edición remota
- Si se conecta a un entorno interactivo donde se pueden ejecutar comandos de Bourne shell, como una sesión SSH, extiende las funciones de Emacs a ese entorno
- VSCode también tiene una función parecida a Tramp, pero no es una estructura que simplemente haya trasladado una versión simplificada de Tramp a TypeScript
- En lugar de usar solo herramientas existentes en la conexión remota, VSCode ejecuta un stager de snippets Bash para descargar un agente
- Este agente incluye una instalación binaria de Node
- La ubicación que parece contener el código fuente relacionado es el directorio server/node de microsoft/vscode
- El agente funciona sobre SSH con reenvío de puertos y crea una conexión WebSockets con el frontend de VSCode en ejecución
- El subprotocolo puede recorrer el sistema de archivos
- Permite editar archivos arbitrarios
- Puede ejecutar su propio proceso PTY de shell
- Puede persistirse a sí mismo
- Hay un nombre que la industria de seguridad usa para una herramienta que funciona de esta manera, pero no se dice directamente porque sería injusto con VSCode
- Permitir edición remota de VSCode en un servidor de desarrollo genera inquietud, y si se usa el mismo enfoque durante un incidente en producción la preocupación aumenta
- Al crear una conexión personalizada para Fly Machine no fue necesario preocuparse por esta estructura, así que, en un sentido profundo, consideraron que no era un problema importante
1 comentarios
Opiniones en Hacker News
Intenté escribir durante más o menos un mes un texto largo sobre software con el que llevaba 3 o 4 años trasteando, pero Kurt se puso nervioso porque no había publicado nada en el blog desde agosto, así que al final decidí escribir el post más simple posible.
La idea era hacer lo contrario de lo que venía haciendo: escribir un post de bajo esfuerzo, y pensé que podía sacar uno en 30 minutos. Esto fue simplemente poner por escrito algo con lo que había estado jugando, y probablemente lo pensé menos que quienes lo leyeron.
La frase del README, “A compromised remote could use the VS Code Remote connection to execute code on your local machine.”, era mucho más clara, y siento que junto a esta advertencia de seguridad debería haber un número de CVE.
Los dos primeros posts que se ven ahora, el de McCord-Valim sobre FLAME-Livebook-GPU y este que contiene “murid”, muestran muy bien la trayectoria psicológica de un desarrollador.
Se podrían permitir binarios del sistema, pero eso se vuelve complejo y quizá obligue a VSCode a meter más cosas en el cliente. Buscando por encima, aparecen opciones de chroot del lado del servidor ssh, pero el manual del cliente ssh no dice mucho al respecto.
O quizá la solución sea descargar un contenedor Docker en el remoto, ejecutar un contenedor con el directorio remoto montado y luego conectarse por ssh a ese contenedor.
El problema de sincronizar solo los archivos de un subdirectorio es que también se necesita la ejecución remota y la depuración iniciadas por VSCode. Por eso los plugins también necesitan acceso remoto o deben ejecutarse en el remoto, y para cierta observación de código, si se ejecuta en local, el costo de sincronizar previamente todo el subdirectorio puede ser demasiado alto.
Puede sonar ingenuo, pero no entiendo bien por qué esto es un problema de seguridad. Si puedes conectarte por ssh a una máquina y hacer reenvío de puertos por socket, en la práctica ya tienes permiso para hacer todo lo demás, y el protocolo de VSCode parece exponer eso de una forma cómoda para ellos.
Me pregunto si la razón por la que es un problema de seguridad es que alguien que está en la misma red que la máquina remota, pero no tiene permisos de SSH, puede conectarse al puerto reenviado por SSH. Como usuario, el sistema SSH de VSCode me gusta bastante porque funciona bastante bien.
ssho con PuTTY.VSCode instala un agente remoto en la máquina destino, usa ssh como protocolo de transporte y dice que va a compartir ese transporte con el usuario. Si solo hace lo que uno quiere, no hay problema, pero un sistema basado en agentes que expone APIs arbitrarias crea una superficie de ataque y un riesgo mucho mayores que la forma conocida, aunque todavía delicada, de imitar una terminal sobre ssh.
El protocolo sobre esa conexión puede recorrer el sistema de archivos, editar archivos arbitrarios, levantar su propio proceso PTY de shell y hacerse persistente. Que el cliente se conecte por ssh a un servidor remoto no significa que ese servidor pueda ejecutar código arbitrario en el cliente; como mínimo, el cliente tendría que realizar explícitamente alguna acción.
Pero sí es un problema de seguridad en el mismo sentido en que “curl | bash” es un problema de seguridad. Una analogía más cercana podría ser curl | bash dentro de
bashrc.Como el agente está conectado a la red y siempre en ejecución, un agujero en el firewall del servidor de desarrollo pasa a ser un agujero en el firewall de la laptop.
Cuanto más sabes de cómo funciona VSCode, más parece algo apenas sostenido con cinta adhesiva y las ideas más malditas que se le podrían ocurrir a un desarrollador JavaScript.
Solo mirando la extensión SSH, hay dos formatos de URI para espacios de trabajo: uno que básicamente solo tiene el nombre del host y otro que es un documento JSON codificado en hexadecimal. Este último se usa cuando se necesita información adicional, como un nombre de usuario concreto, o cuando el nombre del host contiene mayúsculas.
La razón por la que esto es realmente necesario es que, por algún motivo, cuando se guarda en espacios de trabajo recientes se convierte a minúsculas.
La conexión SSH también admite configurar extensiones que se instalarán en el servidor, pero si pones demasiadas no puede conectarse a hosts Windows. Las pasa como argumentos de línea de comandos a través de CMD, y CMD tiene un límite de 8191 caracteres, y desde ese CMD llama a PowerShell.
Puedes ofrecer autocompletado personalizado, diagnósticos, etc., y también crear un Go to definition personalizado para soporte entre lenguajes.
Ojalá Microsoft me contratara solo por unos meses, me sentara en un rincón y me dejara desenredar este desastre.
Administré servidores para clases de redes, exploits binarios y programación de sistemas introductoria, y esta cosa es un gran dolor de cabeza. Por culpa de este tonto troyano de acceso remoto, los estudiantes no entienden cómo usar el cliente OpenSSH
Intenté varias cosas para solucionarlo. En el motd del servidor de la clase escribí que no usaran el plugin de servidor remoto de VSCode, y frente a la clase ejecuté
ncdu /homepara mostrar que cualquier estudiante cuyo uso de disco en el servidor superara los 100 MB era, sin excepción, usuario de VSCodeTambién puse un límite de 45 procesos por usuario, porque por alguna razón el troyano de acceso remoto de VSCode usa alrededor de 50 procesos de Node. Si los estudiantes ignoraban el motd y las advertencias en clase, caían en el límite y tenían que pedirnos que matáramos sus procesos para poder conectarse de nuevo
Al final cambié el límite de procesos por un script que mata todos los troyanos de acceso remoto
.vscode-servercada 10 segundosEn una clase en la que fui ayudante, había una tarea que consistía en procesar código máquina básico para imitar las herramientas de ensamblado y ejecución de la ISA que habíamos aprendido, y los estudiantes tenían que entender la estructura de bytes de los archivos con cosas como
hexdumpPero Sublime “amablemente” renderizaba los archivos objeto como una representación textual tipo hexdump, agregando espacios para mejorar la legibilidad, y los mostraba en un orden de endianidad distinto al que se veía al hacer
hexdumpen el servidor Linux de la escuelaCada semestre algunos estudiantes venían a preguntar por qué el código que habían escrito para leer una cadena ASCII como
AD DE EF BEencontraba texto desconocido, y era porque no habían comprobado que los bytes reales empezaran con 0xDE, 0xAD, 0xBE, 0xEFNo tengo muy claro cuál es la alternativa aquí. La edición por SSH de VSCode funciona sorprendentemente bien, y hace mucho dejé de andar peleándome con vim, nano o micro en máquinas remotas
El agente me deja trabajar en silencio y sin estorbar. Se siente casi como trabajar en mi máquina local, y para mí eso es una gran ventaja
Puede ser un riesgo de seguridad, pero la experiencia de desarrollo no tiene comparación. No me importa mucho qué otros editores esté matando VSCode; solo necesito que la herramienta me deje trabajar sin estorbar
No despliega binarios; lee y escribe bytes a través de pipes, y toda ejecución significativa ocurre localmente. En particular, no crea persistencia: no es lo mismo que “el plugin de VSCode pueda acceder mientras estás conectado por SSH” a que “el plugin de VSCode pueda acceder para siempre”
Cuando trabajan con varios remotos, a menudo no saben a cuál están conectados ni cuál es el estado de la conexión. La terminal es lenta y la persistencia del estado de la sesión es irregular
Es una experiencia mucho peor que usar
tmuxy un editor de texto decente. Además, el servidor es muy pesado y no se cierra correctamente, así que es común que terminen con seis instancias del servidor levantadasLa mitad de las actualizaciones se rompen, y a veces pierden una hora porque no saben entrar al host con un cliente ssh real y limpiar el servidor de vscode roto
¿Qué aprendimos? ¿Que existe la ejecución remota de código? ¿Que la confianza mal puesta en herramientas de desarrollo suele terminar en arrepentimiento? ¿Que el diseño de software moderno es un desastre? Todo eso era obvio con un poco de cuidado.
SSH es una solución de los 90. Es Telnet con algunas funciones agregadas y, aunque se le llame shell “segura”, literalmente es menos segura que Telnet+TLS.
La gente que decidió que, como ya tenía un túnel con una sesión de usuario en el servidor, no hacía falta crear un transporte de red para aplicaciones ni un protocolo de conexión segura por separado, terminó montando sobre SSH toda clase de cosas raras pero celebradas.
Es el resultado de abandonar conceptos aprendidos de los sistemas operativos distribuidos, ignorar la autenticación y autorización avanzadas desarrolladas desde entonces, y adoptar lo peor y más fácil.
Que exista este tipo de “SSH agent” no es absurdo. No nos movimos para crear la herramienta correcta para el trabajo, así que seguimos metiendo cada vez más cosas en una herramienta existente que no fue diseñada originalmente para eso. No tenemos derecho a hacernos los sorprendidos.
Este es el mundo que construimos. Lo construimos todos, con nuestro trabajo o con nuestra complicidad silenciosa. Aunque no sea SSH, pasa lo mismo en la política, el comercio, la escuela y todo lo demás. Vivimos todos los días en el montón que nosotros mismos levantamos, y cada día que no hacemos nada es otra palada encima. No puedes tener la pala en la mano y fingir que esto es sorprendente o una locura.
Por eso, si en general permites conexiones HTTPS salientes, lo correcto sería permitir también todas las conexiones salientes excepto SMTP. El tráfico malicioso real de todos modos se tunelizará por HTTPS, y el único efecto restante es obstaculizar el despliegue de protocolos nuevos que no carguen con la complejidad e ineficiencia de los túneles.
Ojalá los inicios de sesión web se parecieran más a la forma en que lo hace SSH.
Salir de vez en cuando a tocar pasto le hace bien al alma. Y también estaría bueno que propusieras cómo crear un protocolo SSH mejor. Quejarse sin crítica constructiva no sirve de mucho.
El término “SSH agent” aquí es confuso, porque normalmente se refiere a un daemon que cachea tokens de autenticación.
Además, ese enfoque rompe el conocido SSH agent de macOS: https://github.com/maxgoedjen/secretive/issues/543
Estoy totalmente de acuerdo en que usar vscode remote en un servidor de producción es una locura.
Dicho eso, el resto de las funciones descritas como “absurdas” suenan a funciones esperables.
Llegué a staff engineer en MAANG, y creo que es un nivel difícil de alcanzar solo con Vim básico. Aun así, veo que otros perfiles de alto rendimiento tienden a seguir usando Vim o Emacs.
Hay muchos desarrolladores excelentes que usan VCode, JetBrains, etc., pero creo que la tendencia a buscar barreras de entrada, desarmar la magia de las herramientas mediante exploración, y valorar proyectos completamente open source, muy modificables e impulsados por la comunidad explica mejor este fenómeno que la funcionalidad o la facilidad de uso.
Leer lo complejo que es la edición remota de VSCode en realidad me da menos ganas de usar VSCode. Basta con entrar por ssh a la máquina y usar el editor que está en esa máquina.
La solución de VSCode funciona, pero no es elegante, no es aplicable universalmente y es más fácil que se rompa. Y, con perdón para los usuarios de Emacs, Tramp sigue siendo bastante horrible y netrw tampoco es mejor.
watchexec+rsyncPuedes vigilar rutas de archivos específicas y sincronizar exactamente solo lo necesario. Sigues trabajando en el sistema de archivos local, así que no hay latencia al editar, puedes usar todas tus herramientas locales y la sincronización termina en milisegundos.
Puedes hacer que los archivos que borras localmente también se borren en remoto, y siempre te queda una copia local después de terminar de trabajar en la máquina remota. En Tramp, eso era algo que siempre había que sincronizar manualmente. Además, es independiente del editor.
Esta función de VS Code me inquieta ahora que sé lo que realmente hace.
Activé Copilot y aparecieron más barras de herramientas, además de texto entrando volando en el lugar donde quería escribir. Vim simplemente me deja ver el código, pensar y escribir. Con VSCode me cuesta entrar en estado de flow.
Estoy a mitad de mis 30; en la universidad usaba emacs y en mi primer trabajo cambié a vim. En proyectos Java muy enrevesados usé IntelliJ, pero fuera de eso seguí usando vim.
Solo abro vim de vez en cuando cuando necesito manipular texto con regex complejas.
En vez de funcionar junto con las herramientas remotas existentes, VSCode despliega un agente integral que incluye la instalación de un binario de Node.js, una conexión WebSocket de vuelta al frontend de VSCode y amplias capacidades de acceso al sistema.
Este agente de VSCode tiene permisos amplios, que incluyen explorar el sistema de archivos, editar archivos, crear procesos PTY de shell e incluso la capacidad de persistirse a sí mismo.
Si es la remota, entiendo que el Tramp de elisp es más liviano en términos de dependencias, pero me pregunto si la superficie de ataque realmente es tan distinta. Es decir, no sé si el binario remoto de Node tiene permisos que no tenga un usuario que ejecuta comandos ssh arbitrarios.
Si el objetivo original era darle a un LLM todas las llaves de una máquina virtual temporal y descartable, me pregunto si el socket abierto por el agente implica que también puede tocar la máquina del desarrollador que se buscaba aislar.
Suena como una idea loca, pero el propio kernel podría ofrecer un servidor web u otro protocolo con cifrado y autenticación, y permitir controlar directamente toda la máquina mediante eBPF. Podría ser un paradigma completamente distinto de control remoto cliente/servidor.
Claro que también podría ser un agujero de seguridad tan grande como para que pase la Estrella de la Muerte.