CVE-2025-12906
Overview
Background
- PEPC (Page Embedded Permission Control) / `<permission>` element
- a built-in HTML element (e.g.
<permission type="camera">) whose appearance is locked down by the user agent so that a page cannot deceptively style a permission prompt trigger. - User-agent shadow content (`::-internal-permission-text`)
- the internal pseudo-element that renders the permission element’s text label, styled by the browser’s built-in
permission.css. - CSS inheritance
- the mechanism by which certain text properties (e.g.
text-emphasis,text-shadow) flow from a parent element into descendants, including into UA-internal text unless explicitly reset. - `initial !important`
- a declaration that forces a property to its initial value and prevents author styles from overriding it, used to “lock” the PEPC style.
Root Cause Analysis
The <permission> element’s internal text is rendered by the UA pseudo-element ::-internal-permission-text, whose styling permission.css is meant to fully control so the label cannot be visually tampered with by the embedding page. However, the inheritable text-decoration properties text-emphasis and text-shadow were not reset in permission.css, so they inherited from the page’s ancestor styles (e.g. a div wrapping the <permission>). As the added web-platform test shows, an author could set text-emphasis and text-shadow on a parent and have those styles applied to the permission label, undermining the guarantee that the permission prompt’s appearance is under UA control.
The fix adds text-emphasis: initial !important; and text-shadow: initial !important; to the permission::-internal-permission-text rule, forcing these properties to their defaults and blocking author inheritance. This restores the PEPC invariant that the internal text does not inherit style from its parent.
text-emphasis, text-shadow) un-reset on the permission element’s internal text, letting page CSS bleed into a UA-controlled label; the fix pins them to initial !important so author styles cannot influence the prompt’s text.Attack Path
- Embed a permission element
A page includes
<permission type="camera">inside an ancestor (e.g. adiv) whose styles it controls. - Apply inheritable text styling
The page sets
text-emphasisand/ortext-shadowon the ancestor, properties that inherit into descendant text. - Style bleeds into UA text
Because
permission::-internal-permission-textdid not reset these properties, the inheritedtext-emphasis/text-shadowrender on the permission element’s internal label, contrary to the PEPC style-locking guarantee. - Deceive the user
The attacker uses this to alter the permission prompt trigger’s text appearance (a spoofing/inappropriate-implementation issue); any concrete user deception outcome is
(inferred)and no memory-safety impact is involved.
Impact Assessment
<permission> element’s UA-controlled text via inherited text-emphasis/text-shadow, weakening the anti-spoofing guarantees of the permission UI in the renderer; this is a logic/inappropriate-implementation issue, not memory corruption. The precondition is only that the page can place a <permission> element under an element it styles. The advisory classifies this as LogicError / “Inappropriate implementation in Permissions” and does not report exploitation in the wild; any spoofing consequence is (inferred).Files Changed
third_party/blink/renderer/core/html/resources/permission.cssthird_party/blink/web_tests/external/wpt/html/semantics/permission-element/inherited-css-ref.htmlthird_party/blink/web_tests/external/wpt/html/semantics/permission-element/inherited-css-tentative.html
Audit Directions
- Un-reset inheritable properties on UA-locked elementsAudit
permission.cssand other UA stylesheets for security-sensitive elements to ensure all inheritable text/visual properties are pinned (initial !important) rather than left to inherit from author content. - Style-locking completenessFor any element whose appearance is meant to be tamper-proof (permission prompts, security chrome), enumerate the full set of inheritable CSS properties and confirm each is neutralized, not just a subset.
- New CSS features vs. locked UITrack newly added inheritable CSS properties and verify they are also reset on style-locked pseudo-elements, since additions can silently reopen this class of inheritance bleed.
Patch
From 6ab0f046554dcc728e6e875de79578ae95bb3e5f Mon Sep 17 00:00:00 2001
From: Thomas Nguyen <tungnh@chromium.org>
Date: Wed, 02 Jul 2025 08:41:08 -0700
Subject: [PATCH] [PEPC] Reset CSS inherited style for permission's internal text element.
This ensures that the permission's internal text will not inherit text
style from its parent.
Bug: 428455319
Change-Id: I8d4b61efe010fd4ea24913afaaafba8b9105a80f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6696007
Commit-Queue: Thomas Nguyen <tungnh@chromium.org>
Reviewed-by: Joey Arhar <jarhar@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1481641}
---
diff --git a/third_party/blink/renderer/core/html/resources/permission.css b/third_party/blink/renderer/core/html/resources/permission.css
index 6505655..d82a9fa 100644
--- a/third_party/blink/renderer/core/html/resources/permission.css
+++ b/third_party/blink/renderer/core/html/resources/permission.css
@@ -31,6 +31,8 @@
}
permission::-internal-permission-text {
+ text-emphasis: initial !important;
+ text-shadow: initial !important;
align-items: center;
display: flex;
font-family: Arial, Helvetica, sans-serif;
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/inherited-css-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/inherited-css-ref.html
new file mode 100644
index 0000000..6714e31
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/inherited-css-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<link rel="help" href="https://github.com/WICG/PEPC/blob/main/explainer.md#locking-the-pepc-style">
+<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/inherited-css-tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/inherited-css-tentative.html
new file mode 100644
index 0000000..f1a8d3b6
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/inherited-css-tentative.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<link rel="match" href="inherited-css-ref.html">
+<link rel="help" href="https://github.com/WICG/PEPC/blob/main/explainer.md#locking-the-pepc-style">
+<!-- The permission element not inherit css properties from the parent div.
+-->
+<body>
+ <style>
+ div {
+ text-emphasis: "x";
+ text-emphasis-position: over right;
+ text-shadow: 1px 1px 2px black;
+ }
+ </style>
+ <div>
+ <permission type="camera"></permission>
+ </div>
+</body>
+</html>
\ No newline at end of file
Regression Test / PoC
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/inherited-css-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/inherited-css-ref.html
new file mode 100644
index 0000000..6714e31
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/inherited-css-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<link rel="help" href="https://github.com/WICG/PEPC/blob/main/explainer.md#locking-the-pepc-style">
+<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/inherited-css-tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/inherited-css-tentative.html
new file mode 100644
index 0000000..f1a8d3b6
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/inherited-css-tentative.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<link rel="match" href="inherited-css-ref.html">
+<link rel="help" href="https://github.com/WICG/PEPC/blob/main/explainer.md#locking-the-pepc-style">
+<!-- The permission element not inherit css properties from the parent div.
+-->
+<body>
+ <style>
+ div {
+ text-emphasis: "x";
+ text-emphasis-position: over right;
+ text-shadow: 1px 1px 2px black;
+ }
+ </style>
+ <div>
+ <permission type="camera"></permission>
+ </div>
+</body>
+</html>
\ No newline at end of file
Original Bug Report
Permission element inner div with style text-emphasis:꧁; and text-emphasis-position: over right; can be abused if no element in the parent chain has any text-emphasis:꧁; and text-emphasis-position: over right; are set.
This bug is similar to https://issues.chromium.org/issues/398803201, https://issues.chromium.org/issues/423670839
when text-emphasis:꧁; and text-emphasis-position: over right; 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 text-emphasis:꧁; and text-emphasis-position: over right; 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