Low watch chrome Authorization Error 🔧 Commit mapped

Overview

Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactMissing authorization in WebView
DescriptionMissing authorization in WebView
ComponentWebView
Bug ClassAuthorization Error
Action tierwatch — logic/policy bug — security-relevant, no memory-unsafety
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.
Tracker497094708
Fix commit05d64dba60f2 (chromium/src) +16/-0
CWECWE-862
CISA KEVNot listed
CreditedGoogle
Reported2026-03-28 (per vendor advisory)
Fix landed2026-08-24 (public git)
Disclosed2026-09-22
Patch gap29 days — fix public in source before the advisory

Background

`RfhToIoThreadClientMap`
the Android WebView browser-side map keying a RenderFrameHost (by process id + LocalFrameToken) to the embedder’s Java IO-thread client, which decides that frame’s network policy (shouldInterceptRequest, shouldOverrideUrlLoading, blocking, etc.).
`SubFrameCreated` IPC
a renderer-originated message reporting that a child frame was created under a parent, historically used by the browser to add the child’s entry to RfhToIoThreadClientMap.
`ClientMapEntryUpdater`
a browser-side WebContentsObserver that already populates RfhToIoThreadClientMap authoritatively as frames are created, independent of any renderer IPC.
Killswitch feature flag
a base::Feature shipped default-enabled so risky behavior can be disabled in the field and later removed once proven safe.

Root Cause Analysis

The browser handler AwContentsIoThreadClient::SubFrameCreated updated RfhToIoThreadClientMap using the parent and child LocalFrameTokens supplied by the renderer over the SubFrameCreated IPC. Because a renderer is untrusted and can be compromised, it could send SubFrameCreated with attacker-chosen frame tokens, inserting or overwriting a map entry so that a frame is associated with the IO-thread client — and therefore the network/authorization policy — of a different frame than the one the browser legitimately created. This is a missing-authorization condition: a security-relevant mapping that governs per-frame request handling was derived from renderer-controlled input rather than from browser-owned frame-lifecycle state.

The fix gates the handler behind kWebViewSubFrameCreatedDoNotUpdateClientMap (enabled by default), making it early-return so the renderer IPC no longer mutates the map; correctness is preserved because ClientMapEntryUpdater, a browser-side WebContentsObserver, already creates the entry from trusted frame-creation events.

Key insight
A security-sensitive frame-to-client mapping was being written from a renderer-controlled IPC even though the browser already populated it authoritatively; the fix stops trusting the renderer input entirely rather than trying to validate the tokens it supplies.

Attack Path

  1. Compromise a renderer The attacker gains code execution in a WebView renderer process, or otherwise controls the messages it emits.
  2. Forge frame tokens The renderer sends a SubFrameCreated IPC carrying parent/child LocalFrameTokens chosen to target a victim frame’s map slot.
  3. Corrupt the client map AwContentsIoThreadClient::SubFrameCreated writes the attacker-influenced entry into RfhToIoThreadClientMap, associating a frame with the wrong embedder IO-thread client.
  4. Bypass per-frame policy Subsequent network requests for that frame are routed through the mismatched client, letting the frame evade or misapply the embedder’s request-interception/authorization decisions.

Impact Assessment

An attacker controlling a WebView renderer can influence which embedder IO-thread client governs a frame’s network handling, a missing-authorization / policy-confusion bug in the privileged browser process of apps embedding WebView. The precondition is a compromised or malicious renderer able to emit the SubFrameCreated IPC; the default-enabled killswitch closes the surface by ignoring that IPC, relying on the browser’s own ClientMapEntryUpdater for correct entries.

Files Changed

  • android_webview/browser/aw_contents_io_thread_client.cc
  • android_webview/common/aw_features.h
  • android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
  • android_webview/common/aw_features.cc

Audit Directions

  • Renderer-supplied identity into browser maps
    Audit any browser-side structure keyed on LocalFrameToken/frame identifiers taken from renderer IPCs; the browser’s own frame-lifecycle observers should be the source of truth for security-relevant mappings.
  • Redundant trust paths
    Look for state that is populated both by a trusted browser observer and by an untrusted renderer message; the renderer path is pure attack surface and should be removed or ignored.
  • WebView IO-thread client resolution
    Review every consumer of RfhToIoThreadClientMap for assumptions that a frame’s entry is authentic, since a mismatched client silently changes network-authorization behavior.
From 05d64dba60f23209116c5355a1ee2f45abd1b790 Mon Sep 17 00:00:00 2001
From: Arthur Sonzogni <[email protected]>
Date: Mon, 24 Aug 2026 13:15:42 -0700
Subject: [PATCH] Add killswitch to disable updating client map on SubFrameCreated IPC

