1 points par GN⁺ 3 시간 전 | 1 commentaires | Partager sur WhatsApp
  • github.dev utilise un jeton OAuth transmis par github.com pour permettre, dans VSCode au navigateur, la consultation de fichiers, les PR et les commits ; ce jeton n’est pas limité à un dépôt précis et permet donc de lire et d’écrire sur l’ensemble des dépôts auxquels l’utilisateur a accès
  • Les webviews de VSCode sont isolées dans des iframes vscode-webview://..., mais pour l’UX des raccourcis clavier, le keydown de la webview est transmis à la fenêtre principale via un message did-keydown, ce qui permet à des scripts non fiables d’envoyer des événements comme s’il s’agissait de frappes utilisateur
  • Une saisie de texte arbitraire ne fonctionne pas à cause des balises HTML <input>, mais en combinant le raccourci par défaut Ctrl+Shift+A, la notification d’installation d’extension recommandée, les local workspace extensions et des raccourcis clavier personnalisés, il est possible d’exécuter la commande d’installation d’extension
  • Le PoC exécute du JavaScript depuis une cellule Markdown d’un notebook Jupyter, accepte l’installation d’une extension recommandée, installe ensuite l’extension choisie via un nouveau raccourci clavier, puis affiche le jeton de l’API GitHub et la liste des dépôts privés
  • VSCode Desktop est lui aussi vulnérable, mais l’attaquant doit convaincre la cible de cloner le dépôt et d’ouvrir le notebook ; les utilisateurs de github.dev doivent effacer les données du site pour faire réapparaître la boîte de dialogue de confirmation initiale comme mesure défensive

Présentation de la vulnérabilité

  • github.dev ouvre une version légère de VSCode exécutée dans le navigateur si l’on remplace, sur une URL de dépôt GitHub accessible, github.com par github.dev ou si l’on clique sur l’entrée de menu correspondante
  • Ce VSCode dans le navigateur permet de consulter les fichiers du dépôt, d’ouvrir aussi des dépôts privés, ainsi que d’envoyer des PR et de créer des commits
  • github.com envoie à github.dev, via POST, un jeton OAuth permettant d’interagir avec GitHub au nom de l’utilisateur, et ce jeton n’est pas limité au dépôt spécifique avec lequel l’utilisateur a interagi
  • Un attaquant peut voler un jeton GitHub disposant de droits de lecture et d’écriture par un simple clic sur un lien, y compris sur des dépôts privés

Isolement des webviews et problème de transmission des frappes clavier

  • Les webviews VSCode isolent l’exécution JavaScript en utilisant une <iframe> d’une origin différente de celle de la fenêtre principale de VSCode
  • La sortie des notebooks Jupyter est rendue dans une <iframe> d’origin vscode-webview://..., tandis que la fenêtre principale Electron utilise l’origin vscode-file://...
  • Grâce à cet isolement, même si un notebook utilise de l’affichage HTML ou des widgets interactifs en JavaScript, il ne peut pas appeler l’API Node.js d’Electron ni l’API VSCode depuis l’intérieur de l’iframe
  • Les fonctionnalités où la fenêtre principale et la webview doivent coopérer, comme l’aperçu Markdown, échangent des messages via l’API Window.postMessage()
  • VSCode transmet au volet principal les événements did-keydown afin que des raccourcis comme Ctrl+Shift+P fonctionnent même quand le focus est dans la webview
  • Un script non fiable exécuté dans la webview peut déclencher directement des événements keydown pour se faire passer pour l’utilisateur

