Series · 3 partsBrowser-to-Native Trust BoundariesPart 2 · You are here
  1. 1Extension Sandbox'taydı. Native Host Değildi.
  2. 2Sayfanın İzni Yoktu. Extension'ın Vardı.You are here
  3. 3Paket İmzalıydı. Güncelleme Yine de Bir Güvenlik Kararıydı.

60 saniyede güven sınırı

Bir web sayfasının extension yetkisini ödünç alması için extension API’lerine doğrudan erişmesi gerekmez. Nihai alıcının erişilebilirliği authorization sanacağı bir mesaj yolu yeterlidir.

Yaygın zincir zararsız görünür:

web sayfası
  → window.postMessage veya ortak DOM
  → isolated content script
  → runtime.sendMessage
  → extension service worker
  → yetkili browser API'si veya cross-origin request

Chrome, content script’leri sayfanın JavaScript ortamından izole olarak tanımlar. Bu özellik değişkenleri ve execution state’i korur; DOM’dan, MessageEvent.data içinden veya sayfa kontrollü bir attribute’tan okunan veriyi güvenilir yapmaz. Chrome’un mesajlaşma güvenliği rehberi nettir: content script’ler service worker’dan daha az güvenilirdir, mesajları saldırgan tarafından hazırlanmış olabilir ve onların tetikleyebildiği yetkili işlemler dar tutulmalıdır.

İkinci ve farklı bir rota da vardır. Bir extension externally_connectable tanımlayarak eşleşen web sayfalarının doğrudan runtime.sendMessage() veya runtime.connect() çağırmasına izin verebilir. Bu çağrılar onMessageExternal ya da onConnectExternal listener’ına ulaşır. Manifest eşleşmesi bir giriş kuralıdır; operasyon seviyesinde authorization değildir.

Dolayısıyla araştırma sorusu şudur:

Sayfa kontrollü bir principal, service worker’ın sayfanın tek başına kullanamayacağı bir capability’yi yeni ve spesifik bir authorization kararı olmadan çalıştırmasını sağlayabiliyor mu?

Bu write-up, hipotezi sentetik bir lab ortamında kanıtlamak veya reddetmek için kontrollü bir yöntem kurar. Production target, gerçek hesap verisi veya yıkıcı etki gerektirmez.

Üç principal, iki mesaj yolu, tek deputy

SAYFA → EXTENSION YETKİ HARİTASI MESAJIN ULAŞMASI, TÜM EXTENSION CAPABILITY'LERİNİN DEVREDİLMESİ DEĞİLDİR WEB SAYFASIorigin · frame · DOMsaldırgan kontrollü veri CONTENT SCRIPTisolated worldRELAY / ÇEVİRMEN SERVICE WORKERsender · schema · statePOLİTİKA KARARI CAPABILITYtabs · fetchstorage · native DOĞRUDAN: externally_connectable → onMessageExternal Browser'ın gördüğü contextsender.url · sender.origintab · frameId · documentId Request capabilityoperation · object IDnonce · expiry · gesture Etki sınırıyalnızca izinli sonuçCALLER-SUPPLIED AUTHORITY YOK DEPUTY GEÇERLİ BİR CHANNEL GÖRDÜĞÜ HALDE BU CALLER'IN BU ETKİYİ NEDEN YAPABİLDİĞİNİ AÇIKLAYAMIYORSA CONFUSED'DIR.
Content-script relay ile doğrudan external-message rotası farklı browser metadata'ları sunar. İkisini ayrı test edin. Her ikisinde de service worker talep edilen capability'yi yetkilendirmelidir.

Sayfa, content script ve service worker tek bir ürün akışına ait olsa bile ayrı principal’lardır. Yetkileri farklıdır:

PrincipalBrowser’ın uyguladığı özelliklerSaldırganın etkileyebildiği özelliklerTipik yetki
Web sayfasıOrigin, frame ve document lifecyclePage JavaScript, DOM, attribute, event ve uygulama state’iSame-origin web capability’leri
Isolated content scriptExtension kimliği ve izole JavaScript global’iSayfadan veya page messaging channel’dan alınan hemen her değerSınırlı extension API ve runtime message
Extension service workerExtension origin’i, paket kodu ve yetkili API erişimiMessage body; bazen eski veya eksik workflow state’iHost permission, tabs, storage ve downloads

