Low watch CVSS 4.3 chrome Logic Error 📄 Reporter bug report 🔧 Commit mapped

Overview

Low
Severity
4.3
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInappropriate implementation in Compositing
DescriptionInappropriate implementation in Compositing
ComponentCompositing
Sub-componentPEPC
Bug ClassLogic Error
Action tierwatch — logic/policy bug — security-relevant, no memory-unsafety
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.
Tracker429440615
Fix commitc5539496a8fd (chromium/src) +34/-0
CWECWE-451
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L
CISA KEVNot listed
CreditedHafiizh
Reported2025-07-03 (per vendor advisory)
Fix landed2025-07-08 (public git)
Disclosed2025-09-02
Patch gap56 days — fix public in source before the advisory

Background

`<permission>` element (PEPC)
the Page-Embedded Permission Control, a browser-rendered permission button implemented in third_party/blink/renderer/core/html/html_permission_element.cc, whose click is treated as a trusted user permission decision.
PEPC style locking
Blink allows only a list of CSS properties on <permission> and clamps or resets others, so that a page cannot make the control illegible or misleading.
Internal permission text span
the shadow-tree element that holds the control’s label text; it inherits computed style from the <permission> host.

Root Cause Analysis

The <permission> style-adjustment code in html_permission_element.cc (the enclosing function’s name is not in the hunk; the hunk ends just before HTMLPermissionElement::DidRecalcStyle) enforced an allowlist of CSS properties for the element. As the commit message and the new comment explain, -webkit-text-stroke-width, -webkit-text-stroke-color and -webkit-text-fill-color are not on that allowlist, but they are inherited by default. So values from the page, set on the element or an ancestor, still flowed into the computed style and reached the internal label span. The invariant that the label is painted only with locked styling was therefore broken.

The fix tightens enforcement by calling builder.ResetTextStrokeWidth(), builder.ResetTextFillColor() and builder.ResetTextStrokeColor() at the end of the adjustment, so those properties fall back to their initial values before the inner text inherits them. The reftest text-stroke-and-fill.tentative.html, which sets a 10px blue stroke and red fill on both permission and its parent div, must now match an unstyled <permission>. The advisory files this under “Compositing”, but the fix itself is in Blink style resolution for PEPC; the commit’s Fixed: 429440615 matches the advisory’s bug ID.

Key insight
Blocking a property from being set on an element does not stop its inherited value from reaching that element’s internals. PEPC’s allowlist missed inherited -webkit-text-* paint properties until they were explicitly reset on the builder.

Attack Path

  1. Page embeds a permission control A site places <permission type="camera"> in its document.
  2. Page sets inherited text paint properties It applies -webkit-text-stroke-width, -webkit-text-stroke-color and/or -webkit-text-fill-color to the element or an ancestor, as the reftest does.
  3. Values bypass the allowlist via inheritance Before the fix, these inherited values reached the internal label span and changed how the browser-controlled text was painted.
  4. Label is obscured or disguised A thick stroke, or a fill colour that differs from the contrast-checked color, could make the label illegible or misleading and so trick the user into granting a permission (inferred; the patch demonstrates only the visual change).

Impact Assessment

A web page could change how the trusted <permission> control’s label is painted in its own renderer, weakening PEPC’s anti-clickjacking style guarantees. This is a UI-deception issue (inferred), not a memory-safety or sandbox bug. It is reachable by ordinary page CSS wherever the <permission> element is available to the page. That requires the PEPC feature to be enabled (flag or origin trial at the time; inferred, since the diff does not show the gating), plus a user click on the altered control. The vendor severity is low, and the supplied metadata does not report in-the-wild exploitation.

Files Changed

  • third_party/blink/renderer/core/html/html_permission_element.cc
  • third_party/blink/web_tests/external/wpt/html/semantics/permission-element/text-stroke-and-fill-ref.html
  • third_party/blink/web_tests/external/wpt/html/semantics/permission-element/text-stroke-and-fill.tentative.html

Audit Directions

  • Inherited properties outside the allowlist
    Enumerate every inherited CSS property, especially prefixed or paint-only ones such as -webkit-text-security, text-shadow, paint-order, -webkit-text-emphasis, font-palette and caret/accent colours, and confirm that PEPC either allows and clamps each one or explicitly resets it.
  • Contrast checks vs. actual paint colour
    PEPC validates color against the background, so check whether other properties (fill colour, stroke, background-clip: text, filters on ancestors) can make the painted colours differ from the checked ones.
  • Shadow-tree inheritance in locked controls
    For other browser-rendered trusted UI built from shadow DOM, check that host-level property restrictions are re-applied to, or reset for, the internal elements that inherit from the host.
