VSCode hatasıyla 1 tıkta GitHub tokenı çalma
(blog.ammaraskar.com)- github.dev, github.com'dan aldığı OAuth tokenıyla tarayıcıdaki VSCode'da dosya görüntüleme, PR ve commit işlemleri yapıyor; bu token belirli bir depoyla sınırlı olmadığından kullanıcının erişebildiği tüm depolarda okuma ve yazma yetkisi sağlıyor
- VSCode webview,
vscode-webview://...iframe'iyle yalıtılıyor; ancak klavye kısayolu deneyimi için webview içindekikeydownolaylarınıdid-keydownmesajı olarak ana pencereye iletiyor ve bu da güvenilmeyen scriptlerin kullanıcı tuş girişleri gibi olay gönderebilmesine yol açıyor - Rastgele metin girişi HTML
<input>nedeniyle işe yaramasa da, varsayılanCtrl+Shift+Akısayolu, önerilen uzantı kurulum bildirimi, local workspace extensions ve özel keybinding'lerin birleşimiyle uzantı kurma komutu çalıştırılabiliyor - PoC, bir Jupyter notebook içindeki Markdown hücresinden JavaScript çalıştırarak önerilen uzantı kurulumunu kabul ediyor, yeni bir keybinding ile seçilen uzantıyı kuruyor ve ardından GitHub API tokenı ile özel depo listesini gösteriyor
- Masaüstü VSCode da aynı zafiyetten etkileniyor; ancak saldırganın kullanıcıyı depoyu klonlamaya ve notebook'u açmaya ikna etmesi gerekiyor. github.dev kullanıcıları için savunma olarak site verilerini temizleyip ilk onay iletişim kutusunu yeniden göstermek gerekiyor
Zafiyet özeti
- github.dev, erişilebilen bir GitHub depo URL'sinde
github.comalanınıgithub.devile değiştirince veya menü öğesine tıklayınca tarayıcıda çalışan hafif bir VSCode açıyor - Bu tarayıcı tabanlı VSCode depo dosyalarını görüntüleyebiliyor, özel depoları da açabiliyor ve PR gönderme ile commit oluşturma işlemleri yapabiliyor
- github.com, kullanıcı adına GitHub ile etkileşime girebilen bir OAuth tokenını github.dev'ye POST ediyor ve bu token kullanıcının etkileşim kurduğu belirli depoyla sınırlı değil
- Saldırganlar yalnızca bir bağlantıya tıklatmakla okuma-yazma yetkisine sahip bir GitHub tokenını ele geçirebiliyor; buna özel depolar da dahil
Webview yalıtımı ve tuş iletimi sorunu
- VSCode webviews, JavaScript çalıştırmayı yalıtmak için ana VSCode penceresinden farklı origin'e sahip bir
<iframe>kullanıyor - Jupyter notebook çıktısı
vscode-webview://...origin'li bir<iframe>içinde render ediliyor; ana Electron penceresi isevscode-file://...origin'ini kullanıyor - Bu yalıtım sayesinde notebook HTML gösterse veya JavaScript tabanlı etkileşimli widget'lar kullansa bile, iframe içinden Electron'un Node.js API'lerine ya da VSCode API'lerine erişemiyor
- Markdown önizleme gibi ana pencere ile webview'in birlikte çalışması gereken özellikler, Window.postMessage() API üzerinden mesaj alışverişi yapıyor
- VSCode, webview içindeyken de
Ctrl+Shift+Pgibi kısayollar çalışsın diyedid-keydownolayını ana pencereye iletiyor - Webview içindeki güvenilmeyen scriptler,
keydownolaylarını doğrudan tetikleyerek kullanıcı gerçekten tuşa basmış gibi davranabiliyor
Saldırı zinciri
Ctrl+Shift+Pile komut paleti açılabiliyor; ancak komut paleti HTML<input>kullandığı için rastgele dizge girme yöntemi işe yaramıyor- Yön tuşları ve
Entergibikeydownile işlenen girişler kullanılabiliyor; ayrıca VSCode'un varsayılan kısayol setinden de yararlanılabiliyor Ctrl+Shift+A, “Notifications: Accept Notification Primary Action” için varsayılan keybinding ve son VSCode bildiriminin birincil düğmesine basıyor.vscode/extensions.jsoniçine önerilen uzantılar eklenirse VSCode kurulum bildirimi gösteriyor; ancak VSCode 1.97'deki publisher trust sistemi, yeni bir yayıncıdan gelen uzantı kurulurken ek bir güven iletişim kutusu açıyorTabile düğmeler arasında gezilebilse de, “Trust Publisher & Install” düğmesininEnterişlemi düğmenin kendikeydownolayına bağlı olduğu için yalnızca bu yolla kurulumu tamamlamak zor- local workspace extensions, güvenilen bir workspace içinde
.vscode/extensionsaltında bulunan uzantıların doğrudan kurulmasına izin veriyor; github.dev/web workspace ise her zaman güvenilen durumda - Local workspace extension'ı doğrudan çalıştırmaya kalkınca, extension worker
vscode-cdn.netüzerinden gelen uzantı beklediği için CSP hatası oluşuyor - Bunun yerine local workspace extension'ın
package.jsondosyasına özel bir keybinding eklenebiliyor ve bu keybindingworkbench.extensions.installExtensionkomutunuskipPublisherTrustbağlamıyla çağırabiliyor
PoC'nin işleyişi ve etkisi
- Gerekli kurulum, içinde Jupyter notebook ve local workspace extension bulunan bir depo
- Notebook içindeki Markdown hücresi, resmin
onerrorniteliği üzerinden JavaScript çalıştırabiliyor - Yük, VSCode önerilen uzantı kurulum bildirimi gösterene kadar bekliyor; ardından bildirimin birincil eylemini kabul etmek için
Ctrl+Shift+Aolayı gönderiyor - Sonrasında uzantı kurulup etkinleşene ve özel keybinding yüklenene kadar bekliyor; ardından seçilen uzantının kurulumunu tetiklemek için
Ctrl+F1olayı gönderiyor - PoC ile kurulan uzantı, GitHub API tokenını alıyor,
https://api.github.com/user/reposadresini sorgulayarak erişilebilen özel depoları çıkarıyor ve token ile depo listesini bilgi kutusunda gösteriyor - PoC çalıştıktan sonra github.dev verilerinin temizlenmesi veya PoC uzantısının kaldırılması gerekiyor; kaldırılmazsa tüm github.dev sayfalarında etkisini sürdürüyor
- Aynı zafiyet masaüstü VSCode'da da var; ancak saldırganın kurbanı depoyu clone etmeye ve webview script yükünü içeren notebook'u açmaya ikna etmesi gerekiyor
- Kurbanın açtığı webview'de başka bir XSS de varsa, masaüstünde bu durum fiilen tam uzaktan kod çalıştırmaya kadar gidebilir
Savunma ve hafifletme unsurları
- Geçmişte hiç github.dev kullanmadıysanız, siteye girişte tıklanması gereken bir iletişim kutusu çıkıyor ve bu da saldırı sayfasından çıkmak için bir fırsat yaratıyor
- github.dev'nin çerezlerini ve yerel site verilerini temizlemek, bu ilk iletişim kutusunun yeniden görünmesini sağlayabilir
- Chrome'da URL çubuğundaki simgeye tıklayıp Cookies and site data > Manage on-device site data yoluna giderek ilgili alan adı verileri silinebiliyor
- github.dev iletişim kutusunu daha önce geçtiyseniz ve tarayıcı yerel depolamasını temizlemediyseniz, github.dev'de CSRF tokenı benzeri bir koruma olmadığından internetteki herhangi bir bağlantı saldırıya yönlendirebilir
- VSCode yalnızca iframe yalıtımına güvenmiyor; aynı zamanda sıkı bir Content Security Policy ve DOMPurify kullanıyor
- Uzantı sayfasındaki Markdown önizlemede
script-src 'none'kullanılarak rastgele JavaScript çalıştırma engelleniyor; bu da yalnızca uzantı bağlantısıyla masaüstünde 1 tık RCE gibi daha büyük etkiyi önlüyor
Açıklama arka planı ve zaman çizelgesi
- MSRC, geçmişte VSCode hata bildirimlerini sessizce düzeltip kredi vermedi ve bunları güvenlik etkisi yok diye işaretledi
- Yakın tarihte Starlabs'ın VSCode XSS hata bildirimi de uygun değil ve düşük önem seviyesinde olarak işaretlendi
- VSCode ekibinin UI/UX ile güvenlik arasında denge kurmak için daha fazla zamana ihtiyaç duymuş olması mümkün; ancak güvenlik araştırmacılarının zaman ve emeğinin doğal görülmemesi gerektiği gerekçesiyle tam açıklama tercih edildi
- 2 Haziran 2026'da, yayından bir saat önce GitHub güvenlik tarafındaki mevcut iletişim noktasına açıklamanın yapılacağı bildirildi
- Aynı gün zafiyet açıklandı ve VSCode issue tracker üzerinde de kayda geçirildi
1 yorum
Hacker News görüşleri
İyi bir özetti; büyük resimde asıl üzücü olan, web’e gömülü VSCode editörünün zaten GitHub’a giriş yapmış olması
Derinlemesine savunma olup olmamasından bağımsız olarak, asıl günah bu olduğu için saldırı yüzeyi çok büyüyor. Bu, kötü niyetli bir NPM paketinin bulabilmesi için iş istasyonunda tüm yetkilere sahip bir GitHub API token’ını düz metin olarak bırakmaya benziyor
İdealde tarayıcı IDE’si, yalnızca ilgili depoda pull/push yapabilen geçici depo-başına yetki kapsamı ya da token ile çalışmalı ve github.com web oturumu hiç olmamalı. Tüm GitHub web arayüzü gerekirse github.com’a dönülür, github.dev ise tek depo hizmeti olarak kalır; doğru yaklaşım bu gibi görünüyor
Tabii bu kullanıcı için daha zahmetli olur, uygulaması da zordur ve muhtemelen github.dev araçlarının geneline tarihsel olarak gömülü varsayımlar vardır
github.dev için de bu yaklaşım ciddi biçimde düşünülmeli
[1] https://orca.security/resources/blog/hacking-github-codespac...
Daha kötüsü, geliştiricilerin bile bunu pek umursamıyor gibi görünmesi
keydownişleyicisine yayılmayacak şekilde düzeltilmeliMasaüstünde Electron’un bunu doğrudan yakalayacak şekilde değiştirilmesi ve bu özelliğin kaldırılması daha iyi olur; web’de ise varsayılan olarak devre dışı bırakılması doğru görünüyor
Diğer Git barındırma hizmetlerinde de benzer bir özellik var mı pek bilmiyorum
Açıkçası LLM ajanları da böyle çalışmalı. LLM’in doğrudan push yapmasına izin vermek pervasızca görünüyor
Bu saldırının özellikle zorlayıcı olmasının nedeni, VSCode eklentilerinin editörün kendisiyle aynı güven seviyesinde çalışması ve çoğu geliştiricinin yetkilerini incelemeden onlarca eklenti kurmuş olması
Kötü niyetli ya da ele geçirilmiş bir eklenti GitHub token’ını sessizce dışarı sızdırırsa, ağ izleme olmadan bunu fark etmek zordur; bu da eklentilerin izole profillerde çalıştırılması gerektiğine dayanak oluşturur
En iyi yöntem GitHub’dan çıkıp kendi barındırdığınız iç GitLab/Forgejo ortamına geçmek ve GitHub’ı tamamen engellemektir
Yakın zamanda benzer bir şey yaşadım. GitHub token’ım ve Cloudflare token’ım çalındı
Güvenliği ciddiye alsanız bile yeterince uzun bir zaman içinde eninde sonunda vurulacağınızı düşünüyorum. Yapılabilecek en iyi şey, ayırmak ve hasar kapsamını kontrol altında tutmak
Hiç kimseye, hiçbir şeye güvenmeyin, OrbStack kullanın ve token’ların bir gün sızacağını varsayarak her zaman buna göre çalışın
İş akışım tamamen bozuldu ama neyse ki token’ları alan taraf daha çok spam botuna benziyordu. Bir sürü sahte spam sayfası oluşturup kripto para madenciliği yapmaya çalıştılar
Geriye en çok kalan duygu, ihlal edilmiş olma hissi. Herkes dikkatli olsun
MSRC’ye bir VSCode hatası bildirdiğinizde sessizce düzeltilip geçilmesinin korkunç bir deneyim olduğuna dair kısım tam bir MSRC klasiği. Araştırmacıların zaten ücretsiz bildirim yaptığını fark etmişler; bu yüzden değiştirmek için bir neden görmüyor gibiler
Bu vakanın ayrıntılarını bilmiyorum ama geçmişte Bountysource ve HackerOne üzerinden bug bounty programı yürüttüm. Bazen güvenlik ekibi daha değerlendirmeyi tamamlamadan rapor geliştirici ekibe önce sızabiliyor
O noktada geliştirici bunu sessizce düzeltebilir. Bunun nedeni bazen, güvenlik açığıyla ilişkilendirilmesinin kendilerini kötü göstereceği ya da terfi fırsatlarını etkileyebileceği yönündeki, ister makul olsun ister olmasın, kaygılarıdır. Sonuç olarak güvenlik ekibi yeniden üretmeye çalıştığında açık artık ortadan kalkmış olur
MSRC’nin gördüğü şey, verilen yeniden üretim adımlarının artık çalışmamasıdır. İç hata geçmişini ya da birinin zaten yamaladığını göremez. Bu yüzden başlangıçtaki bulgu geçerli olsa bile rapor geçersiz sayılarak kapatılır
Bu exploit için harcanan zamanı fiilen bağışlayıp VS Code’un güvenlik müdahalesini iyileştirmesi gerektiğini göstermiş olmanız için teşekkürler. Vazgeçebilirdiniz ama hâlâ yardımcı oluyorsunuz
Neden daha fazla geliştiricinin Neovim denemediğini pek anlayamıyorum.
Bu biraz zevk meselesi olabilir ama kurulu olanla çalışan şeyi kavrayabildiğiniz küçük bir yapı hoşuma gidiyor. VSCode, tarayıcı IDE’si, eklentiler, senkronizasyon, token’lar ve rastgele plugin’ler birbirine karışınca neyin neye eriştiğini anlamak zorlaşıyor
Bu, Microsoft’un resmi Python eklentisinin bir özelliğiydi ve diğer açılardan da eldeki tek düzgün eklenti sayılırdı, ama benim projemin kullandığından farklı bir kütüphane sürümü için tip tanımlarını kuruyordu. Doğrulanmamış üçüncü taraf kodu gayet rahat biçimde çalıştırıyormuş gibi görünmesi beni ciddi biçimde tedirgin etti ve bunu ayarlardan kapatmak da mümkün görünmüyordu.
“O günden sonra bir daha arkama bakmadım” demek isterdim ama dürüst olmak gerekirse son 1-2 yılda Neovim neredeyse her yükseltmede ayarlarımı düzenli olarak bozmaya başladı. Bir gün bunun olabileceğine dair işaretler vardı. Teknik olarak 10 yıl geçmiş olsa da nvim hâlâ ilk kararlı sürümünü çıkarmadı; bu yüzden kararsızlık konusunda çok da suçlayamam ama akılda tutulması gereken bir nokta.
Düz Vim’e geri dönmeyi düşünüyorum. Bir sürü rahatlık özelliğini kaybederim ama en azından çalışırken bozulan şeyleri debug etmek zorunda kalmayı azaltmak isterim
Bir sürü plugin kurmanıza ya da SpaceVim gibi bir şey kullanmanıza gerek kalmıyor. Bir bakarsanız hoşunuza gidebilir
nvim’e alışmak zaman alıyor ama alışınca daha hızlı. Yine de birçok insanın konfor alanında kalmasının nedeni anlaşılır
Tam açıklama iyi bir şey. MSRC’den memnun olmayan çok fazla insan var ve Nightmare Eclipse olayında olduğu gibi bu durum artık taşmaya başlıyor.
Bu tür açıklamalar birikirse belki MSRC kendine dönüp bakar ve sorunun kendileri olduğunu fark eder. Pek olası görünmüyor ama umut edilebilir
Yine de en azından denemesi ya da herkese açık etmeden birkaç gün önce haber vermesi gerekirdi diye düşünüyorum. Sonucun ne olacağını bilemezsiniz
Yazı çok iyiydi ama son kısımda biraz kafam karıştı. Doğru anladıysam emin olmak istiyorum.
Yazar, yeni yayıncı güven sistemi yüzünden sadece kısayol hilesiyle kötü amaçlı eklentiyi doğrudan kurmanın mümkün olmadığını söyledi; yayıncı kontrolü olmayan yerel workspace eklentileriyle bunun aşılabildiğini ama CSP’nin bunu engellediğini de ekledi.
Çözüm, “yayıncı doğrulaması olmadan eklenti kur” kısayolunu bağlayan bir yerel workspace eklentisi kurmak gibi görünüyor.
Yani 1) bunun iki eklenti gerektiği anlamına mı geldiğini merak ediyorum: ilki sadece tuş ataması yapan yerel eklenti, ikincisi ise gerçek kötü amaçlı eklenti ve CSP yüzünden yerel olmasına da gerek olmayan, hatta fiilen yerel olamayacak olan mı; 2) CSP’nin yalnızca yerel eklentinin JS’ini engelleyip
package.jsondosyasını ya da kısayol ekleme yeteneğini engellemediği doğru mu?En doğrudan yürütme için
my-extension/extension.jskoymayı deneyebilirsiniz ama CSP bunu engeller. Ancakscript-srcCSP yalnızca script’leri engellediğindenpackage.jsondosyasını getirmeye izin verilir. Bu yüzden bundan yararlanılarak tuş ataması katkısı yapılıyorMSRC durumu gerçekten inanılmaz.
Daha iyi kaynaklar da vardır ama The Primeagen’in şu videosunun iyi bir giriş olduğunu düşünüyorum.
https://www.youtube.com/watch?v=9kxx5xp5nTQ
“Bu davranışa izin vermenin tek yolu, farklı origin’lere sahip iki web sayfasının
Window.postMessage()API’si üzerinden iş birliği yapmasıdır” kısmına küçük bir itirazım var.iframe veya üst pencere
location.anchorözelliğini değiştirerek de iletişim kurabilir