Chaîne d’attaque

  • Il est possible d’ouvrir la palette de commandes avec Ctrl+Shift+P, mais comme elle utilise un <input> HTML, une approche consistant à saisir une chaîne arbitraire ne fonctionne pas
  • En revanche, on peut utiliser des entrées traitées via keydown, comme les flèches directionnelles et Enter, ainsi que l’ensemble des raccourcis par défaut de VSCode
  • Ctrl+Shift+A correspond au raccourci par défaut de « Notifications: Accept Notification Primary Action » et clique sur le bouton principal de la dernière notification VSCode
  • Si l’on ajoute une extension recommandée dans .vscode/extensions.json, VSCode affiche une notification d’installation, mais le système de confiance des éditeurs de VSCode 1.97 ouvre une boîte de dialogue distincte lors de l’installation d’une extension provenant d’un nouvel éditeur
  • Il est possible de naviguer entre les boutons avec Tab, mais l’action Enter du bouton « Trust Publisher & Install » est liée au keydown du bouton lui-même, ce qui rend l’installation difficile par cette seule voie
  • Les local workspace extensions permettent d’installer directement les extensions situées dans .vscode/extensions dans un workspace de confiance, et github.dev / les web workspaces sont toujours considérés comme fiables
  • Si l’on tente d’exécuter directement une extension locale de workspace, le worker d’extension s’attend à une extension venant de vscode-cdn.net, ce qui provoque une erreur CSP
  • À la place, on peut ajouter un raccourci clavier personnalisé dans le package.json d’une extension locale de workspace, afin que ce raccourci appelle workbench.extensions.installExtension avec le contexte skipPublisherTrust

Fonctionnement du PoC et impact

  • La configuration nécessaire est un dépôt contenant un notebook Jupyter et une local workspace extension
  • Une cellule Markdown du notebook peut exécuter du JavaScript via l’attribut onerror d’une image
  • La charge utile attend que VSCode affiche la notification d’installation d’extension recommandée, puis envoie l’événement Ctrl+Shift+A pour accepter l’action principale de la notification
  • Elle attend ensuite que l’extension soit installée et activée, puis que le raccourci clavier personnalisé soit en place, avant de déclencher l’installation de l’extension choisie via l’événement Ctrl+F1
  • L’extension installée dans le PoC récupère le jeton de l’API GitHub et interroge https://api.github.com/user/repos pour obtenir les dépôts privés accessibles, puis affiche le jeton et la liste des dépôts dans une boîte d’information
  • Après l’exécution du PoC, il faut effacer les données de github.dev ou supprimer l’extension du PoC ; sans cela, elle persiste sur toutes les pages github.dev
  • VSCode Desktop présente la même vulnérabilité, mais l’attaquant doit convaincre la victime de cloner le dépôt et d’ouvrir un notebook contenant la charge utile de script de webview
  • S’il existe une autre XSS dans la webview ouverte par la victime, cela peut en pratique conduire à une exécution de code à distance quasi totale sur Desktop également

Défense et éléments d’atténuation

  • Si l’on n’a jamais utilisé github.dev auparavant, une boîte de dialogue nécessitant un clic apparaît à l’ouverture du site, ce qui offre une occasion d’échapper à la page d’attaque
  • Effacer les cookies et les données locales du site de github.dev peut faire réapparaître cette boîte de dialogue initiale
  • Dans Chrome, on peut cliquer sur l’icône de la barre d’adresse, puis aller dans Cookies and site data > Manage on-device site data pour supprimer les données des domaines concernés
  • Si l’utilisateur a déjà passé la boîte de dialogue github.dev et n’a pas effacé le stockage local du navigateur, github.dev ne dispose pas de protections de type jeton CSRF, ce qui permet à n’importe quel lien sur Internet de rediriger vers l’attaque
  • VSCode ne s’appuie pas uniquement sur l’isolement par iframe, mais utilise aussi une Content Security Policy stricte et DOMPurify
  • En utilisant script-src 'none' dans l’aperçu Markdown de la page d’extension, l’exécution de JavaScript arbitraire est bloquée, ce qui empêche un impact plus grave où un simple lien d’extension deviendrait une RCE en un clic sur Desktop

Contexte de la divulgation et calendrier

  • Le MSRC a par le passé corrigé discrètement des signalements de bugs VSCode sans attribuer de crédit et en les marquant comme sans impact sécurité
  • Récemment, le signalement du bug XSS VSCode par Starlabs a lui aussi été marqué comme non éligible et de faible sévérité
  • L’équipe VSCode avait peut-être besoin de plus de temps pour trouver un équilibre entre UI/UX et sécurité, mais une divulgation complète a été choisie au motif qu’il ne faut pas considérer comme acquises le temps et les efforts des chercheurs en sécurité
  • Le 2 juin 2026, une heure avant la publication, la divulgation prévue a été communiquée à un contact existant de l’équipe sécurité GitHub
  • Le même jour, la vulnérabilité a été rendue publique et enregistrée aussi dans le tracker d’issues VSCode

