Medium watch CVSS 5.3 chrome Info Disclosure 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
5.3
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInformation leak in ControlledFrame
DescriptionInformation leak in ControlledFrame
ComponentControlledFrame
Sub-componentControlled Frame
Bug ClassInfo Disclosure
Action tierwatch — information disclosure — security-relevant, below the RCE-class bar
Computed by PatchGap's deterministic exploitability ruler from the fixing commit. patch-now = RCE-class & attacker-reachable in a default config, or exploited in the wild; watch = real security signal below that bar; noise = no security relevance.
Tracker533070113
Fix commit5e86f334aa87 (chromium/src) +105/-9
CWECWE-200 (Information exposure)
CVSS vectorCVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:N/A:N
CISA KEVNot listed
CreditedGoogle
Reported2026-07-09 (per vendor advisory)
Fix landed2026-08-04 (public git)
Disclosed2026-09-08
Patch gap35 days — fix public in source before the advisory

Background

Controlled Frame
an embedding primitive (built on the WebView/guest-view machinery) that lets an Isolated Web App host untrusted web content in a separate guest render process while injecting embedder-supplied content scripts.
`UserScriptLoader`
the browser-side class that serializes registered content scripts into a base::ReadOnlySharedMemoryRegion and pushes them to renderers via the UpdateUserScripts Mojo call.
`owner_host` / `WebViewRendererState`
owner_host is the IWA origin that owns a guest, and WebViewRendererState is the browser-side registry mapping each guest process to its WebViewInfo, including the set of content_script_ids actually registered to that guest.
`kControlledFrameEmbedder`
the mojom::HostID::HostType value identifying scripts owned by a Controlled Frame embedder (the IWA), as opposed to an extension.

Root Cause Analysis

In UserScriptLoader::SendUpdate, the browser duplicated the single shared-memory region holding all of the embedder’s serialized content scripts (shared_memory.Duplicate()) and sent it to every guest process whose owner_host matched host_id().id. Because a single IWA origin can host multiple sibling Controlled Frame guests that share the same owner_host, a script targeted at one specific guest was broadcast, in raw serialized form, into the shared memory of all sibling guests. Although script execution was gated elsewhere, the source bytes were still resident in the unrelated sibling guest’s address space, giving that guest read access to script source it was never authorized to see (CWE-200).

The fix makes SendUpdate branch on kControlledFrameEmbedder, query WebViewRendererState::GetContentScriptIDsForProcess for the exact script IDs registered to the target process, and re-Serialize only the matching scripts into a per-process region; if the process has no registered scripts, or none match, it returns kNoActionTaken and sends nothing.

Key insight
The single core mistake was sharing one all-inclusive serialized script region across every guest that merely shared an owner_host, conflating “same owner” with “authorized recipient”; the fix filters scripts per-process by the guest’s explicitly registered content_script_ids before serialization.

Attack Path

  1. Host multiple guests under one IWA An Isolated Web App (the embedder) creates two or more Controlled Frame guests that share the same owner_host, one of which loads attacker-influenced content.
  2. Register a script for one guest The embedder registers a content script intended for only one specific guest process, so the serialized region contains that script’s source code.
  3. Broadcast on update UserScriptLoader::SendUpdate duplicates the full shared-memory region and calls UpdateUserScripts on every sibling guest process matching owner_host, placing the script’s raw source into each sibling’s shared memory.
  4. Read cross-guest source The unrelated sibling guest process, which was never registered for that script, can read the injected source bytes out of its own mapped shared memory, disclosing content-script source intended for a different guest (inferred as to the specific in-renderer read primitive, which the patch does not show).

Impact Assessment

An attacker controlling one Controlled Frame guest process gains read access to embedder content-script source code intended for a sibling guest under the same IWA owner_host — an information disclosure confined to guest renderer memory. The advisory classifies this as an information leak in Controlled Frame (CWE-200); it does not report exploitation in the wild, and no code execution or sandbox escape is demonstrated by the patch.

Changed Functions

FunctionChangeNotes
for
extensions/browser/guest_view/web_view/web_view_renderer_state.cc
modified
if
extensions/browser/guest_view/web_view/web_view_renderer_state.cc
modified
if
extensions/browser/user_script_loader.cc
modified
for
extensions/browser/user_script_loader.cc
modified

