1 puntos por GN⁺ 3 시간 전 | 1 comentarios | Compartir por WhatsApp
  • github.dev usa un token OAuth recibido de github.com para ver archivos, enviar PRs y hacer commits en VSCode dentro del navegador, y como ese token no está limitado a un repositorio específico, puede leer y escribir en todos los repositorios a los que el usuario tenga acceso
  • El webview de VSCode se aísla con un iframe vscode-webview://..., pero para mejorar la UX de atajos de teclado reenvía el keydown del webview a la ventana principal mediante un mensaje did-keydown, lo que permite que scripts no confiables envíen eventos como si fueran pulsaciones reales del usuario
  • La entrada de texto arbitraria no funciona por el uso de HTML <input>, pero combinando el atajo predeterminado Ctrl+Shift+A, la notificación de instalación de extensiones recomendadas, las local workspace extensions y combinaciones de teclas personalizadas, es posible ejecutar el comando de instalación de extensiones
  • La PoC ejecuta JavaScript desde una celda Markdown de un Jupyter notebook, acepta la instalación de una extensión recomendada, instala después la extensión elegida con una nueva combinación de teclas y finalmente muestra el token de la API de GitHub y la lista de repositorios privados
  • VSCode de escritorio también tiene la misma vulnerabilidad, pero el atacante debe lograr que la víctima clone el repositorio y abra el notebook; los usuarios de github.dev necesitan borrar los datos del sitio para que vuelva a aparecer el cuadro de confirmación inicial como medida de defensa

Resumen de la vulnerabilidad

  • github.dev abre una versión ligera de VSCode que corre en el navegador cuando se cambia la URL de un repositorio accesible de github.com a github.dev o se hace clic en una opción del menú
  • Este VSCode en el navegador permite ver archivos del repositorio, abrir también repositorios privados, y además enviar PRs y crear commits
  • github.com hace un POST a github.dev con un token OAuth que le permite interactuar con GitHub en nombre del usuario, y ese token no está restringido al repositorio específico con el que el usuario interactuó
  • Un atacante puede robar un token de GitHub con permisos de lectura y escritura con solo lograr que la víctima haga clic en un enlace, incluyendo acceso a repositorios privados

Aislamiento de Webview y problema de reenvío de teclas

  • Los VSCode webviews aíslan la ejecución de JavaScript usando un <iframe> con un origen distinto al de la ventana principal de VSCode
  • La salida de un Jupyter notebook se renderiza dentro de un <iframe> con origen vscode-webview://..., mientras que la ventana principal de Electron usa el origen vscode-file://...
  • Gracias a este aislamiento, aunque el notebook use visualización HTML o widgets interactivos basados en JavaScript, no puede llamar a las APIs de Node.js de Electron ni a la API de VSCode desde dentro del iframe
  • Las funciones que requieren cooperación entre la ventana principal y el webview, como la vista previa Markdown, intercambian mensajes mediante la API Window.postMessage()
  • VSCode reenvía el evento did-keydown a la ventana principal para que atajos como Ctrl+Shift+P sigan funcionando incluso cuando el foco está dentro del webview
  • Un script no confiable dentro del webview puede disparar directamente eventos keydown y hacerse pasar por pulsaciones reales del usuario

Cadena de ataque

  • Se puede abrir la paleta de comandos con Ctrl+Shift+P, pero como la paleta usa un HTML <input>, no funciona un enfoque basado en escribir cadenas arbitrarias
  • Sí pueden usarse entradas procesadas como keydown, como las flechas de dirección y Enter, y también aprovechar el conjunto de atajos predeterminados de VSCode
  • Ctrl+Shift+A es la combinación predeterminada para “Notifications: Accept Notification Primary Action” y pulsa el botón principal de la última notificación de VSCode
  • Si se incluyen extensiones recomendadas en .vscode/extensions.json, VSCode muestra una notificación para instalarlas, pero el sistema de confianza de publishers de VSCode 1.97 muestra un cuadro adicional al instalar una extensión de un publisher nuevo
  • Aunque es posible mover el foco entre botones con Tab, el manejo de Enter en el botón “Trust Publisher & Install” está ligado al keydown del propio botón, por lo que resulta difícil completar la instalación solo por esa ruta
  • Las local workspace extensions permiten instalar directamente extensiones ubicadas en .vscode/extensions dentro de un workspace confiable, y github.dev/web workspace siempre se considera confiable
  • Si se intenta ejecutar directamente una extensión local del workspace, el worker de extensiones espera una extensión proveniente de vscode-cdn.net, lo que provoca un error de CSP
  • En cambio, es posible agregar una combinación de teclas personalizada en el package.json de la extensión local del workspace para que esa combinación invoque workbench.extensions.installExtension con el contexto skipPublisherTrust