1 commentaires

 
GN⁺ 3 시간 전
Réactions sur Hacker News
  • C’était un bon récapitulatif et, plus globalement, le fait même que l’éditeur VSCode embarqué dans le web soit connecté à GitHub est regrettable
    Indépendamment de la défense en profondeur, c’est ce péché originel qui crée une énorme surface d’attaque. C’est comparable au fait de laisser en clair sur le poste de travail un token d’API GitHub avec tous les droits, afin qu’un paquet NPM malveillant puisse le trouver
    Dans l’idéal, l’IDE dans le navigateur fonctionnerait avec un périmètre d’autorisations temporaire, limité au dépôt concerné, ou avec un token équivalent ne permettant que le pull/push sur ce dépôt, sans aucune session web github.com. Si l’on a besoin de l’interface web complète de GitHub, on retourne sur github.com, et github.dev reste un service centré sur un seul dépôt
    Mais ce serait moins pratique pour l’utilisateur, difficile à mettre en œuvre, et il est probable que toute la boîte à outils github.dev repose historiquement sur des hypothèses contraires

    • Codespaces fonctionne effectivement ainsi. Le token n’a que des droits de lecture/écriture sur le dépôt du Codespace activé [1]
      github.dev devrait sérieusement envisager cette approche
      [1] https://orca.security/resources/blog/hacking-github-codespac...
    • Le problème des paquets NPM malveillants risque de s’aggraver. J’ai récemment vu des outils d’exécution IA comme OpenCode télécharger en arrière-plan des paquets npm arbitraires et les disséminer un peu partout dans le répertoire personnel et les répertoires de projet, sans prévenir l’utilisateur ni lui demander son avis
      Le pire, c’est que même les développeurs ne semblent pas vraiment s’en soucier
    • Être connecté quand on ouvre son propre dépôt, pourquoi pas, mais ça ne devrait jamais être le cas quand on ouvre le dépôt d’un autre compte. Et il faudrait aussi corriger les raccourcis clavier des webviews pour n’autoriser que des combinaisons inoffensives et empêcher leur propagation vers le moindre gestionnaire keydown
      Sur desktop, il vaudrait mieux qu’Electron les intercepte directement et supprimer cette fonctionnalité ; sur le web, la désactiver par défaut semble plus approprié
    • Avec des clés SSH et des GitHub deploy keys, on peut obtenir quelque chose d’assez proche. Je ne peux pas garantir que ce soit plus sûr, mais je n’ai jamais mis en place une configuration GitHub donnant accès à tous les dépôts
      Je ne sais pas vraiment si d’autres hébergeurs Git proposent une fonction similaire
    • On pourrait autoriser le pull sur le dépôt concerné, mais faire en sorte que le push n’aille pas via un token, seulement vers une zone de staging d’où l’utilisateur pourrait effectuer le push final
      Honnêtement, les agents LLM devraient aussi fonctionner comme ça. Les laisser pousser directement me paraît imprudent
  • Cette attaque est particulièrement délicate parce que les extensions VSCode s’exécutent avec le même niveau de confiance que l’éditeur lui-même, et que la plupart des développeurs en installent des dizaines sans jamais vérifier leurs permissions
    Si une extension malveillante ou compromise exfiltre discrètement un token GitHub, c’est difficile à détecter sans supervision réseau, ce qui plaide pour exécuter les extensions dans des profils isolés

    • Même avec une supervision réseau, c’est très difficile à bloquer si l’exfiltration passe par GitHub lui-même. Surtout sans interception SSL ni liste blanche d’URL extrêmement stricte
      La meilleure approche consiste à quitter GitHub, migrer vers un GitLab/Forgejo interne auto-hébergé, et bloquer complètement GitHub
  • J’ai vécu quelque chose de similaire récemment. Mes tokens GitHub et Cloudflare ont été volés
    Même en prenant la sécurité au sérieux, avec suffisamment de temps, on finit par se faire avoir. Le mieux qu’on puisse faire, c’est cloisonner et limiter l’étendue des dégâts
    Il ne faut faire confiance à personne ni à rien, utiliser OrbStack, et toujours travailler en partant du principe que les tokens finiront un jour par fuiter
    Mon flux de travail a été complètement interrompu, mais heureusement, ceux qui ont récupéré les tokens ressemblaient davantage à des bots spammeurs. Ils ont créé une masse de fausses pages de spam et tenté de faire du minage de cryptomonnaies
    Le sentiment qui reste le plus fortement, c’est celui d’avoir été violé. Faites tous attention

    • Je me demande si c’était des pages du type GitHub Pages. Est-ce que des dépôts ont été créés sur le compte ? Je suis aussi curieux de savoir comment tu as découvert que les tokens avaient été compromis
  • Le passage sur l’expérience affreuse consistant à signaler le bug VSCode au MSRC pour qu’il soit corrigé discrètement, c’est du MSRC typique. Ils ont visiblement compris que les chercheurs signaleraient de toute façon gratuitement, donc ils n’ont aucune raison de changer

    • Le MSRC ne corrige pas lui-même les bugs
      Je ne connais pas les détails précis de ce cas, mais j’ai déjà géré des programmes de bug bounty via Bountysource et HackerOne. Il arrive parfois qu’un rapport soit transmis à l’équipe de développement avant même que l’équipe sécurité ne l’ait entièrement évalué
      À ce stade, un développeur peut le corriger discrètement. Parfois parce qu’il craint, rationnellement ou non, qu’un bug de sécurité lui donne mauvaise image ou nuise à ses perspectives d’avancement. Résultat : quand l’équipe sécurité essaie de reproduire le problème, la vulnérabilité a déjà disparu
      Du point de vue du MSRC, ils constatent seulement que les étapes de reproduction fournies ne fonctionnent plus. Ils n’ont pas de visibilité sur l’historique interne du bug ni sur le fait que quelqu’un l’a déjà patché. Le rapport est donc clos comme invalide, même si la découverte initiale était parfaitement légitime
    • Pendant longtemps, c’est resté le statu quo, puis des chercheurs en sécurité pénibles ont commencé à exiger une rémunération plutôt que de la réputation
  • Merci d’avoir en pratique fait don du temps passé sur cet exploit pour montrer qu’il fallait améliorer la réponse de sécurité de VS Code. Tu aurais pu laisser tomber, mais tu continues quand même à aider

    • Je n’ai pas l’intention de vendre cette vulnérabilité ni de la garder sous le coude. En revanche, produire une preuve de concept peut prendre des heures, et quand l’éditeur se contente de patcher discrètement sans accorder ni crédit ni reconnaissance, c’est vraiment rageant
  • Je ne comprends pas très bien pourquoi davantage de développeurs n’essaient pas Neovim
    C’est peut-être une question de goût, mais j’aime les petites configurations où l’on peut savoir ce qui est installé et ce qui tourne. Quand on mélange VSCode, un IDE dans le navigateur, des extensions, la synchronisation, des tokens et des plugins arbitraires, il devient difficile de savoir quoi a accès à quoi

    • J’ai abandonné VS Code il y a quelques années pour passer à Neovim. C’était après avoir découvert que VS Code installait automatiquement un paquet Python arbitraire pour des bibliothèques sans définitions de types par défaut
      C’était une fonctionnalité de l’extension Python officielle de Microsoft et, sur d’autres aspects, c’était plus ou moins la seule extension vraiment utilisable, mais elle installait des définitions de types pour une version de bibliothèque différente de celle utilisée par mon projet. Ça m’a énormément inquiété, parce que cela donnait l’impression d’exécuter sans problème du code tiers non vérifié, et il ne semblait même pas possible de le désactiver dans les paramètres
      J’aimerais dire que « je n’ai jamais regardé en arrière depuis », mais honnêtement, depuis 1 à 2 ans, Neovim s’est mis à casser régulièrement ma configuration à presque chaque mise à jour. Il y avait des signes que cela finirait par arriver. Techniquement, même après 10 ans, nvim n’a toujours pas publié sa première version stable, donc on ne peut pas vraiment lui reprocher son instabilité, mais c’est bon à garder en tête
      J’envisage de revenir à Vim pur. Je perdrai beaucoup de fonctions pratiques, mais j’aimerais au moins avoir moins souvent à déboguer des fonctionnalités cassées en plein travail
    • Helix me plaît pas mal. Je n’ai pas exploré Neovim en profondeur, mais Helix intègre assez bien les fonctionnalités de type IDE qui m’ont toujours manqué dans Vim
      Pas besoin d’installer une montagne de plugins ni d’utiliser quelque chose comme SpaceVim. Ça vaut le coup d’y jeter un œil, tu pourrais aimer
    • Je trouve qu’il est assez difficile de faire changer les habitudes logicielles. Il y a des raccourcis à apprendre, et au début on se sent plus lent, ce qui renforce l’impression que « ce n’est pas mieux »
      Il faut du temps pour s’habituer à nvim, mais une fois le cap passé, c’est plus rapide. Ça explique quand même pourquoi beaucoup de gens restent dans leur zone de confort
  • La divulgation publique était une bonne chose. Il y a beaucoup trop de gens mécontents du MSRC, et comme dans le cas Nightmare Eclipse, cela commence maintenant à déborder
    Si ce genre de divulgations s’accumule, peut-être que le MSRC finira par se remettre en question et par comprendre que le problème, c’est eux. Ça paraît peu probable, mais on peut espérer

    • Je ne suis pas certain que ce soit encore la meilleure approche. Il semble qu’il ait même renoncé à soumettre le problème, en pensant qu’il recevrait une gravité « faible » par comparaison avec ses précédents signalements de XSS
      Cela dit, j’estime qu’il aurait au moins dû essayer, ou prévenir plusieurs jours avant de publier. On ne sait jamais ce qui peut se passer
  • L’article était très bon, mais la fin m’a un peu embrouillé. Je veux vérifier si j’ai bien compris
    L’auteur dit qu’avec le nouveau système de confiance des éditeurs, on ne peut pas installer directement une extension malveillante uniquement avec le tour des raccourcis, et que le contournement via une extension locale de l’espace de travail sans vérification d’éditeur est bloqué par la CSP
    La solution semble être d’installer une extension locale de l’espace de travail qui associe le raccourci « installer une extension sans vérification de l’éditeur »
    Donc je me demande 1) si cela veut dire qu’il faut deux extensions. La première serait une extension locale qui ne fait qu’ajouter le raccourci, et la seconde la véritable extension malveillante qui, à cause de la CSP, n’a pas besoin d’être locale et ne peut d’ailleurs pas vraiment l’être, et 2) si la CSP ne bloque que le JS de l’extension locale, mais pas package.json ni la capacité d’ajouter des raccourcis

    • 1 et 2 sont corrects. Il suffit de regarder le dépôt de preuve de concept : https://github.com/ammaraskar/github-dev-token-steal-poc/tre...
      On pourrait essayer d’ajouter my-extension/extension.js pour l’exécution la plus directe, mais la CSP le bloque. En revanche, comme la CSP script-src ne bloque que les scripts, le chargement de package.json reste autorisé. C’est donc utilisé pour déclarer le raccourci clavier
  • La situation du MSRC est vraiment difficile à croire
    Il existe peut-être de meilleures ressources, mais je trouve que cette vidéo de The Primeagen est une bonne introduction
    https://www.youtube.com/watch?v=9kxx5xp5nTQ

  • J’ai un petit désaccord sur la phrase « la seule manière d’autoriser ce comportement est que deux pages web d’origines différentes coopèrent via l’API Window.postMessage() »
    Un iframe ou une fenêtre parente peut aussi communiquer en modifiant la propriété location.anchor