Files Changed

  • extensions/browser/guest_view/web_view/web_view_renderer_state.h
  • extensions/browser/guest_view/web_view/web_view_renderer_state.cc
  • extensions/browser/user_script_loader_unittest.cc
  • extensions/browser/user_script_loader.cc

Audit Directions

  • Shared-memory fan-out by coarse owner key
    Audit any browser-side code that serializes data once and broadcasts the same region/handle to multiple renderers keyed on a shared owner (origin, owner_host, partition) rather than on per-recipient authorization.
  • Execution-gated but not disclosure-gated data
    Look for paths where a security control blocks use of data (execution, rendering) but the raw data is still copied into an unauthorized process’s memory, since presence alone is an info leak.
  • Guest-view multiplexing
    Review other WebViewRendererState/guest-view consumers that iterate the web_view_info_map_ by owner_host to ensure they scope per-guest resources (script IDs, partitions) rather than granting embedder-wide access.
From 5e86f334aa876188b1809b0f6a9ee78dfa6c4892 Mon Sep 17 00:00:00 2001
From: Simon Hangl <simonha@google.com>
Date: Tue, 04 Aug 2026 07:03:05 -0700
Subject: [PATCH] [Controlled Frame] Fix cross-guest content script source leak

A vulnerability existed in Controlled Frame where content script source
code intended for a specific guest process was serialized and broadcast
to all sibling guest processes that shared the same owner_host (IWA
origin). Although script execution was properly blocked, the raw source
code was still present in the sibling guest's memory, leading to a
CWE-200 Information Exposure leak.

This CL fixes the issue by updating `UserScriptLoader::SendUpdate` to
filter scripts during serialization. For `kControlledFrameEmbedder`
host types, it now queries `WebViewRendererState` for the explicit
script IDs registered to the target guest process. If the process has
no registered scripts, or the script IDs do not match, they are stripped
from the shared memory region before it is sent across the IPC.

Added `EmbedderScriptsNotSentToUnrelatedGuestProcess` to
`UserScriptLoaderUnitTest` to mock the renderer Mojo interface and
mechanically guarantee that the browser correctly drops unrelated
scripts.

Bug: 533070113
Change-Id: I366ac8a721d5449fe48ad0beaf85a1fb14418acb
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8155940
Reviewed-by: Andrea Orru <andreaorru@chromium.org>
Commit-Queue: Simon Hangl <simonha@google.com>
Reviewed-by: Kevin McNee <mcnee@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1673303}
---
diff --git a/extensions/browser/guest_view/web_view/web_view_renderer_state.cc b/extensions/browser/guest_view/web_view/web_view_renderer_state.cc
index f78ff2d..5111519 100644
--- a/extensions/browser/guest_view/web_view/web_view_renderer_state.cc
+++ b/extensions/browser/guest_view/web_view/web_view_renderer_state.cc
@@ -126,6 +126,24 @@
   return false;
 }
 
+std::optional<std::set<std::string>>
+WebViewRendererState::GetContentScriptIDsForProcess(
+    content::ChildProcessId guest_process_id) const {
+  base::AutoLock auto_lock(web_view_info_map_lock_);
+
+  std::optional<std::set<std::string>> script_ids;
+  for (const auto& info : web_view_info_map_) {
+    if (info.first.child_id == guest_process_id) {
+      if (!script_ids) {
+        script_ids.emplace();
+      }
+      script_ids->insert(info.second.content_script_ids.begin(),
+                         info.second.content_script_ids.end());
+    }
+  }
+  return script_ids;
+}
+
 void WebViewRendererState::AddContentScriptIDs(
     int embedder_process_id,
     int view_instance_id,
diff --git a/extensions/browser/guest_view/web_view/web_view_renderer_state.h b/extensions/browser/guest_view/web_view/web_view_renderer_state.h
index f1fc86a..c61e22c 100644
--- a/extensions/browser/guest_view/web_view/web_view_renderer_state.h
+++ b/extensions/browser/guest_view/web_view/web_view_renderer_state.h
@@ -14,6 +14,7 @@
 #define EXTENSIONS_BROWSER_GUEST_VIEW_WEB_VIEW_WEB_VIEW_RENDERER_STATE_H_
 
 #include <map>
+#include <optional>
 #include <set>
 #include <string>
 #include <utility>
@@ -66,6 +67,10 @@
   // found, otherwise returns false.
   bool GetPartitionID(int guest_process_id, std::string* partition_id) const;
 
+  // Returns the content script IDs for the given guest process.
+  std::optional<std::set<std::string>> GetContentScriptIDsForProcess(
+      content::ChildProcessId guest_process_id) const;
+
   // Returns true if the renderer with process ID `render_process_id` is a
   // WebView guest process.
   bool IsGuest(int render_process_id) const;
diff --git a/extensions/browser/user_script_loader.cc b/extensions/browser/user_script_loader.cc
index f5d8358..8d75262 100644
--- a/extensions/browser/user_script_loader.cc
+++ b/extensions/browser/user_script_loader.cc
@@ -550,11 +550,8 @@
       NOTREACHED();
   }
 