Service worker bir deputy’dir: kullanıcıya yönelik bir özellik adına yetki taşır. Daha düşük güven seviyesindeki principal operasyonu veya kaynağı seçerken deputy permission sağlıyorsa confused deputy haline gelir.

Platform kontrolleri gerçekte neyi garanti eder?

Security review sırasında platform kontrollerine çoğu zaman sağlayabileceklerinden daha geniş anlam yüklenir.

KontrolNeyi kanıtlarNeyi kanıtlamaz
Content-script isolated worldPage script content script’in JavaScript global’ini doğrudan okuyamazOrtak DOM veya explicit message üzerinden alınan veri güvenilirdir
content_scripts.matchesScript’in hangi sayfalara inject edilebileceğiniO origin’deki her path, frame ve tenant tüm özellikleri kullanabilir
all_frames: falseDeclarative injection varsayılan olarak top frame’e yapılırTop-frame mesajı halen onaylı olan document’ı tanımlar
externally_connectable.matchesHangi web page URL pattern’larının external channel açabileceğiniCaller açık olan her operasyonu çağırabilir
runtime.onMessageMesaj internal extension messaging rotasından geldiPage-derived payload veya talep edilen object yetkilidir
runtime.onMessageExternalCaller external extension messaging rotasını kullandıSender origin tek başına yeterli authorization’dır
MessageSenderListener’ın kullanabileceği browser-observed sender context’iPayload içindeki aynı alanlar doğrudur veya istenen etki güvenlidir
Host permissionExtension context uzak bir origin’e erişebilirContent script worker’a istediği URL’yi fetch ettirebilir
Kullanıcı kurulumuKullanıcı extension paketini ve permission prompt’u kabul ettiGelecekteki her page action yeni bir kullanıcı kararıdır

Chrome’un externally_connectable dokümantasyonu kritik bir scope farkını açıklar: matches ayarı doğrudan bağlanan web sayfalarını kontrol eder ve content script’leri etkilemez. Bu nedenle geniş bir content-script match ile birleşen window.postMessage relay, externally_connectable olmasa bile dışarıdan erişilebilen ayrı bir yüzeydir.

Zafiyet kalıbı: authority injection

Tehlikeli message schema genellikle intent yerine authority taşır:

{
  "action": "fetch",
  "url": "https://internal-api.example/admin/export",
  "method": "POST",
  "headers": { "X-Workspace": "another-tenant" },
  "body": "..."
}

Caller URL, method, header, tenant ve body’yi seçer. Service worker ise host permission, extension cookie’leri veya authenticated network position sağlar. Handler yalnızca action === "fetch" kontrolü yapsa bile destination ya da object’i yetkilendirmiş olmaz.

Capability odaklı schema bu sahipliği tersine çevirir:

{
  "version": 1,
  "operation": "read-current-project-summary",
  "projectId": "project-17",
  "requestId": "7de0d4c1-...",
  "approvalId": "gesture-8b2f"
}

Extension sabit HTTPS endpoint’i, sabit method’u, izinli response alanlarını, mevcut tenant’ı ve seçili project’i güvenilir state’ten çözer. Caller bir network primitive değil, sınırlandırılmış identifier sağlar.

Tekrarlayan confused-deputy varyantları şunlardır:

VaryantKaybedilen sınırGözlenebilir sonuç
Arbitrary cross-origin fetchSayfa URL’yi seçer; worker host permission sağlarSayfanın erişemediği kaynağı okumak veya değiştirmek
Tab authority borrowingSayfa tab ID veya navigation target seçer; worker tabs sağlarCross-tab disclosure, capture, script injection veya navigation
Storage oracleSayfa key veya namespace seçer; worker extension storage sağlarExtension state disclosure veya corruption
Download deputySayfa URL, filename veya open davranışı seçer; worker downloads sağlarİstenmeyen dosya ya da yanıltıcı yerel artifact
External-message overreachİzinli origin dispatcher içindeki her action’ı seçebilirOnaylı entegrasyon ilgisiz capability’leri devralır
Port lifecycle confusionLong-lived port document/account değişiminden sonra trusted kalırEski authorization yeni page state’e uygulanır
Response overexposureWorker raw API output’u daha az güvenilen content script’e döndürürSecret’lar page-reachable context’e sızar

