Medium chrome Logic Error 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInsufficient validation of untrusted input in WebNN
DescriptionInsufficient validation of untrusted input in WebNN
ComponentWebNN
Bug ClassLogic Error
Tracker499051067
Fix commit27d53b3a9c47 (chromium/src) +4/-0
CISA KEVNot listed
CreditedGoogle
Disclosed2026-06-02

Files Changed

  • services/webnn/webnn_graph_builder_impl.cc
From 27d53b3a9c4772b0bab0ff99ee3e31db916c93a0 Mon Sep 17 00:00:00 2001
From: Shiyi Zou <shiyi.zou@intel.com>
Date: Thu, 09 Apr 2026 02:03:18 -0700
Subject: [PATCH] webnn: reject slice with scalar input in mojo validation

Slicing a scalar is a no-op that the blink side already handles [1], so
this path should never be reached from a well-behaved renderer.

[1]
https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.cc;l=3150

Bug: 499051067
Change-Id: I772a25de722c6ce8e189aa1d4412fc055ad590be
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7740566
Commit-Queue: Zou, Shiyi <shiyi.zou@intel.com>
Reviewed-by: Hu, Ningxin <ningxin.hu@intel.com>
Cr-Commit-Position: refs/heads/main@{#1612050}
---

diff --git a/services/webnn/webnn_graph_builder_impl.cc b/services/webnn/webnn_graph_builder_impl.cc
index afafdc9..bac2399 100644
--- a/services/webnn/webnn_graph_builder_impl.cc
+++ b/services/webnn/webnn_graph_builder_impl.cc
@@ -2358,6 +2358,10 @@
     // The slice operator is invalid.
     return false;
   }
+  if (input->descriptor.Rank() == 0) {
+    // Slicing a scalar is a no-op that the blink side has handled.
+    return false;
+  }
 
   const base::expected<OperandDescriptor, std::string> validated_output =
       ValidateSliceAndInferOutput(*context_properties_, input->descriptor,
Loading diff…

Original Bug Report

reported by vm...@google.com

Potential OOB access in GPU process via rank-0 Slice in WebNN ORT backend

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 without the security team.

Overview: A compromised renderer can bypass Blink’s validation and send a rank-0 Slice operation with empty parameters to the GPU process. The GPU validation fails to enforce a non-scalar rank constraint, allowing zero-element arrays to be passed to the ONNX Runtime backend, potentially leading to an out-of-bounds access.

Affected files:

  • services/webnn/ort/graph_builder_ort.cc
  • services/webnn/webnn_context_impl.cc
  • services/webnn/webnn_graph_builder_impl.cc
  • services/webnn/ort/graph_impl_ort.cc

Estimated timestamp from git blame: 2025-07-02

Description

In WebNN, the Slice operation is expected to operate on tensors and slice along defined dimensions. In the Blink renderer (MLGraphBuilder::slice), if a rank-0 (scalar) input is provided with empty dimensions, it is safely converted to an Identity operation. However, a compromised renderer can bypass this and send a raw mojom::Slice operation to the GPU process with a rank-0 input and an empty ranges array.

The GPU-side validation in ValidateSliceAndInferOutput (services/webnn/public/cpp/graph_validation_utils.cc) attempts to validate the operation. It checks if the backend supports the input data type and rank via context_properties.data_type_limits.slice_input. In the ONNX Runtime (ORT) backend (services/webnn/ort/context_impl_ort.cc), slice_input allows up to kMaxRank (which includes 0). Unlike other operations, WebNNContextImpl::IntersectWithBaseProperties does not restrict slice_input to kNonScalarMaxRank.

Because the input rank is 0, length checks like attributes.starts.size() != input_rank evaluate to 0 != 0 (False). Furthermore, the bounds validation loop (for (uint32_t i = 0; i < input_rank; ++i)) is entirely skipped. The GPU process therefore deems the malformed scalar Slice valid.

The operation is then dispatched to GraphBuilderOrt::AddSliceOperation (services/webnn/ort/graph_builder_ort.cc), which initializes starts, ends, steps, and axes based on the empty ranges array. This results in the creation of ONNX 1D initializer tensors with a shape of [0]. These empty tensors are added to the ONNX model as the Slice parameters.

When the ONNX model is initialized in the ORT Execution Provider (e.g., DirectML), the underlying engine is forced to parse a Slice node parameterized by zero-length arrays. As previously documented by Chrome developers in the same file (see AddReverseOperation workaround: “we map this to an Identity node to prevent ORT EPs from mishandling empty arrays”), ORT Execution Providers mishandle empty configuration arrays. This can lead to the Execution Provider assuming at least one dimension is present, performing unchecked memory operations, and resulting in an out-of-bounds read or write within the highly privileged GPU process.

Potential Steps to Reproduce

  1. From a compromised renderer, instantiate a WebNN graph builder.
  2. Create a rank-0 scalar input operand.
  3. Construct a mojom::Slice operation targeting the rank-0 operand, providing an explicitly empty ranges array.
  4. Send the CreateGraph IPC message to the GPU process.
  5. The GPU process validates the operation, forwards the empty arrays to the ORT backend, and potentially triggers an OOB access during graph initialization or execution.

Suggested Fix

In services/webnn/webnn_context_impl.cc, update IntersectWithBaseProperties to correctly restrict slice_input to non-scalar ranks by intersecting it with kNonScalarMaxRank. Alternatively, explicitly reject rank-0 inputs or explicitly handle empty range arrays in ValidateSliceAndInferOutput.

Evaluated with Chrome root at commit: ff3d2b74fa39431785bd60e51463b08fcc71ee33


Results 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