Badacz bezpieczeństwa Ammar Askar odkrył podatność w webowym edytorze (Visual Studio Code) udostępnianym w ramach GitHub. Samo otwarcie repozytorium mogło umożliwić atakującemu kradzież tokenu, który pozwala uzyskać dostęp do repozytoriów ofiary.
TLDR:
Badacz bezpieczeństwa Ammar Askar odkrył podatność w webowej wersji Visual Studio Code w ramach GitHub, która mogła prowadzić do przejęcia tokenu użytkownika.
Atak wykorzystywał mechanizm webview i możliwość przekazywania zdarzeń klawiatury (keydown) z osadzonego notebooka Jupyter do głównego okna edytora.
Dzięki odpowiednio przygotowanemu repozytorium atakujący mógł doprowadzić do instalacji złośliwego rozszerzenia VSCode i uzyskać dostęp do tokenu GitHub posiadającego uprawnienia do wszystkich repozytoriów ofiary.
Do przeprowadzenia ataku wystarczało otwarcie spreparowanego repozytorium w github.dev.
Microsoft opublikował poprawki blokujące wykorzystany wektor ataku dzień po jego publicznym ujawnieniu.
GitHub udostępnia funkcję do łatwej edycji plików w ramach repozytorium. Wystarczy w adresie URL zmienić domenę github.com na github.dev. Wtedy w przeglądarce uruchamia się Visual Studio Code z widokiem danego repozytorium/pliku.
Webowy edytor ma dostęp do repozytorium na takim samym poziomie, jak użytkownik. Umożliwia przeglądanie wszystkich plików, wysyłanie pull requestów, a także commitów.
Dzieje się tak dlatego, że github.com wysyła w żądaniu POST token OAuth do github.dev, który umożliwia dostęp do zasobów danego użytkownika. Co ważne – token ten nie jest ograniczony do konkretnego repozytorium – pozwala na pełny dostęp do innych repozytoriów (także prywatnych).
Visual Studio Code najczęściej kojarzymy jako aplikację desktopową opartą na Electronie, co oznacza że wykonywanie kodu JavaScript wewnątrz VSC oznaczałoby po prostu wykonanie kodu na urządzeniu użytkownika. Dlatego zastosowano sandboxing, między innymi w postaci webview.
Dla webview zdefiniowany jest inny origin niż dla głównego okna VSCode, aby zapewnić izolację wykonywanego w nich kodu. Metoda ta jest używana m.in. do podglądu Markdown albo edycji notatników Jupyter:
Rys. 2 – renderowanie kodu HTML wewnątrz iframe w Jupyter, źródło: blog.ammaraskar.com
Jak widać źródłem dla elementu iframe jest vscode-webview://…, w przeciwieństwie do głównego okna Electron, którego origin to vscode-file://…. Oznacza to, że nawet jeśli notatnik Jupyter używa JavaScript, nie można skorzystać z integracji Electrona w ramach tego iframe ani wywoływać API VSCode.
To jednak “tylko” statyczna treść. W podglądzie Markdown jest funkcja, która podkreśla aktualnie zaznaczoną linię, a także aktualizuje podgląd na żywo podczas edycji.
Zastosowanie osobnych origin uniemożliwia również głównemu oknu edytora interakcję z DOM w ramce iframe. Jedynym sposobem na komunikację między nimi jest API Window.postMessage(). Ta metoda pozwala przesyłać obiekty JavaScript między różnymi oknami. W przykładzie z podglądem Markdown główne okno edytora wysyła wiadomość:
Webowa wersja Visual Studio Code stosuje podobny mechanizm sandboxingu. Przeglądarka izoluje ramki iframe od głównej strony. Utrudnia to jednak działanie skrótów klawiszowych.
Przeglądarka standardowo nie pozwala stronom nasłuchiwać kliknięć klawiszy w ramkach z innego origin – nie chcemy przykładowo, aby strona przechwytywała wprowadzane w ramce dane, a tym bardziej hasła czy numery kart płatniczych.
Aby skróty klawiszowe w VSCode mogły działać także gdy użytkownik kliknie w webview (czyli wejdzie w interakcję z ramką, a nie bezpośrednio stroną), do głównego okna przekazywany jest event keydown. Odpowiada za to ten fragment kodu:
W uproszczeniu możemy powiedzieć, że webview przekazuje ten event do głównego okna VSCode, żeby został on potraktowany tak jak kliknięcie poza obszarem webview.
Teoretycznie skrypt działający wewnątrz webview mógłby symulować działanie użytkownika i wywoływać keydown dla dowolnych klawiszy. W tym celu np. otwierałby widok command palette i uruchamiał niebezpieczne komendy, takie jak instalacja złośliwego rozszerzenia.
W rzeczywistości jednak nie jest to takie proste. Choć złośliwy webview mógłby symulować event keydown, przeglądarka nie przyjmie w taki sposób wpisywanych komend/poleceń. Faktycznie można otworzyć command palette, ale nie ma możliwości wpisania w nim tekstu. Jednak command palette nie jest jedyną opcją.
Visual Studio Code ma zestaw domyślnych skrótów klawiszowych, które reagują bezpośrednio na keydown. Po eksperymentach badacz wybrał akcję “Notifications: Accept Notification Primary Action”. Skrót Ctrl+Shift+A powoduje zatwierdzenie “głównej akcji” z ostatniego powiadomienia.
O jakim powiadomieniu i akcji mowa? Badacz skorzystał z funkcji rekomendowania rozszerzeń przez plik .vscode/extensions.json:
Nie jest to jednak wystarczające, by zainstalować wtyczkę z poziomu webview. VSCode od wersji 1.97 ma system zaufania wydawców – instalacja rozszerzenia od nowego wydawcy pokazuje dodatkowe okno, nawet jeśli klikniemy Install:
Można przejść do przycisku potwierdzenia z pomocą Tab, ale symulowanie jego kliknięcia przy użyciu zdarzenia keydown nie będzie możliwa.
Zamiast tego można użyć innej funkcji VSCode: lokalnych rozszerzeń. W zaufanym workspace (a w ramach github.dev wszystkie workspaces są zaufane), można instalować rozszerzenia bezpośrednio z katalogu .vscode/extensions. Wtyczki instalowane w ten sposób omijają sprawdzenie wydawcy. Przy próbie uruchomienia pojawia się jednak błąd Content Security Policy, bo program oczekuje, że rozszerzenia będą pochodziły z vscode-cdn[.]net.
To jednak uniemożliwia tylko wykonywanie samego kodu wtyczki. Rozszerzenia mogą jeszcze definiować dodatkowe skróty klawiszowe w package.json. Badacz zauważył, że ten plik zostaje obsłużony poprawnie. Wystarczy więc zadeklarować w nim skrót do dowolnej komendy VSCode, np. instalacji rozszerzenia z pominięciem weryfikacji.
Do przeprowadzenia ataku wykorzystującego tę podatność wystarczy przygotować repozytorium z notatnikiem Jupyter i lokalnym rozszerzeniem. Notatnik musi uruchomić JavaScript, co możemy zrobić przez osadzenie odpowiednio spreparowanego obrazka (znacznika HTML) w Markdown:
Listing 6 – sposób na osadzenie kodu JS w Markdown, źródło: blog.ammaraskar.com
Payload stworzony w celu demonstracji ataku wyglądał tak:
// Wait for VSCode to load and pop open the notification. await sleep(10 * 1000);
// ctrl+shift+a, accept the primary notification asking if we want to install // the recommended extension window.dispatchEvent( new KeyboardEvent(“keydown”, {key: “a”, code: “KeyA”, keyCode: 65, ctrlKey: true, shiftKey: true}) ); // Wait a little for the extension to install… await sleep(500);
// ctrl+f1, the custom keybind to install the chosen extension. window.dispatchEvent( new KeyboardEvent(“keydown”, {key: “F1”, code: “F1”, keyCode: 112, ctrlKey: true}) );
Skrypt najpierw czeka chwilę, aby VSCode zdążyło wyświetlić użytkownikowi komunikat o instalacji rekomendowanego rozszerzenia.
Następnie wysyła event keydown (Ctrl+Shift+A), aby zaakceptować powiadomienie. Później czeka, aż rozszerzenie się zainstaluje i symuluje kliknięcie Ctrl+F1, aby uruchomić własny skrót klawiszowy.
Do wykonania tych działań potrzebne jest tylko otwarcie przez użytkownika złośliwego repozytorium w webowej wersji VSCode na github.dev. W efekcie złośliwa wtyczka może uzyskać dostęp do tokenu GitHub ofiary, co badacz przetestował listując jej repozytoria:
Badacz z uwagi na dotychczasowe problemy ze zgłaszaniem podatności do Microsoft, zdecydował się na publiczne ujawnienie luki.
Przy tego rodzaju podatności trudno o rady w zakresie zabezpieczania się. Możemy napisać, że odradzamy otwieranie zewnętrznych repozytoriów w github.dev, ale… ona do tego właśnie służy. Jedyną sensowną strategią będzie więc otwieranie nieznanych/niezaufanych repozytoriów w oknie incognito, aby użyta instancja VSC nie miała dostępu do naszego tokenu GitHub.
Oś czasu:
2 czerwca 2026 – godzinę przed publikacją tekstu badacz informuje o niej kontakt w zespole GitHub Security
2 czerwca 2026 – badacz ujawnia błąd na swoim blogu i w issue trackerze VSCode
3 czerwca 2026 – Microsoft wprowadza tymczasową poprawkę: dodaje potwierdzenie przy otwieraniu notatników w webowym VSCode i blokuje możliwość pomijania weryfikacji wydawcy wtyczki przez komendy
3 czerwca 2026 – Microsoft wdraża bardziej kompleksową poprawkę ograniczającą eventy keydown w webview notatników