Zafiyet yalnızca “sayfa mesaj gönderebiliyor” değildir. Sayfanın tek başına yapabildiğiyle deputy’ye yaptırabildiği arasındaki kanıtlanmış farktır.

İki ingress rotası birleştirilmemeli

Internal listener ve external listener farklı sender toplulukları alır. Bunları alias haline getirmek browser’ın sağladığı değerli context’i yok eder.

// Tehlikeli: iki sender topluluğu aynı permissive dispatcher'a ulaşır.
const dispatch = (request, sender) => perform(request.action, request.args);

chrome.runtime.onMessage.addListener(dispatch);
chrome.runtime.onMessageExternal.addListener(dispatch);

Bir content script’ten gelen internal mesaj için service worker browser tarafından sağlanan sender.id, sender.url, sender.origin, sender.tab, sender.frameId ve mevcut olduğunda sender.documentId alanlarını değerlendirebilir. External web-page mesajında sender.url veya sender.origin bağlanan sayfayı tanımlar; fakat sayfa ile listener arasında content script yoktur. Başka bir extension için sender.id merkezi önemdedir. Politikanın ihtiyaç duyduğu alan eksikse sistem fail-closed davranmalıdır.

Message body içine kopyalanmış origin, tab ID, frame ID, extension ID veya document ID kabul etmeyin. Bunlar caller’ın iddiasıdır. Politika browser’ın out-of-band sağladığı sender nesnesini kullanmalı; URL’leri suffix ya da substring ile değil URL parser ile normalize etmelidir.

Kontrollü sentetik lab

Lab’ı zararsız etkiler etrafında kurun:

  • tek service worker ve tek content script içeren unpacked Manifest V3 extension;
  • biri izinli, biri negative-control olan iki loopback veya rezerv test origin’i;
  • sabit namespace kullanan window.postMessage page bridge;
  • yalnızca izinli test origin’i için ayrı externally_connectable kaydı;
  • project-17 ve project-18 içeren sahte project catalog;
  • onaylı project için memory içindeki counter’ı artıran tek privileged effect;
  • sender context, karar ve counter değişimini kaydeden bağımsız event ledger.

Gerçek cookie, browser history, download, credential, remote administration interface veya production origin kullanmayın. Bir request’in sınırı geçtiğini kanıtlamak için counter yeterlidir.

Kasıtlı olarak güvensiz relay küçüktür:

// content-script.js — yalnızca kasıtlı güvensiz lab kalıbı
window.addEventListener("message", (event) => {
  if (event.data?.namespace !== "lab-extension") return;
  chrome.runtime.sendMessage(event.data.payload);
});

Bu kod event.source, mevcut page origin, message shape, operation, size veya document lifecycle kontrolü yapmaz. Daha önemlisi, kusursuz bir event.source === window kontrolü bile yalnızca hangi window’un event yayınladığını gösterir; sayfayı güvenilir yapmaz. MDN, cross-document messaging için hem origin hem gerekirse source doğrulamasını önerir. Ancak bunlar admission fact’tir; service worker yine de operation authorization yapmalıdır.

Web sayfası, isolated content script, extension service worker ve yetkili browser API'lerini her sınırda message evidence ile gösteren mimari kesit.
Boundary plate / 02 Isolated world JavaScript ortamlarını ayırır; güveni değil. Privileged context çalışmadan önce browser-observed sender korunmalı ve her request named capability'ye indirgenmelidir.

Mesaj göndermeden önce inventory

Handler ile etkileşim kurmadan önce kod ve policy haritasını çıkarın.

Manifest ve injection inventory

AlanToplanacak evidence
Content-script matchesExact scheme, host, path, exclusion ve dynamic registration’lar
Frame reachall_frames, match_about_blank, match_origin_as_fallback
Execution worldISOLATED veya MAIN; ortak DOM/event channel’ın gerekçesi
External callersexternally_connectable.matches, ID’ler ve wildcard kullanımı
Privileged permissionspermissions, host_permissions, optional grant ve activeTab
Web-accessible resourcesDışarı açılan path’ler ve bunları yükleyebilen siteler
LifecycleService-worker restart, port reconnect ve state recovery davranışı