From c5539496a8fd440a8f9ad62031184a109307efd7 Mon Sep 17 00:00:00 2001
From: Andy Paicu <[email protected]>
Date: Tue, 08 Jul 2025 01:46:38 -0700
Subject: [PATCH] [PEPC] Prevent -webkit-text-stroke/-webkit-text-fill on the permission element

Even though these properties are not allowed for the permission element,
it seems they get inherited to the inner text anyways. Therefore reset
them manually.

Fixed: 429440615
Change-Id: Ie17b82de959c92ba808d3c966385f31527ef2ea1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6705900
Reviewed-by: Mason Freed <[email protected]>
Commit-Queue: Andy Paicu <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1483611}
---

diff --git a/third_party/blink/renderer/core/html/html_permission_element.cc b/third_party/blink/renderer/core/html/html_permission_element.cc
index 28d8b733..ac35dd0 100644
--- a/third_party/blink/renderer/core/html/html_permission_element.cc
+++ b/third_party/blink/renderer/core/html/html_permission_element.cc
@@ -981,6 +981,15 @@
       }
     }
   }
+
+  // These webkit-prefixed properties are not supported by the permission
+  // element. But since they are inherited by default, they are passed through
+  // to the internal permission text span, even if they're not on the list of
+  // allowed CSS properties.
+  // Reset them here to avoid any side effects.
+  builder.ResetTextStrokeWidth();
+  builder.ResetTextFillColor();
+  builder.ResetTextStrokeColor();
 }
 
 void HTMLPermissionElement::DidRecalcStyle(const StyleRecalcChange change) {
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/text-stroke-and-fill-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/text-stroke-and-fill-ref.html
new file mode 100644
index 0000000..c420d08
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/text-stroke-and-fill-ref.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<body>
+  <div>
+    <permission type="camera"></permission>
+  </div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/text-stroke-and-fill.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/text-stroke-and-fill.tentative.html
new file mode 100644
index 0000000..05b49508
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/text-stroke-and-fill.tentative.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<link rel="match" href="text-stroke-and-fill-ref.html">
+<link rel="help" href="https://github.com/WICG/PEPC/blob/main/explainer.md#locking-the-pepc-style">
+<body>
+  <style>
+    permission, div {
+      -webkit-text-stroke-width: 10px;
+      -webkit-text-stroke-color: blue;
+      -webkit-text-fill-color: red;
+    }
+  </style>
+  <div>
+    <permission type="camera"></permission>
+  </div>
+</body>
+</html>
\ No newline at end of file
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/text-stroke-and-fill-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/text-stroke-and-fill-ref.html
new file mode 100644
index 0000000..c420d08
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/text-stroke-and-fill-ref.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<body>
+  <div>
+    <permission type="camera"></permission>
+  </div>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/text-stroke-and-fill.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/text-stroke-and-fill.tentative.html
new file mode 100644
index 0000000..05b49508
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/text-stroke-and-fill.tentative.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<link rel="match" href="text-stroke-and-fill-ref.html">
+<link rel="help" href="https://github.com/WICG/PEPC/blob/main/explainer.md#locking-the-pepc-style">
+<body>
+  <style>
+    permission, div {
+      -webkit-text-stroke-width: 10px;
+      -webkit-text-stroke-color: blue;
+      -webkit-text-fill-color: red;
+    }
+  </style>
+  <div>
+    <permission type="camera"></permission>
+  </div>
+</body>
+</html>
\ No newline at end of file
Loading diff…

Original Bug Report

reported by [email protected]

Permission element inner div with style -webkit-text-stroke-width: thick;font-weight: bolder; can be abused if no element in the parent chain has any -webkit-text-stroke-width: thick;font-weight: bolder; are set.

This bug is similar to https://issues.chromium.org/issues/398803201, https://issues.chromium.org/issues/423670839, https://issues.chromium.org/issues/428455319, https://issues.chromium.org/issues/429270814

when -webkit-text-stroke-width: thick;font-weight: bolder; are embedded in a tag above the <permission> tag, for example a div or something else, this affects the <permission> tag, thus covering the text in the <permission> tag. if style -webkit-text-stroke-width: thick;font-weight: bolder; embedded directly in the <permission> tag are not affected. The impact is that sites can potentially trick users to trigger permission prompts even if the permission is currently in a DENY state for that origin. (It does not however bypass the permission prompt in any way)

references for some css that can and cannot be embedded in the <permission> tag: https://developer.chrome.com/blog/permission-element-origin-trial?hl=en

View on issue tracker