High chrome Type Confusion 🔧 Commit mapped

Overview

High
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactType confusion in V8
DescriptionType confusion in V8
ComponentV8
Sub-componentObjects
Bug ClassType Confusion
Tracker562038980
Fix commit3d445698dfc9 (v8/v8) +30/-1
CISA KEVNot listed
CreditedGoogle
Disclosed2026-10-13

Changed Functions

FunctionChangeNotes
if
src/objects/map.cc
modified
TEST_F
test/unittests/api/remote-object-unittest.cc
modified

Files Changed

  • src/objects/js-objects.cc
  • src/objects/map.cc
  • test/unittests/api/remote-object-unittest.cc
From 3d445698dfc94acd9027f59060404780554601b1 Mon Sep 17 00:00:00 2001
From: Igor Sheludko <ishell@chromium.org>
Date: Thu, 01 Oct 2026 20:07:11 +0200
Subject: [PATCH] [objects] Prevent map normalization of remote objects

When `Object.assign` encounters a source object with a large number of
properties, `JSReceiver::SetOrCopyDataProperties` pre-normalizes the
target object to a dictionary map.

If the target object is a remote object (a JS_SPECIAL_API_OBJECT_TYPE
whose map is contextless), it possesses no `NativeContext`.
`Map::Normalize` was previously unconditionally casting the `Null` native
context of the remote object's meta-map to a `NativeContext`, leading
to an out-of-bounds ReadOnly memory access and eventually OOB writes.

This patch updates `JSReceiver::SetOrCopyDataProperties` to exclude
contextless `JS_SPECIAL_API_OBJECT_TYPE` targets from normalization,
properly handling them alongside global proxies and shared structs,
which natively lack a context. It also replaces the potential silent
crash in `Map::Normalize` with a `DCHECK`.

Fixed: 562038980

TAG=agy
CONV=39463f19-fb84-40db-8b81-2d8d8d68ab36

Change-Id: I9116d3e144f44e7e569b609fb5c055a4640fbb57
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/8502261
Reviewed-by: Patrick Thier <pthier@chromium.org>
Auto-Submit: Igor Sheludko <ishell@chromium.org>
Commit-Queue: Patrick Thier <pthier@chromium.org>
Cr-Commit-Position: refs/heads/main@{#110261}
---
diff --git a/src/objects/js-objects.cc b/src/objects/js-objects.cc
index ea767fef..2018421 100644
--- a/src/objects/js-objects.cc
+++ b/src/objects/js-objects.cc
@@ -478,6 +478,9 @@
     InstanceType target_instance_type = target->map()->instance_type();
     if (InstanceTypeChecker::IsJSObject(target_instance_type) &&
         !InstanceTypeChecker::IsJSGlobalProxy(target_instance_type) &&
+        // Exclude remote objects (they don't have local properties anyway).
+        !(InstanceTypeChecker::IsJSSpecialApiObject(target_instance_type) &&
+          !target->GetCreationContext().has_value()) &&
         !InstanceTypeChecker::IsAlwaysSharedSpaceJSObject(
             target_instance_type)) {
       // Convert to slow properties if we're guaranteed to overflow the number
diff --git a/src/objects/map.cc b/src/objects/map.cc
index 185c934..c45a674 100644
--- a/src/objects/map.cc
+++ b/src/objects/map.cc
@@ -1384,8 +1384,10 @@
   }
   DirectHandle<NormalizedMapCache> cache;
   if (use_cache) {
+    Tagged<Object> maybe_native_context = meta_map->native_context_or_null();
+    DCHECK(!IsNull(maybe_native_context));
     Tagged<Object> normalized_map_cache =
-        meta_map->native_context()->normalized_map_cache();
+        Cast<NativeContext>(maybe_native_context)->normalized_map_cache();
     use_cache = !IsUndefined(normalized_map_cache);
     if (use_cache) {
       cache = Cast<NormalizedMapCache>(
diff --git a/test/unittests/api/remote-object-unittest.cc b/test/unittests/api/remote-object-unittest.cc
index 7536274..7a54c98 100644
--- a/test/unittests/api/remote-object-unittest.cc
+++ b/test/unittests/api/remote-object-unittest.cc
@@ -101,5 +101,29 @@
   EXPECT_STREQ("object", *result);
 }
 
+TEST_F(RemoteObjectTest, NormalizeRemoteObject) {
+  Local<FunctionTemplate> constructor_template =
+      FunctionTemplate::New(isolate(), Constructor);
+  constructor_template->InstanceTemplate()->SetAccessCheckCallbackAndHandler(
+      AccessCheck, NamedPropertyHandlerConfiguration(NamedGetter),
+      IndexedPropertyHandlerConfiguration());
+
+  Local<Object> remote_object =
+      constructor_template->NewRemoteInstance().ToLocalChecked();
+
+  Local<Context> context = Context::New(isolate());
+  Context::Scope context_scope(context);
+
+  context->Global()
+      ->Set(context, String::NewFromUtf8Literal(isolate(), "remoteObj"),
+            remote_object)
+      .Check();
+
+  TryRunJS(
+      "const src = {};"
+      "for (let i = 0; i < 1200; i++) src['p' + i] = 1;"
+      "try { Object.assign(remoteObj, src); } catch (e) {}");
+}
+
 }  // namespace remote_object_unittest
 }  // namespace v8
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/test/unittests/api/remote-object-unittest.cc b/test/unittests/api/remote-object-unittest.cc
index 7536274..7a54c98 100644
--- a/test/unittests/api/remote-object-unittest.cc
+++ b/test/unittests/api/remote-object-unittest.cc
@@ -101,5 +101,29 @@
   EXPECT_STREQ("object", *result);
 }
 
+TEST_F(RemoteObjectTest, NormalizeRemoteObject) {
+  Local<FunctionTemplate> constructor_template =
+      FunctionTemplate::New(isolate(), Constructor);
+  constructor_template->InstanceTemplate()->SetAccessCheckCallbackAndHandler(
+      AccessCheck, NamedPropertyHandlerConfiguration(NamedGetter),
+      IndexedPropertyHandlerConfiguration());
+
+  Local<Object> remote_object =
+      constructor_template->NewRemoteInstance().ToLocalChecked();
+
+  Local<Context> context = Context::New(isolate());
+  Context::Scope context_scope(context);
+
+  context->Global()
+      ->Set(context, String::NewFromUtf8Literal(isolate(), "remoteObj"),
+            remote_object)
+      .Check();
+
+  TryRunJS(
+      "const src = {};"
+      "for (let i = 0; i < 1200; i++) src['p' + i] = 1;"
+      "try { Object.assign(remoteObj, src); } catch (e) {}");
+}
+
 }  // namespace remote_object_unittest
 }  // namespace v8
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.