-  base::ReadOnlySharedMemoryRegion region_for_process =
-      shared_memory.Duplicate();
-  if (!region_for_process.IsValid()) {
-    return SendUpdateResult::kNoActionTaken;
-  }
+  base::ReadOnlySharedMemoryRegion region_for_process;
+  bool use_custom_region = false;
 
 #if BUILDFLAG(ENABLE_GUEST_VIEW)
   // If the process only hosts guest frames, then those guest frames share the
@@ -601,11 +598,49 @@
         if (owner_host != host_id().id) {
           return SendUpdateResult::kNoActionTaken;
         }
+
+        if (host_id().type ==
+            mojom::HostID::HostType::kControlledFrameEmbedder) {
+          use_custom_region = true;
+          std::optional<std::set<std::string>> script_ids =
+              WebViewRendererState::GetInstance()
+                  ->GetContentScriptIDsForProcess(process->GetID());
+          if (!script_ids || script_ids->empty()) {
+            return SendUpdateResult::kNoActionTaken;
+          }
+          if (loaded_scripts_) {
+            UserScriptList filtered_scripts;
+            for (const std::unique_ptr<UserScript>& script : *loaded_scripts_) {
+              if (script_ids->count(script->id())) {
+                std::unique_ptr<UserScript> filtered_script =
+                    UserScript::CopyMetadataFrom(*script);
+                for (size_t i = 0; i < script->js_scripts().size(); ++i) {
+                  filtered_script->js_scripts()[i]->set_content(
+                      std::string(script->js_scripts()[i]->GetContent()));
+                }
+                for (size_t i = 0; i < script->css_scripts().size(); ++i) {
+                  filtered_script->css_scripts()[i]->set_content(
+                      std::string(script->css_scripts()[i]->GetContent()));
+                }
+                filtered_scripts.push_back(std::move(filtered_script));
+              }
+            }
+            region_for_process = Serialize(filtered_scripts);
+          }
+        }
         break;
     }
   }
 #endif
 
+  if (!use_custom_region) {
+    region_for_process = shared_memory.Duplicate();
+  }
+
+  if (!region_for_process.IsValid()) {
+    return SendUpdateResult::kNoActionTaken;
+  }
+
   renderer->UpdateUserScripts(std::move(region_for_process),
                               mojom::HostID::New(host_id().type, host_id().id));
   return SendUpdateResult::kRendererHasBeenNotified;
diff --git a/extensions/browser/user_script_loader_unittest.cc b/extensions/browser/user_script_loader_unittest.cc
index 3cc7818..e9e179a 100644
--- a/extensions/browser/user_script_loader_unittest.cc
+++ b/extensions/browser/user_script_loader_unittest.cc
@@ -161,10 +161,12 @@
     return process;
   }
 
-  void LoadScriptsAndWait(UserScriptLoader* loader,
-                          content::RenderProcessHost* embedder_process) {
+  void LoadScriptsAndWait(
+      UserScriptLoader* loader,
+      content::RenderProcessHost* embedder_process,
+      std::string script_id = UserScript::GenerateUserScriptID()) {
     auto script = std::make_unique<UserScript>();
-    script->set_id(UserScript::GenerateUserScriptID());
+    script->set_id(script_id);
     script->set_host_id(loader->host_id());
     auto content = UserScript::Content::CreateInlineCode(
         GURL("https://embedder.example/inline.js"));
@@ -202,8 +204,10 @@
   ASSERT_TRUE(helper()->IsProcessInitializedForTesting(guest_process.get()));
 
   const std::string owner_host = "isolated-app://embedder.example";
+  const std::string script_id = UserScript::GenerateUserScriptID();
   WebViewRendererState::WebViewInfo web_view_info;
   web_view_info.owner_host = owner_host;
+  web_view_info.content_script_ids.insert(script_id);
   const int dummy_routing_id = 1;
   WebViewRendererState::GetInstance()->AddGuestForTesting(
       guest_process->GetDeprecatedID(), dummy_routing_id, web_view_info);
@@ -218,7 +222,7 @@
       browser_context(),
       mojom::HostID(mojom::HostID::HostType::kControlledFrameEmbedder,
                     owner_host));
-  LoadScriptsAndWait(&loader, guest_process.get());
+  LoadScriptsAndWait(&loader, guest_process.get(), script_id);
 
   EXPECT_TRUE(loader.initial_load_complete());
   EXPECT_TRUE(helper()->ProcessReceivedUpdateUserScripts(guest_process.get()));
@@ -254,6 +258,40 @@
   }
 }
 