Funcionamiento e impacto de la PoC

  • La configuración necesaria es un repositorio que contenga un Jupyter notebook y una local workspace extension
  • Una celda Markdown del notebook puede ejecutar JavaScript mediante el atributo onerror de una imagen
  • El payload espera hasta que VSCode muestre la notificación para instalar la extensión recomendada y luego envía el evento Ctrl+Shift+A para aceptar la acción principal de la notificación
  • Después espera a que la extensión se instale, se active y cargue la combinación de teclas personalizada, y luego envía el evento Ctrl+F1 para disparar la instalación de la extensión elegida
  • La extensión instalada por la PoC obtiene el token de la API de GitHub, consulta https://api.github.com/user/repos para obtener los repositorios privados accesibles y luego muestra el token y la lista de repositorios en un cuadro informativo
  • Tras ejecutar la PoC, es necesario borrar los datos de github.dev o eliminar la extensión de la PoC; si no se elimina, seguirá activa en todas las páginas de github.dev
  • VSCode de escritorio también presenta la misma vulnerabilidad, pero el atacante debe lograr que la víctima clone el repositorio y abra el notebook que contiene el payload del script del webview
  • Si el webview que abre la víctima tiene otra vulnerabilidad XSS, en escritorio esto podría derivar prácticamente en ejecución remota de código completa

Defensas y factores de mitigación

  • Si nunca se ha usado github.dev antes, al entrar al sitio aparece un cuadro de diálogo que requiere un clic, lo que da una oportunidad para salir de la página maliciosa
  • Si se borran las cookies y los datos locales del sitio de github.dev, ese cuadro de diálogo inicial puede aparecer de nuevo
  • En Chrome, se puede pulsar el ícono de la barra de direcciones e ir a Cookies and site data > Manage on-device site data para borrar los datos del dominio correspondiente
  • Si el usuario ya pasó ese cuadro de github.dev y no ha borrado el almacenamiento local del navegador, github.dev no tiene protecciones como un token CSRF, por lo que cualquier enlace en internet podría redirigir al ataque
  • VSCode no depende solo del aislamiento por iframe, sino que también usa una estricta Content Security Policy y DOMPurify
  • Como la vista previa Markdown de la página de extensiones usa script-src 'none' para impedir la ejecución arbitraria de JavaScript, se bloquea un impacto mayor donde un simple enlace a una extensión se convertiría en RCE de 1 clic en escritorio

Contexto de la divulgación y cronología

  • MSRC corrigió discretamente reportes anteriores de bugs de VSCode sin dar crédito y los marcó como sin impacto de seguridad
  • Un reciente reporte de bug XSS de VSCode de Starlabs también fue marcado como no elegible y de baja severidad
  • Puede que el equipo de VSCode necesitara más tiempo para equilibrar UI/UX y seguridad, pero se optó por una divulgación completa porque no se debe dar por sentado el tiempo y esfuerzo de los investigadores de seguridad
  • Una hora antes de su publicación, el 2 de junio de 2026, se informó de la divulgación prevista a un contacto previo del equipo de seguridad de GitHub
  • Ese mismo día se publicó la vulnerabilidad y también se registró en el issue tracker de VSCode