Message ve effect inventory

AlanSorular
Listener populationInternal message, external page, external extension, port veya one-shot?
Sender policyHangi browser-observed alanlar zorunlu, URL nasıl normalize ediliyor?
SchemaUnknown key, yanlış type, nesting ve oversized değer reddediliyor mu?
DispatcherCaller URL, method, script, tab, path, key veya command seçebiliyor mu?
Trusted stateTenant, selected object, user gesture ve approval nereden geliyor?
ResponseContent script veya external page’e hangi alanlar dönüyor?
Effect observerPrivileged action’ın gerçekleştiğini hangi bağımsız sinyal kanıtlıyor?
Denial observerReddedilen request’in hiç etki üretmediğini ne kanıtlıyor?

Static code search; onMessage, onConnect, onMessageExternal, onConnectExternal, sendMessage, connect, postMessage, custom DOM event ve privileged API çağrılarını bulmalıdır. Her listener’ı son etkiye kadar izleyin. Generic dispatcher’a forward eden sanitized handler, review’un son noktası değildir.

Sender context’i koruyun ve doğrulayın

Güvenli internal listener channel admission, schema validation ve authorization’ı ayırır:

const ALLOWED_ORIGIN = "https://app.lab.invalid";
const PROJECTS = new Set(["project-17"]);

chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  const senderUrl = sender.url ? new URL(sender.url) : null;
  const admitted =
    sender.id === chrome.runtime.id &&
    senderUrl?.origin === ALLOWED_ORIGIN &&
    sender.frameId === 0 &&
    typeof sender.documentId === "string";

  if (!admitted) return false;

  const valid =
    message &&
    message.version === 1 &&
    message.operation === "read-current-project-summary" &&
    typeof message.projectId === "string" &&
    Object.keys(message).every((key) =>
      ["version", "operation", "projectId", "requestId", "approvalId"].includes(
        key,
      ),
    );

  if (!valid || !PROJECTS.has(message.projectId)) {
    sendResponse({ ok: false, code: "DENIED" });
    return false;
  }

  void handleApprovedSummary(message, sender).then(sendResponse);
  return true;
});

Bu bir kalıptır; doğrudan kullanılacak universal policy değildir. Bazı browser veya context’ler her sender alanını sağlamaz ve browser compatibility test edilmelidir. Policy, eksik hangi değerin denial üreteceğini belirtmelidir. Ayrıca approvalId, well-formed herhangi bir string kabul etmek yerine trusted extension state’e bağlanmalıdır.

External rota kendi listener’ına ve daha küçük operation set’ine ihtiyaç duyar:

chrome.runtime.onMessageExternal.addListener(
  (message, sender, sendResponse) => {
    const origin = sender.url ? new URL(sender.url).origin : null;
    if (origin !== "https://partner.lab.invalid") return false;

    if (
      message?.version !== 1 ||
      message?.operation !== "extension-health" ||
      Object.keys(message).some(
        (key) => !["version", "operation", "requestId"].includes(key),
      )
    ) {
      sendResponse({ ok: false, code: "DENIED" });
      return false;
    }

    sendResponse({ ok: true, state: "ready" });
    return false;
  },
);

Partner origin generic dispatcher değil, status capability alır. Origin allowlist kasıtlı olarak küçük bir protocol sağladığında daha güçlüdür.

Capability minimization string filtering’den üstündür

.., javascript: veya seçili domain’leri blocklamak caller’ı security primitive üzerinde söz sahibi bırakır. Primitive’leri named ve dar capability’lerle değiştirin.

Caller’dan almayınYerine bunu kabul edinTrusted code içinde çözün
Tam URL ve HTTP methodOperation ve bounded object IDSabit HTTPS origin, path, method ve response alanları
Tab ID ve script sourceCurrent-workflow actionActive approved tab ve paket içindeki script dosyası
Storage key veya namespaceTyped preference nameSabit key map ve value schema
Filename ve download URLReport IDServer-side report URL ve güvenli üretilmiş filename
Raw HTML veya JavaScriptStructured display fieldsExtension context’te text-only DOM construction
Arbitrary dispatcher actionVersioned operation unionExplicit handler ve default-deny