+// Test that an embedder content script is NOT sent to a guest renderer
+// if that guest's ID is not associated with the script.
+// This prevents cross-guest script leaks in Controlled Frame.
+TEST_F(UserScriptLoaderUnitTest,
+       EmbedderScriptsNotSentToUnrelatedGuestProcess) {
+  std::unique_ptr<content::MockRenderProcessHost> guest_process =
+      CreateAndInitializeProcess(/*is_for_guests_only=*/true);
+  ASSERT_TRUE(helper()->IsProcessInitializedForTesting(guest_process.get()));
+
+  const std::string owner_host = "isolated-app://embedder.example";
+  // Deliberately do NOT add the script_id to web_view_info.content_script_ids.
+  // This simulates a sibling guest process that shouldn't receive the script.
+  WebViewRendererState::WebViewInfo web_view_info;
+  web_view_info.owner_host = owner_host;
+  const int dummy_routing_id = 1;
+  WebViewRendererState::GetInstance()->AddGuestForTesting(
+      guest_process->GetDeprecatedID(), dummy_routing_id, web_view_info);
+  base::ScopedClosureRunner cleanup_guest(base::BindOnce(
+      [](int process_id, int routing_id) {
+        WebViewRendererState::GetInstance()->RemoveGuestForTesting(process_id,
+                                                                   routing_id);
+      },
+      guest_process->GetDeprecatedID(), dummy_routing_id));
+
+  EmbedderUserScriptLoader loader(
+      browser_context(),
+      mojom::HostID(mojom::HostID::HostType::kControlledFrameEmbedder,
+                    owner_host));
+  LoadScriptsAndWait(&loader, guest_process.get());
+
+  EXPECT_TRUE(loader.initial_load_complete());
+  EXPECT_FALSE(helper()->ProcessReceivedUpdateUserScripts(guest_process.get()));
+}
+
 }  // namespace
 
 }  // namespace extensions
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/extensions/browser/user_script_loader_unittest.cc b/extensions/browser/user_script_loader_unittest.cc
index 3cc7818..e9e179a 100644
--- a/extensions/browser/user_script_loader_unittest.cc
+++ b/extensions/browser/user_script_loader_unittest.cc
@@ -161,10 +161,12 @@
     return process;
   }
 
-  void LoadScriptsAndWait(UserScriptLoader* loader,
-                          content::RenderProcessHost* embedder_process) {
+  void LoadScriptsAndWait(
+      UserScriptLoader* loader,
+      content::RenderProcessHost* embedder_process,
+      std::string script_id = UserScript::GenerateUserScriptID()) {
     auto script = std::make_unique<UserScript>();
-    script->set_id(UserScript::GenerateUserScriptID());
+    script->set_id(script_id);
     script->set_host_id(loader->host_id());
     auto content = UserScript::Content::CreateInlineCode(
         GURL("https://embedder.example/inline.js"));
@@ -202,8 +204,10 @@
   ASSERT_TRUE(helper()->IsProcessInitializedForTesting(guest_process.get()));
 
   const std::string owner_host = "isolated-app://embedder.example";
+  const std::string script_id = UserScript::GenerateUserScriptID();
   WebViewRendererState::WebViewInfo web_view_info;
   web_view_info.owner_host = owner_host;
+  web_view_info.content_script_ids.insert(script_id);
   const int dummy_routing_id = 1;
   WebViewRendererState::GetInstance()->AddGuestForTesting(
       guest_process->GetDeprecatedID(), dummy_routing_id, web_view_info);
@@ -218,7 +222,7 @@
       browser_context(),
       mojom::HostID(mojom::HostID::HostType::kControlledFrameEmbedder,
                     owner_host));
-  LoadScriptsAndWait(&loader, guest_process.get());
+  LoadScriptsAndWait(&loader, guest_process.get(), script_id);
 
   EXPECT_TRUE(loader.initial_load_complete());
   EXPECT_TRUE(helper()->ProcessReceivedUpdateUserScripts(guest_process.get()));
@@ -254,6 +258,40 @@
   }
 }
 