1 comentarios

 
GN⁺ 3 시간 전
Comentarios de Hacker News
  • Fue un buen resumen y, viéndolo en grande, lo decepcionante es que el editor VSCode embebido en la web esté conectado a GitHub.
    Independientemente de si hay defensa en profundidad o no, ese pecado original amplía mucho la superficie de ataque. Es parecido a dejar en texto plano en la estación de trabajo un token de la API de GitHub con todos los permisos para que cualquier paquete NPM malicioso pueda encontrarlo.
    Idealmente, el IDE en el navegador debería ejecutarse con un alcance temporal por repositorio o con un token que solo permita pull/push sobre ese repositorio, y no debería haber ninguna sesión web de github.com. Si hace falta toda la interfaz web de GitHub, uno vuelve a github.com, y github.dev debería quedarse como un servicio para un solo repositorio.
    Claro, eso sería incómodo para el usuario, difícil de implementar y probablemente chocaría con supuestos que históricamente están metidos por todas partes en las herramientas de github.dev

    • Codespaces de hecho funciona así. El token solo tiene permisos de lectura/escritura sobre el repositorio del Codespace activado [1]
      github.dev también debería considerar seriamente este enfoque
      [1] https://orca.security/resources/blog/hacking-github-codespac...
    • El problema de los paquetes NPM maliciosos parece que va a empeorar cada vez más. Hace poco vi herramientas de ejecución con IA como OpenCode descargar paquetes npm arbitrarios en segundo plano y regarlos por el directorio home y por varios lugares del directorio del proyecto, sin avisarle ni preguntarle al usuario.
      Peor aún, ni siquiera parece que a los desarrolladores les importe demasiado
    • Que estés conectado cuando abres tu propio repositorio está bien, pero cuando abres el repositorio de otra cuenta nunca debería pasar eso. Y también deberían corregir los atajos de teclado de webview para que solo permitan combinaciones inofensivas y no se propaguen a ningún manejador de keydown.
      En escritorio sería mejor que Electron los interceptara directamente y eliminar esta función; en la web, parece correcto desactivarla por defecto
    • Con claves SSH y una GitHub deploy key se puede lograr algo más o menos parecido. No puedo asegurar que sea más seguro, pero nunca he configurado GitHub con acceso a todos los repositorios.
      No sé bien si otros hostings de Git tienen una función similar
    • Me pregunto si se podría permitir hacer pull desde ese repositorio, pero que el push no vaya con el token sino solo a un área de staging desde donde el usuario haga el push final.
      Sinceramente, los agentes LLM también deberían funcionar así. Dejar que un LLM haga push directo parece imprudente
  • Lo que hace este ataque especialmente complicado es que las extensiones de VSCode se ejecutan con el mismo nivel de confianza que el propio editor, y la mayoría de los desarrolladores tienen instaladas decenas de extensiones cuyos permisos nunca revisaron.
    Si una extensión maliciosa o comprometida filtra silenciosamente un token de GitHub, es difícil detectarlo sin monitoreo de red, y eso respalda la idea de que las extensiones deberían ejecutarse en perfiles aislados

    • Incluso con monitoreo de red, si la exfiltración se hace hacia GitHub mismo, es muy difícil bloquearla. Sobre todo si no tienes intercepción SSL y una lista de permitidos de URL extremadamente estricta
      La mejor opción es salir de GitHub, migrar a un GitLab/Forgejo interno autoalojado y bloquear GitHub por completo
  • Hace poco me pasó algo parecido. Me robaron un token de GitHub y un token de Cloudflare.
    Aunque uno se tome la seguridad en serio, si pasa suficiente tiempo, al final te toca. Lo mejor es separar y limitar el alcance del daño.
    No confíes en nadie ni en nada, usa OrbStack y trabaja siempre asumiendo que los tokens algún día se van a filtrar.
    Mi flujo de trabajo quedó totalmente roto, pero por suerte quienes se llevaron los tokens parecían más bien bots de spam. Crearon un montón de páginas falsas de spam e intentaron minar criptomonedas.
    La sensación que más me quedó fue la de haber sido vulnerado. Cuídense todos

    • Me da curiosidad si eran páginas tipo GitHub Pages. ¿Te crearon repositorios en la cuenta? También me interesa cómo te diste cuenta de que te habían robado el token
  • La parte de haber reportado el bug de VSCode a MSRC y que lo arreglaran en silencio fue una experiencia horrible, muy típica de MSRC. Parece que ya se dieron cuenta de que los investigadores igual les reportan gratis, así que no ven por qué cambiar eso

    • MSRC no es quien corrige los bugs.
      No conozco los detalles concretos de este caso, pero antes administré programas de bug bounty mediante Bountysource y HackerOne. A veces pasa que un reporte llega al equipo de desarrollo antes de que el equipo de seguridad termine de evaluarlo.
      En ese punto, un desarrollador puede corregirlo en silencio. A veces por el temor —racional o no— de que, si queda asociado a un bug de seguridad, eso lo haga ver mal o afecte sus oportunidades de ascenso. Como resultado, cuando el equipo de seguridad intenta reproducirlo, la vulnerabilidad ya no está.
      Desde la perspectiva de MSRC, lo único que ven es que los pasos de reproducción que les dieron ya no funcionan. No pueden ver el historial interno del bug ni si alguien ya lo parchó. Entonces el reporte se cierra como inválido, aunque el hallazgo original haya sido legítimo
    • Durante mucho tiempo ese fue el status quo, hasta que investigadores de seguridad molestos empezaron a exigir recompensa en vez de reputación
  • Gracias por básicamente donar el tiempo invertido en este exploit para visibilizar la necesidad de mejorar la respuesta de seguridad de VS Code. Podrías simplemente haberte rendido, pero sigues ayudando

    • No tengo intención de vender ni guardar esta vulnerabilidad. Pero sí, hacer una prueba de concepto puede tomar varias horas, y se siente realmente mal cuando el proveedor solo la parchea en silencio y no te da ni crédito ni reconocimiento
  • No entiendo muy bien por qué más desarrolladores no prueban Neovim
    Puede ser cuestión de gustos, pero me gusta una configuración pequeña donde puedas entender qué está instalado y qué está corriendo. Cuando se mezclan VSCode, IDEs en el navegador, extensiones, sincronización, tokens y plugins arbitrarios, se vuelve difícil saber qué tiene acceso a qué

    • Hace unos años dejé VS Code y me pasé a Neovim. Fue después de darme cuenta de que VS Code instalaba automáticamente paquetes de Python arbitrarios para bibliotecas sin definiciones de tipos predeterminadas
      Era una función de la extensión oficial de Python de Microsoft y, en otros aspectos, era más o menos la única extensión realmente usable, pero instaló definiciones de tipos para una versión de la biblioteca distinta de la que usaba mi proyecto. Me dio mucha desconfianza porque parecía ejecutar código de terceros no verificado con toda naturalidad, y tampoco parecía que se pudiera desactivar con una configuración
      Me gustaría decir que “nunca miré atrás”, pero, siendo sincero, en los últimos 1 o 2 años Neovim empezó a romperme la configuración de forma regular con casi cada actualización. Ya había señales de que algún día podía pasar. Técnicamente ya pasaron 10 años, pero nvim sigue sin sacar una primera versión estable, así que no se le puede culpar por la inestabilidad, aunque vale la pena tenerlo presente
      Estoy pensando en volver a Vim puro. Perdería muchas funciones de comodidad, pero me gustaría tener que depurar menos cosas rotas mientras trabajo
    • Helix me gusta bastante. No he profundizado mucho en Neovim, pero Helix ya trae bastante bien integradas varias funciones tipo IDE que siempre eché de menos en Vim
      No hace falta instalar un montón de plugins ni usar algo como SpaceVim. Vale la pena echarle un vistazo; capaz te gusta
    • He notado que es bastante difícil hacer que la gente cambie sus hábitos de software. Hay atajos que aprender y, al principio, se siente más lento, lo que refuerza esa sensación de que “no es mejor”
      Lleva tiempo acostumbrarse a nvim, pero, una vez que te acostumbras, es más rápido. Aun así, eso explica por qué mucha gente se queda en su zona de confort
  • Hacer divulgación pública fue una buena decisión. Hay demasiada gente descontenta con MSRC y, como en la situación de Nightmare Eclipse, esto ya empieza a desbordarse
    Si se acumulan divulgaciones como esta, tal vez MSRC haga un poco de introspección y se dé cuenta de que ellos son el problema. No parece muy probable, pero se puede tener esperanza

    • No estoy seguro de que esto siga siendo el mejor enfoque. Parece que ni siquiera intentó reportarlo porque esperaba que lo clasificaran como “bajo” comparado con envíos previos de XSS
      Aun así, creo que por lo menos debió intentarlo, o avisar varios días antes de hacerlo público. Uno nunca sabe qué podría pasar
  • El artículo estuvo muy bien, pero me confundí un poco en la parte final. Quiero confirmar si entendí bien
    El autor dijo que, por el nuevo sistema de confianza de publicadores, no se puede instalar directamente una extensión maliciosa solo con el truco del atajo, y que eso se puede rodear con una extensión local del workspace que no tiene verificación de publicador, pero que el CSP lo bloquea
    La solución parece ser instalar una extensión local del workspace que vincule el atajo de “instalar extensión sin verificar publicador”
    Entonces, 1) me pregunto si eso significa que hacen falta dos extensiones. La primera sería una extensión local que solo hace el keybinding, y la segunda sería la extensión realmente maliciosa, que por culpa del CSP ni siquiera necesita ser local y de hecho no podría serlo; y 2) me pregunto si el CSP solo bloquea el JS de la extensión local, pero no package.json ni la capacidad de agregar atajos

    • 1 y 2 son correctos. Puedes ver el repositorio de prueba de concepto: https://github.com/ammaraskar/github-dev-token-steal-poc/tre...
      Podrías intentar poner my-extension/extension.js para una ejecución más directa, pero el CSP lo bloquea. Sin embargo, como el script-src del CSP solo bloquea scripts, sí permite cargar package.json. Entonces eso se aprovecha para aportar el keybinding
  • La situación de MSRC es realmente difícil de creer
    Seguro hay material mejor, pero creo que este video de The Primeagen es una buena introducción
    https://www.youtube.com/watch?v=9kxx5xp5nTQ

  • Sobre la parte que dice “la única manera de permitir este comportamiento es que dos páginas web de distintos orígenes cooperen usando la API Window.postMessage()”, tengo una pequeña objeción
    También se puede comunicar mediante un iframe o haciendo que la ventana padre cambie la propiedad location.anchor