Selamlar,
Storybook ekibi CVE-2026-114125 (GHSA-f2ph-cmg5-wxc8, CVSS 4.0 9.4) ile ilgili danışmayı yayımladı: çalışan bir storybook dev sunucusunun preview iframe'i herhangi bir web sitesine gömülebiliyor ve her origin'den postMessage olayı kabul ediyordu. Kötü niyetli bir site, kullanıcı etkileşimiyle dev sunucusunun story dosyalarını değiştirmesini sağlayabiliyor; değişen dosya yerel bir runtime tarafından çalıştırılırsa geliştiricinin yetkisiyle kod çalışabiliyordu. Bu konu, olayı özetleyip kendi kodunuzda postMessage'ı nasıl güvenli kullanacağınızı anlatıyor.
Konuda anlatılacaklar
- Storybook açığının özeti ve yamalı sürümler
- postMessage nasıl çalışır?
- Hatalı ve doğru alıcı kodu
- Gönderen tarafta hedef origin
- Kontrol listesi
Storybook özeti
- Etkilenen: Storybook 8, 9, 10 ve 11 alpha dev sunucuları (@storybook/addon-mcp ve @storybook/addon-vitest dahil).
- Yamalı: 8.6.19, 9.1.21, 10.6.2, 11.0.0-alpha.6. Yükseltmeden storybook dev çalıştırmayın.
- Etkilenmeyen: Build edilmiş statik Storybook'lar ve tarayıcıda hiç açılmayan dev sunucuları.
- Yeni varsayılanlar: farklı host adına iframe gömme kapalı; preview ve manager yalnızca kendi origin'i ve localhost servisleriyle mesajlaşıyor. Eski davranış için security.insecureRemoteIframeEmbed ve security.insecureIframeMessaging bayrakları var ama ekip bunları önermiyor.
- Danışmaya göre Chrome ve Firefox'un yeni sürümleri bir sitenin localhost'a bağlanmadan önce izin isteyebiliyor; güvenmediğiniz sitelere bu izni vermeyin.
postMessage nasıl çalışır?
window.postMessage farklı origin'deki pencereler (ana sayfa ile iframe, açılan popup) arasında güvenli mesajlaşma için tasarlandı. Ama "güvenli" olması iki tarafın da kontrol yapmasına bağlı. MDN açıkça uyarıyor: mesaj alan taraf event.origin'i doğrulamazsa, herhangi bir site mesaj gönderebilir.
Hatalı alıcı
// YANLIS: her origin'den gelen mesaja guveniyor
window.addEventListener("message", (e) => {
if (e.data.type === "updateFile") {
saveFile(e.data.path, e.data.content); // tehlikeli islem
}
});Doğru alıcı
const ALLOWED = new Set(["https://app.ornek.com", "http://localhost:6006"]);
window.addEventListener("message", (e) => {
// 1) Origin'i tam eslesme ile dogrula (includes/startsWith kullanma)
if (!ALLOWED.has(e.origin)) return;
// 2) Kaynagin beklenen pencere oldugunu kontrol et
if (e.source !== expectedFrame.contentWindow) return;
// 3) Veriyi sema ile dogrula
const d = e.data;
if (typeof d !== "object" || d.type !== "setArgs") return;
// 4) Tehlikeli islemleri mesajla tetikleme; yalnizca dar kapsamli UI durumu
applyArgs(sanitize(d.args));
});Gönderen taraf
// YANLIS: "*" hedefi, mesaji kim yuklenmisse ona verir
frame.contentWindow.postMessage(secretToken, "*");
// DOGRU: hedef origin'i acikca yaz
frame.contentWindow.postMessage({type:"init"}, "https://widget.ornek.com");Kontrol listesi
- Her message dinleyicisinde izin listesiyle tam origin eşleşmesi.
- Mesajla dosya yazma, komut çalıştırma, kimlik bilgisi aktarma gibi yan etkili işlem yapmayın.
- Gömülmesini istemediğiniz sayfalarda Content-Security-Policy: frame-ancestors 'self' kullanın.
- Geliştirme sunucularını (Storybook, Vite, Jupyter) yalnızca localhost'a bağlayın ve güncel tutun.
- Kod incelemesinde "addEventListener('message'" araması yapın.
grep -rn "addEventListener(\s*['\"]message" src/ | head
grep -rn "postMessage(.*['\"]\*['\"]" src/ | headKendi projelerinizde postMessage dinleyicilerini en son ne zaman denetlediniz? Bulduğunuz hatalı kalıpları paylaşın.
Yasal uyarı
Bu yazı bilgilendirme ve savunma amaçlıdır. Anlatılan kontrolleri yalnızca kendi sistemlerinizde veya yazılı izinle yapın. İzinsiz erişim, tarama ve sömürü girişimleri TCK 243-245 kapsamında suçtur. TurkTeam white-hat bir topluluktur; çalıntı veri, hesap, combo/log paylaşımı ve hack hizmeti talepleri forum kurallarına aykırıdır.
Kaynaklar
- https://github.com/storybookjs/storybook...-cmg5-wxc8
- https://www.cve.org/CVERecord?id=CVE-2026-114125
- https://developer.mozilla.org/en-US/docs...ostMessage
- https://cheatsheetseries.owasp.org/cheat...Sheet.html