+// Test that an embedder content script is NOT sent to a guest renderer
+// if that guest's ID is not associated with the script.
+// This prevents cross-guest script leaks in Controlled Frame.
+TEST_F(UserScriptLoaderUnitTest,
+       EmbedderScriptsNotSentToUnrelatedGuestProcess) {
+  std::unique_ptr<content::MockRenderProcessHost> guest_process =
+      CreateAndInitializeProcess(/*is_for_guests_only=*/true);
+  ASSERT_TRUE(helper()->IsProcessInitializedForTesting(guest_process.get()));
+
+  const std::string owner_host = "isolated-app://embedder.example";
+  // Deliberately do NOT add the script_id to web_view_info.content_script_ids.
+  // This simulates a sibling guest process that shouldn't receive the script.
+  WebViewRendererState::WebViewInfo web_view_info;
+  web_view_info.owner_host = owner_host;
+  const int dummy_routing_id = 1;
+  WebViewRendererState::GetInstance()->AddGuestForTesting(
+      guest_process->GetDeprecatedID(), dummy_routing_id, web_view_info);
+  base::ScopedClosureRunner cleanup_guest(base::BindOnce(
+      [](int process_id, int routing_id) {
+        WebViewRendererState::GetInstance()->RemoveGuestForTesting(process_id,
+                                                                   routing_id);
+      },
+      guest_process->GetDeprecatedID(), dummy_routing_id));
+
+  EmbedderUserScriptLoader loader(
+      browser_context(),
+      mojom::HostID(mojom::HostID::HostType::kControlledFrameEmbedder,
+                    owner_host));
+  LoadScriptsAndWait(&loader, guest_process.get());
+
+  EXPECT_TRUE(loader.initial_load_complete());
+  EXPECT_FALSE(helper()->ProcessReceivedUpdateUserScripts(guest_process.get()));
+}
+
 }  // namespace
 
 }  // namespace extensions
Loading diff…

Original Bug Report

reported by vm...@google.com

Potential IWA <controlledframe> content script source leak to sibling guest processes

Project Fortify, an experimental security project, has identified the following potential security issue. If you’re a feature owner CC-ed on this bug, please do your best to review these reports. Please see https://chromium.googlesource.com/chromium/src/+/main/docs/security/ai-generated-security-bugs-faq.md for more information.

Overview: An information disclosure vulnerability potentially exists in the Isolated Web App (IWA) <controlledframe> implementation where custom content script source code can leak to sibling guest processes. Because content script serialization and updates are origin-scoped rather than guest-instance-scoped, all scripts registered by an IWA are bundled into a single shared memory region and sent to every guest process owned by that IWA. A compromised guest process can map and read this shared memory region to retrieve sensitive script bytes intended for other frames.

Affected files:

  • extensions/browser/user_script_loader.cc
  • components/guest_view/browser/guest_view_base.cc
  • extensions/browser/api/guest_view/web_view/web_view_internal_api.cc
  • extensions/browser/user_script_manager.cc
  • extensions/browser/guest_view/web_view/web_view_content_script_manager.cc

Estimated timestamp from git blame: 2024-01-22

Summary of the Potential Issue

An architectural information disclosure vulnerability potentially exists in the Isolated Web App (IWA) <controlledframe> implementation. The issue allows custom content script source code (including inline script bytes) to leak across sibling guest processes.

Because content script serialization and distribution are scoped to the IWA’s origin (HostID of type kControlledFrameEmbedder) rather than to specific guest instances, all scripts registered by an IWA across different <controlledframe> elements are bundled into a single shared memory region. This region is then sent to every guest process owned by that IWA. A compromised guest process can read this shared memory mapping and retrieve sensitive script bytes intended only for other frames.