This adds the kWebViewSubFrameCreatedDoNotUpdateClientMap feature flag
(enabled by default) acting as a killswitch. When enabled, the browser
ignores the SubFrameCreated IPC from the renderer and no longer updates
RfhToIoThreadClientMap.

The map entry is already created on the browser side via
ClientMapEntryUpdater (WebContentsObserver) when frames are created.

If no issues arise in ~5 months (~January 2027), this feature flag and
the associated SubFrameCreated IPC can be completely removed as proposed
in https://crrev.com/c/8159020.

Fixed: 497094708
Change-Id: I1b9b60f0fa29de795d6dc6f68ea5af88c5ad7ec6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8279597
Auto-Submit: Arthur Sonzogni <[email protected]>
Commit-Queue: Arthur Sonzogni <[email protected]>
Reviewed-by: Richard Coles <[email protected]>
Commit-Queue: Richard Coles <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1684954}
---
diff --git a/android_webview/browser/aw_contents_io_thread_client.cc b/android_webview/browser/aw_contents_io_thread_client.cc
index 6d2a25e..6a5f872 100644
--- a/android_webview/browser/aw_contents_io_thread_client.cc
+++ b/android_webview/browser/aw_contents_io_thread_client.cc
@@ -431,6 +431,10 @@
     int child_id,
     const blink::LocalFrameToken& parent_frame_token,
     const blink::LocalFrameToken& child_frame_token) {
+  if (base::FeatureList::IsEnabled(
+          features::kWebViewSubFrameCreatedDoNotUpdateClientMap)) {
+    return;
+  }
   RfhToIoThreadClientMap* map = RfhToIoThreadClientMap::GetInstance();
   std::optional<JavaObjectWeakGlobalRef> opt_delegate_weak_ref = map->Get(
       content::GlobalRenderFrameHostToken(child_id, parent_frame_token));
diff --git a/android_webview/common/aw_features.cc b/android_webview/common/aw_features.cc
index f34247e..e5403e6 100644
--- a/android_webview/common/aw_features.cc
+++ b/android_webview/common/aw_features.cc
@@ -392,6 +392,13 @@
 BASE_FEATURE(kWebViewStaticMethodsNotTriggerStartup,
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+// Kill switch for updating RfhToIoThreadClientMap on SubFrameCreated IPC.
+// When enabled, the map is not updated from the SubFrameCreated IPC.
+// TODO(crbug.com/497094708): Remove this flag and apply
+// https://crrev.com/c/8159020 in ~5 months (~January 2027).
+BASE_FEATURE(kWebViewSubFrameCreatedDoNotUpdateClientMap,
+             base::FEATURE_ENABLED_BY_DEFAULT);
+
 // A Feature used for WebView variations tests. Not used in production. Please
 // do not clean up this stale feature: we intentionally keep this feature flag
 // around for testing purposes.
diff --git a/android_webview/common/aw_features.h b/android_webview/common/aw_features.h
index 8e9a17cd..31b8c4e 100644
--- a/android_webview/common/aw_features.h
+++ b/android_webview/common/aw_features.h
@@ -98,6 +98,7 @@
 BASE_DECLARE_FEATURE(kWebViewSingleSharedContextState);
 BASE_DECLARE_FEATURE(kWebViewSkipInterceptsForPrefetch);
 BASE_DECLARE_FEATURE(kWebViewStaticMethodsNotTriggerStartup);
+BASE_DECLARE_FEATURE(kWebViewSubFrameCreatedDoNotUpdateClientMap);
 BASE_DECLARE_FEATURE(kWebViewTestFeature);
 BASE_DECLARE_FEATURE(kWebViewTestNonembeddedLowEntropySource);
 BASE_DECLARE_FEATURE(kWebViewUnreducedProductVersion);
diff --git a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
index 27f6834..babf45e 100644
--- a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
+++ b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
@@ -1460,6 +1460,10 @@
                 "Allows Webview to allocate and share a single shared context for all the"
                         + " webview instances."),
         Flag.baseFeature("ComponentsBase32InRust", "Enables the Rust-based Base32 implementation."),
+        Flag.baseFeature(
+                AwFeatures.WEBVIEW_SUB_FRAME_CREATED_DO_NOT_UPDATE_CLIENT_MAP,
+                "When enabled, the browser ignores SubFrameCreated IPC and does not update"
+                        + " RfhToIoThreadClientMap."),
         // Add new commandline switches and features above. The final entry should have a
         // trailing comma for cleaner diffs.
     };
Loading diff…

Original Bug Report

The reporter's bug is still restricted on the tracker. Chrome de-restricts security bugs ~30–90 days after the fix ships; a later run will backfill it here.