Return value aynı kurala tabidir. Chrome, content script’e gönderilen verinin sayfaya sızabileceğini belirtir. Service worker yalnızca render için gereken minimum alanları döndürmeli; raw cross-origin response, authentication header, internal identifier veya geniş extension storage asla dönmemelidir.

Authorization’ı lifecycle’a bağlayın

Message policy connection anında doğru, effect anında yanlış olabilir. Single-page application’lar top-level document’ı değiştirmeden state’i değiştirir. Frame’ler navigate olur. Service worker durur ve yeniden başlar. Long-lived port disconnect ve reconnect olur. Queued request beklerken kullanıcı account veya workspace değiştirir.

High-impact request şunları bağlamalıdır:

  • MessageSender içindeki tab.id, frameId ve desteklendiğinde documentId;
  • normalize edilmiş page origin;
  • extension tarafından görülen account veya tenant;
  • extension tarafından çözülen selected object;
  • gerçek user gesture veya explicit approval state;
  • single-use nonce ve kısa expiry;
  • tam operation ve response class.

Bağı effect’ten hemen önce yeniden doğrulayın. “Bu port trusted” şeklinde koşulsuz boolean tutmayın. Hangi document için, ne zamana kadar ve hangi işlemi yapmak üzere trusted olduğunu kaydedin. Navigation, account transition, worker restart, port disconnect veya permission change durumunda state’i geçersiz kılın.

Reproduction methodology: capability delta’yı kanıtlayın

Güvenli sonuç capability farkını canary’lerle gösterir:

  1. Baseline kurun. Test sayfasından inert counter operation’ı doğrudan deneyin. Sayfanın privileged counter’a kendi başına ulaşamadığını kaydedin.
  2. Ingress’i kaydedin. Content-script relay üzerinden tek well-formed request gönderin. Caller’ın kopyaladığı alanları değil, service worker’daki browser-observed sender alanlarını yakalayın.
  3. Effect’i bağımsız gözlemleyin. Üretilen request ID’yi counter ledger ile correlate edin. Success response supporting evidence’dır; effect proof değildir.
  4. Tek authorization boyutunu değiştirin. Negative-control origin, child frame, stale document, farklı project ID veya external route ile tekrarlayın.
  5. Vulnerable ve fixed build’i karşılaştırın. Approved request çalışmaya devam etmeli; her unauthorized varyant decision record üretmeli fakat counter’ı değiştirmemelidir.
  6. Lifecycle sınırlarını çalıştırın. Request’i replay etmeden önce navigate edin, account değiştirin, port’u yeniden bağlayın ve worker’ı restart edin.
  7. Lab’ı kaldırın. Extension’ı unload edin, synthetic state’i temizleyin ve iki ingress rotasının da artık erişilemediğini doğrulayın.

Her testte tek değişken değiştirin. Origin, frame, schema ve object aynı anda değişirse denial’ın hangi gate tarafından üretildiği anlaşılamaz.

Capability delta’yı gerçek cross-origin account data okuyarak, başka tab yakalayarak, gerçek download oluşturarak veya native host çağırarak göstermeyin. Canary effect authorization hatasını zararı büyütmeden kanıtlar.

Karar pipeline’ı

EXTENSION CAPABILITY KARAR PIPELINE'I REQUEST TEK BİR ETKİ KAZANIR; WORKER'IN AMBIENT AUTHORITY'SİNİ DEVRALMAZ 1 · ROUTEinternalexternal · port 2 · SENDERorigin · framedocument · id 3 · SCHEMAversion · typesize · keys 4 · WORKFLOWtenant · gesturenonce · expiry 5 · CAPABILITYfixed operationbounded result DENIAL RECORDgate · reason · request IDsıfır privileged effect EFFECT OBSERVERexpected canary değiştiadjacent canary değişmedi EVIDENCE BUNDLEsender · decision · effectnegative control · cleanup FAIL-CLOSED KOŞULLARI: YANLIŞ ROUTE · UNKNOWN ORIGIN · STALE DOCUMENT · EXTRA KEY · MISSING GESTURE · REPLAY · EFFECT MISMATCH
Authorization bir sender-origin if-statement değil, pipeline'dır. Başarısız her gate nedeni kaydeder ve privileged effect üretmez.