Root Cause Analysis

  1. Origin-Scoped User Script Loader: In extensions/browser/user_script_manager.cc:74-89, there is exactly one EmbedderUserScriptLoader per HostID:

    EmbedderUserScriptLoader* UserScriptManager::GetUserScriptLoaderForEmbedder(
        const mojom::HostID& host_id) {
      auto it = embedder_script_loaders_.find(host_id);
      if (it != embedder_script_loaders_.end()) return it->second.get();
      ...
      return CreateEmbedderUserScriptLoader(host_id);
    }
    

    For any <controlledframe> element embedded inside an IWA, the generated HostID is of type kControlledFrameEmbedder and its ID is the serialized IWA origin (e.g., "isolated-app://iwa-A"):

    // extensions/browser/api/guest_view/web_view/web_view_internal_api.cc:119-125
    if (embedder_rfh->GetWebExposedIsolationLevel() >=
        content::WebExposedIsolationLevel::kIsolatedApplication) {
      const std::string origin =
          embedder_rfh->GetMainFrame()->GetLastCommittedOrigin().Serialize();
      return extensions::mojom::HostID(
          extensions::mojom::HostID::HostType::kControlledFrameEmbedder, origin);
    }
    

    As a result, all <controlledframe> elements within the same IWA share a single, unified EmbedderUserScriptLoader.

  2. Broadcasting to All Owned Guests: In UserScriptLoader::SendUpdate() (extensions/browser/user_script_loader.cc:580-603), the recipient filter only checks if the guest’s owner_host matches the loader’s HostID ID:

    if (owner_host != host_id().id) {
      return SendUpdateResult::kNoActionTaken;
    }
    

    Because all guest views embedded in the same IWA share the same owner_host (the IWA’s serialized origin), this check passes for all guest processes owned by the IWA. Consequently, the entire serialized shared memory region—containing all scripts registered by any guest frame—is transmitted to every guest process.

  3. Renderer Memory Mapping: Upon receiving the update, the guest renderer process maps the shared memory region via UserScriptSet::UpdateUserScripts():

    shared_memory_mapping_ = shared_memory.Map();
    

    While the in-process execution gate (UserScriptInjector::CanExecuteOnFrame) correctly prevents the execution of unauthorized scripts, the script contents remain resident in the guest process’s address space.

Suggested Potential Exploitation Steps

(Note: These are potential steps, as our analysis is static and our tooling agent does not have the ability to execute code or run a live proof of concept.)

  1. Setup: An IWA page embeds two <controlledframe> guest views with distinct storage partitions:
    • cf1 (trusted partition) loads https://trusted.example and has a custom script added via addContentScripts containing a secret API key or token in its inline code payload.
    • cf2 (untrusted partition) loads an attacker-controlled origin.
  2. Process Separation: The two guest views are placed into separate guest renderer processes due to their distinct partitions.
  3. Data Broadcast: The browser serializes all scripts for the IWA origin into a single ReadOnlySharedMemoryRegion and transmits it to both cf1’s and cf2’s renderer processes.
  4. Exfiltration: An attacker who compromises the guest renderer process of cf2 (renderer RCE) can read the memory space of their own process, locating the mapped ReadOnlySharedMemoryRegion and extracting the raw script bytes containing the sensitive API key/token intended only for cf1.

Impact

Cross-instance information disclosure from a compromised guest renderer. This breaks the isolation boundary between <controlledframe> storage partitions when custom content scripts are used, potentially leaking sensitive credentials or developer-authored logic across frames.

Suggested Fix

To resolve this issue, the browser should ensure that the shared memory region delivered to a guest process only contains scripts that the specific guest process is authorized to execute.

This could be achieved by:

  1. Keying EmbedderUserScriptLoader instances more granularly, such as combining the HostID with the guest’s instance/view ID or storage partition.
  2. Or filtering the scripts during the serialization or delivery phase so that a distinct shared memory region is built and sent for each unique set of authorized scripts per guest process.

Evaluated with Chrome root at commit: 84065d9121f6e48f67755f0ae963cc09617e5c85


Results so far have been promising, but there can be wrong deductions. Feel free to adjust as follows:

  • If you are familiar with the severity guidelines, you may adjust the severity.
  • If this is a false positive, and there’s no work to be done, please close as WAI.
  • If there is work to do here but not a vulnerability, please change the issue type to Task/Bug/FR.

Data from false positives will be used to improve accuracy over time. And please feel free to reach out to me directly if you have concerns or feedback on the project.

View on issue tracker