Medium chrome Uninitialized Memory 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUninitialized Use in WebML
DescriptionUninitialized Use in WebML
ComponentWebML
Bug ClassUninitialized Memory
Tracker497926664
Fix commit075420627d3c (chromium/src) +10/-0
CISA KEVNot listed
CreditedGoogle
Disclosed2026-06-02

Files Changed

  • services/webnn/coreml/tensor_impl_coreml.mm
From 075420627d3caa36a8253a4c3c0d62d7ac77535c Mon Sep 17 00:00:00 2001
From: Bryan Enrique Gonzalez Velez <bryanenriquegv@google.com>
Date: Thu, 09 Apr 2026 09:26:26 -0700
Subject: [PATCH] [Project-Fortify] Zero out uninitialized memory in WebNN CoreML

This is a quick fix for a potential security issue.

This change zero out uninitialized IOSurface memory.
Avoiding memory disclosure

Project-Fortify (Internal only) go/code-terracotta-review-explainer

Bug: 497926664
Change-Id: I55c5d4274dc1f4e766809b4c782daaf1469a8b27
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7735329
Reviewed-by: Stephen Nusko <nuskos@chromium.org>
Reviewed-by: Reilly Grant <reillyg@chromium.org>
Commit-Queue: Bryan Enrique Gonzalez <bryanenriquegv@google.com>
Cr-Commit-Position: refs/heads/main@{#1612294}
---

diff --git a/services/webnn/coreml/tensor_impl_coreml.mm b/services/webnn/coreml/tensor_impl_coreml.mm
index f35d6e20..ff7c757d 100644
--- a/services/webnn/coreml/tensor_impl_coreml.mm
+++ b/services/webnn/coreml/tensor_impl_coreml.mm
@@ -129,6 +129,16 @@
   IOSurfaceRef surface =
       IOSurfaceCreate(base::apple::NSToCFPtrCast(iosurface_properties));
 
+  CHECK_EQ(IOSurfaceLock(surface, 0, NULL), kIOReturnSuccess);
+
+  // SAFETY: IOSurfaceGetAllocSize is guaranteed to return the total
+  // allocation size of the buffer. See:
+  // https://developer.apple.com/documentation/iosurface/iosurfacegetallocsize(_:)
+  UNSAFE_BUFFERS(memset(IOSurfaceGetBaseAddress(surface), 0,
+                        IOSurfaceGetAllocSize(surface)));
+
+  CHECK_EQ(IOSurfaceUnlock(surface, 0, NULL), kIOReturnSuccess);
+
   CVPixelBufferRef pixel_buffer = nil;
   CVReturn pixel_buffer_result = CVPixelBufferCreateWithIOSurface(
       kCFAllocatorDefault, surface,
Loading diff…

Original Bug Report

reported by vm...@google.com

Potential uninitialized memory disclosure in WebNN CoreML float16 tensors

Project Fortify, an experimental security project, has identified the following potential security issue.

Overview: The WebNN CoreML backend on macOS fails to zero-initialize IOSurface-backed float16 tensors. Combined with a missing size validation check in WebNNContextImpl, this allows a web page or compromised renderer to read uninitialized GPU memory. This could leak sensitive cross-origin texture data or other process memory.

Affected files:

  • services/webnn/coreml/tensor_impl_coreml.mm
  • services/webnn/webnn_context_impl.cc
  • services/webnn/coreml/utils_coreml.mm

Estimated timestamp from git blame: 2025-08-18

Description

A potential uninitialized memory disclosure exists in the WebNN CoreML backend on macOS, which could allow an attacker to read uninitialized GPU process memory (such as recycled IOSurface buffers containing cross-origin WebGL textures or UI data).

There are two root causes that enable this:

  1. Missing Zero-Initialization in CoreML Backend: In services/webnn/coreml/tensor_impl_coreml.mm, the function CreateMultiArrayBackedByIOSurface is used to allocate memory for float16 tensors. It calls IOSurfaceCreate but fails to clear or zero-initialize the newly allocated surface. This contrasts with CreateMultiArrayFromDescriptor (used for other types), which explicitly uses memset to zero out the memory.

  2. Missing Size Validation in WebNNContext: In services/webnn/webnn_context_impl.cc, the WebNNContextImpl::CreateTensor method contains a size-validation check tensor_data.size() != validated_descriptor->PackedByteLength(). However, this check is only performed if the tensor has the kGraphConstant usage flag. For non-constant tensors, it accepts an empty buffer (assuming the backend already zero-initialized the tensor) or an undersized buffer.

Potential Steps to Trigger

Note: These are suggested steps based on static analysis; our tooling cannot execute working proofs-of-concept to verify them dynamically.

Path A: Standard Web Page

  1. An attacker’s web page calls MLContext.createTensor() requesting a float16 tensor.
  2. The renderer sends a CreateTensor Mojo IPC with an empty BigBuffer(0) for the initial data.
  3. The GPU process allocates the IOSurface via CreateMultiArrayBackedByIOSurface (leaving it uninitialized).
  4. In WebNNContextImpl::CreateTensor, because the buffer size is 0, the code skips calling WriteTensorImpl (relying on the false assumption that the tensor is already zero-initialized).
  5. The attacker calls MLTensor.read() to read the tensor, receiving the uninitialized IOSurface memory.

Path B: Compromised Renderer

  1. A compromised renderer sends a CreateTensor Mojo IPC for a large float16 tensor (e.g., 2MB) but provides a tiny tensor_data buffer (e.g., 1 byte).
  2. Because the validation check is skipped for non-constant tensors, WebNNContextImpl::CreateTensor accepts the 1-byte buffer and passes it to WriteTensorImpl.
  3. RecursivelyWriteToMLMultiArray (in utils_coreml.mm) copies the 1-byte prefix into the tensor, leaving the rest of the 2MB IOSurface uninitialized.
  4. The compromised renderer sends a ReadTensor IPC, extracting the full 2MB of uninitialized memory.

Suggested Fix

  1. Zero-Initialize IOSurfaces: In CreateMultiArrayBackedByIOSurface (services/webnn/coreml/tensor_impl_coreml.mm), map the newly created CVPixelBuffer or IOSurface and explicitly zero-initialize its contents before returning it.
  2. Enforce Size Validation: In WebNNContextImpl::CreateTensor (services/webnn/webnn_context_impl.cc), ensure that tensor_data.size() is validated against validated_descriptor->PackedByteLength() for all tensors, not just kGraphConstant tensors. The size should be strictly equal to either 0 (for uninitialized/default tensors) or the exact packed byte length.

Evaluated with Chrome root at commit: a9cbf6e8b275fe4147435aa905f3b7f5a656f5f0


Results from so far have been promising, but there can be wrong deductions. If this proves to be a false positive, please close as WAI; 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