Evidence matrix

Mesajın alınmasını privileged effect’ten; privileged effect’i de unauthorized impact’ten ayırın.

İddiaPositive evidenceNegative controlGüçlü sonuç
Sayfa content-script bridge’e ulaşırBeklenen top document içinde namespaced event gözlenirForeign namespace ve child-frame event yok sayılırTest edilen page-to-content ingress karakterize edildi
Content script service worker’a ulaşırBrowser sender context ve request ID kaydedilirExtension page veya stale document mesajı ayrıştırılırListener test edilen sender class’ları tanır
External page rotası scoped’durİzinli lab origin yalnızca status operation’a ulaşırUnlisted origin ve ilgisiz operation reddedilirDirect external ingress origin ve capability ile sınırlıdır
Confused-deputy effect vardırPage request normalde erişilemeyen canary değişimiyle correlate olurPage-only baseline canary’yi değiştiremezExtension authority gösterilen capability delta’yı oluşturdu
Object authorization çalışırApproved project counter bir kez değişirUnknown ve adjacent project ID değişmeden kalırCaller test edilen izin dışı object’i seçemez
Lifecycle binding çalışırCurrent document ve fresh approval başarılıdırNavigation, expired approval ve replay etki üretmezTest authority kaydedilen lifecycle dışına taşmaz
Response minimize edilmiştirCaller yalnızca dokümante summary alanlarını alırSecret/internal alan success ve error path’te yokturTest response worker’ın daha geniş verisini açmaz
Cleanup tamamdırExtension ve synthetic state kaldırılırCleanup sonrası iki message rotası da başarısızdırLab test edilen bridge’i artık expose etmez

Rejected response, hiçbir effect oluşmadığını kanıtlamaz. Independent ledger hem target hem adjacent canary’nin değişmediğini göstermelidir.

Test matrix

BoyutVaryantlarBeklenen güvenli sonuç
Ingress routeContent relay, external page, external extension, extension UIHer population için ayrı listener ve operation policy
OriginExact allowed, sibling subdomain, HTTP, opaque, unrelatedYalnızca policy’nin istediği normalize exact origin ilerler
Source/frameTop window, child frame, popup, replaced documentYalnızca amaçlanan current frame ve document ilerler
SchemaMissing, extra, wrong type, array, deep nesting, oversizedCapability resolution öncesinde reject
OperationAllowed, unknown, deprecated, case variationExplicit versioned allowlist ve default-deny
ObjectCurrent, adjacent, unknown, cross-tenant IDTrusted state yalnızca approved object’i çözer
ApprovalFresh gesture, absent, expired, mismatched operationHigh-impact operation matching fresh approval ister
Replay/lifecycleDuplicate nonce, navigation, worker restart, account changeAuthority kayıtlı binding dışına taşmaz
ResponseSuccess, denial, timeout, upstream errorPrivileged raw data içermeyen minimum stable schema
CleanupExtension’ı unload et ve registration’ları temizleDirect ve relayed route artık kullanılamaz

Hardening sırası

  1. Gerekmeyen rotaları kaldırın. Doğrudan page integration gerekmiyorsa externally_connectable eklemeyin. Alışkanlıkla DOM veya postMessage relay kurmayın.
  2. Injection’ı daraltın. Exact HTTPS match pattern, exclusion, top-frame-only execution ve workflow uygunsa programmatic ya da activeTab injection kullanın.
  3. Caller population’larını ayırın. Internal content message, extension page, external page ve external extension ayrı listener veya explicit route discriminator ister.
  4. Browser-observed sender fact kullanın. Exact origin normalize edip karşılaştırın. Policy’nin dayandığı frame/document alanlarını zorunlu kılın. Payload içindeki kopyalara güvenmeyin.
  5. Malformed protocol’ü reddedin. Schema’yı versionlayın, serialized size ve collection count sınırı koyun, unknown key reddedin ve discriminated operation allowlist kullanın.
  6. Authority’yi intent ile değiştirin. Caller named operation ve bounded identifier seçsin; trusted code URL, method, tab, storage key, filename ve packaged script seçsin.
  7. Sensitive effect’i fresh state’e bağlayın. Tenant, object, gesture, nonce, expiry, document ve operation tek authorization record içinde birleşsin.
  8. Response’u minimize edin. Content script’i sayfaya olası disclosure path olarak kabul edin.
  9. Transition anında geçersiz kılın. Navigation, account change, worker restart, disconnect ve permission change önceki authorization’ı sonlandırsın.
  10. Denial’ı effect olarak test edin. Her rejected request için privileged side effect’in sıfır olduğunu bağımsız doğrulayın.

