High watch CVSS 4.3 chrome Authorization Error 🔧 Commit mapped

Overview

High
Severity
4.3
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactIncorrect authorization in Paint
DescriptionIncorrect authorization in Paint
ComponentPaint
Sub-componentHiC
Bug ClassAuthorization Error
Action tierwatch — information disclosure — security-relevant, below the RCE-class bar
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.
Tracker523095011
Fix commit84661bdde8bb (chromium/src) +5/-3
CWECWE-863
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:N
CISA KEVNot listed
CreditedGoogle
Reported2026-06-12 (per vendor advisory)
Fix landed2026-07-24 (public git)
Disclosed2026-08-25
Patch gap32 days — fix public in source before the advisory

Background

Text-clip mask painting
Blink renders -webkit-background-clip: text (and similar) by painting a mask in the PaintPhase::kTextClip phase; BoxFragmentPainter::PaintTextClipMask builds a nested PaintInfo for that pass.
`PaintInfo` / `PaintFlag`
the per-paint context object; PaintFlag::kPrivacyPreserving marks a paint that must not emit content the caller is not allowed to see (e.g. cross-origin pixels), and PaintInfo::IsPrivacyPreserving() reports whether the current paint carries that flag.
Privacy-preserving paint paths
capture/snapshot flows (element capture, cross-origin-restricted painting) run the paint tree with kPrivacyPreserving set so downstream painters redact protected content.
Flag propagation invariant
when a painter spawns a child PaintInfo for a sub-pass, it must carry the parent’s privacy-preserving state forward, or the sub-pass silently paints without the restriction.

Root Cause Analysis

BoxFragmentPainter::PaintTextClipMask constructs a fresh PaintInfo for the kTextClip mask pass from the parent paint_info, copying the context, cull rect, phase and DescendantPaintingBlocked() state — but it did not propagate the parent’s privacy-preserving flag.

As a result, when the outer paint was privacy-preserving (a capture/snapshot that must not expose cross-origin content), the text-clip mask sub-pass ran with no such restriction, so painting the mask could emit content that the privacy-preserving paint was specifically meant to withhold — an incorrect-authorization / cross-origin disclosure condition.

The fix threads the flag through explicitly: the new PaintInfo is built with paint_info.IsPrivacyPreserving() ? PaintFlag::kPrivacyPreserving : PaintFlag::kNoFlag, so the mask pass inherits the same restriction as its parent. The change is defensive hardening of the paint pipeline against downstream cross-origin content ever reaching a text-clip mask.

Key insight
A child PaintInfo spawned for the text-clip mask dropped the parent’s kPrivacyPreserving flag, so a privacy-preserving paint stopped being privacy-preserving inside the mask sub-pass; propagating the flag restores the invariant.

Attack Path

  1. Enter a privacy-preserving paint content reaches a capture/snapshot path (e.g. cross-origin-restricted element capture) that paints with PaintFlag::kPrivacyPreserving set.
  2. Target a text-clip element the captured subtree contains an element using text-clip masking, so BoxFragmentPainter::PaintTextClipMask runs.
  3. Flag is dropped pre-fix, the mask PaintInfo is created without the privacy-preserving flag, so the mask pass paints unrestricted.
  4. Cross-origin content exposed content that the privacy-preserving paint was meant to redact is painted into the mask output, disclosing it cross-origin.

Impact Assessment

An attacker gains a cross-origin information-disclosure vector in the renderer (Blink paint): a privacy-preserving capture that includes a text-clip mask could paint content it should have withheld. The precondition is reaching a kPrivacyPreserving paint over a text-clip-masked element; Chrome tracks it as incorrect authorization in Paint (high severity), and the fix is a defensive propagation that closes the gap before any downstream painter could leak cross-origin pixels.

Changed Functions

FunctionChangeNotes
if
third_party/blink/renderer/core/paint/box_fragment_painter.cc
modified

Files Changed

  • third_party/blink/renderer/core/paint/box_fragment_painter.cc

Audit Directions

  • Child `PaintInfo` construction
    audit every site that builds a nested PaintInfo for a sub-pass (masks, clips, filters, reflections) and confirm it forwards IsPrivacyPreserving() and other security-relevant flags from the parent.
  • Privacy-preserving completeness
    enumerate the paint phases reachable under kPrivacyPreserving and verify each honors the flag end-to-end, not just at the top-level entry.
  • Flag-drop on copy
    flag constructors/copies of context objects that carry security state (PaintFlag, taint, sandbox bits) but re-initialize a subset of fields, silently losing the rest.
From 84661bdde8bb85cdeb99dafd1661f13e6949cabf Mon Sep 17 00:00:00 2001
From: Stephen Chenney <schenney@chromium.org>
Date: Fri, 24 Jul 2026 13:05:08 -0700
Subject: [PATCH] [HiC] Add privacy flag for text clip

Not really a bug since it's not an external resource, but it makes
the AI happy and prevents further bug reports or potential problems
if the code downstream ever paints cross origin content.

Bug: 523095011
Change-Id: Id6dea450cbea60a109dd67b1e2f53f8401e47015
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8139364
Commit-Queue: Philip Rogers <pdr@chromium.org>
Auto-Submit: Stephen Chenney <schenney@chromium.org>
Reviewed-by: Philip Rogers <pdr@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1668117}
---
diff --git a/third_party/blink/renderer/core/paint/box_fragment_painter.cc b/third_party/blink/renderer/core/paint/box_fragment_painter.cc
index 1bdfbf5b..65a81573 100644
--- a/third_party/blink/renderer/core/paint/box_fragment_painter.cc
+++ b/third_party/blink/renderer/core/paint/box_fragment_painter.cc
@@ -2294,9 +2294,11 @@
                                            const gfx::Rect& mask_rect,
                                            const PhysicalOffset& paint_offset,
                                            bool object_has_multiple_boxes) {
-  PaintInfo mask_paint_info(paint_info.context, CullRect(mask_rect),
-                            PaintPhase::kTextClip,
-                            paint_info.DescendantPaintingBlocked());
+  PaintInfo mask_paint_info(
+      paint_info.context, CullRect(mask_rect), PaintPhase::kTextClip,
+      paint_info.DescendantPaintingBlocked(),
+      paint_info.IsPrivacyPreserving() ? PaintFlag::kPrivacyPreserving
+                                       : PaintFlag::kNoFlag);
   if (!object_has_multiple_boxes) {
     PaintObject(mask_paint_info, paint_offset);
     return;
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.