Detection ve forensic sinyaller

Faydalı telemetry şunları içerir:

  • extension ID, version, install source ve permission değişiklikleri;
  • content-script registration, match scope, frame policy ve execution world;
  • internal/external listener, port name ve request ID;
  • browser-observed sender origin, tab, frame ve document identifier;
  • secret payload yerine schema version, operation name ve object identifier;
  • authorization gate, decision reason, approval age ve replay sonucu;
  • çağrılan privileged API, destination class ve bounded response class;
  • request çevresindeki navigation, account, worker ve port lifecycle event’leri;
  • tek document’tan beklenmeyen request burst veya origin’ler arasında tekrarlayan denial;
  • effect correlation ve adjacent canary’nin değişmediğine ilişkin kanıt.

Token, page content, sensitive query string içeren tam URL veya raw cross-origin response loglamayın. Security telemetry ikinci bir exfiltration rotasına dönüşmemelidir.

Finding’i raporlamak

Kesin bir finding title ödünç alınan capability’yi adlandırır:

Content-script relay caller tarafından seçilen URL’yi browser sender context veya object authorization doğrulamadan forward ettiği için page script, extension service worker’a authenticated cross-origin project request yaptırabiliyordu.

Rapor şunları içermelidir:

  • exact browser, extension ve manifest version;
  • iki ingress rotası ve ulaştıkları listener;
  • effect ile ilgili manifest match pattern, frame scope ve permission;
  • yakalanan browser-observed sender alanları;
  • minimum message schema ve caller-controlled authority alanları;
  • page-only baseline, approved canary, unauthorized canary ve independent effect evidence;
  • origin, frame, document, operation, object, replay ve lifecycle için negative control;
  • gerçek sensitive data kullanmadan gösterilen minimum capability delta;
  • hem relay hem service-worker dispatcher içindeki root cause;
  • blocklist yerine capability contract olarak ifade edilen remediation;
  • cleanup proof ve kalan belirsizlik.

Severity, erişilebilir privileged effect ve caller population’a göre belirlenir. Tek exact partner origin’e sabit health response dönmek, geniş content-script match üzerinden erişilebilen arbitrary authenticated fetch ile aynı değildir. İddialar test edilen operation, origin, permission ve lifecycle state ile sınırlı kalmalıdır.

Nihai model

Güvenli tasarım “page data kullanılmadan önce sanitize edildi” değildir. Küçük bir authorization protocol’dür:

browser-observed sender
  → explicit ingress policy
  → versioned intent
  → trusted object resolution
  → fresh workflow authorization
  → tek bounded effect
  → minimum response

Isolated world değerlidir. Manifest match pattern değerlidir. externally_connectable değerlidir. Fakat hiçbiri sayfaya service worker’ın ambient authority’sini vermez.

Extension ancak şu soruyu evidence ile cevaplayabildiğinde confused deputy olmaktan çıkar: Hangi principal, hangi named capability’yi, hangi object için, hangi fresh approval altında istedi ve tam olarak ne değişti?

Kaynaklar ve güncellik

Bu teknik not ne kadar güncel?

Kontrol edilen kaynaklar31 Ağustos 2026

En son kaynak incelemesi, içerik güncellemesi veya yayın tarihi gösterilmektedir.

İnceleme DurumuKamuya açık kaynaklar incelendi

Birincil kamu kayıtları kontrol edildi. Ortama özgü davranış, ayrıca yeniden üretilmedikçe iddianın dışındadır.