CWE-653 (Insufficient Compartmentalization) applies when injected UI elements live directly in the host page's DOM tree. Without Shadow DOM, the host page's CSS rules cascade into your extension UI — z-index, font-size, color, display can all be overridden by the page, producing broken layouts. Conversely, your injected styles can break the host page's UI, causing support tickets and potential Chrome Web Store policy violations. Shadow DOM creates a hard boundary at the style sheet level: the host page cannot style inside the shadow root, and styles defined inside cannot leak out. This is the only reliable way to build UI in content scripts that survives across arbitrary host pages.
Low because style leakage and injection are primarily reliability and UX failures rather than direct security vulnerabilities, but they can degrade extension functionality enough to produce support-surfaced bugs.
Wrap every injected UI element in a Shadow DOM root with mode: 'closed' in your content scripts.
// src/content.js
const host = document.createElement('div');
const shadow = host.attachShadow({ mode: 'closed' });
shadow.appendChild(myUIElement);
document.body.appendChild(host);
Using 'closed' prevents the host page from accessing the shadow root via element.shadowRoot. Load all stylesheets into the shadow root directly using new CSSStyleSheet() or a <link> element appended inside the shadow.
ID: extension-permissions-security.content-script-isolation.shadow-dom
Severity: low
What to look for: Enumerate all UI injection points in content scripts. Count the number of attachShadow calls vs direct document.body.appendChild calls. Check if injected UI (buttons, sidebars, overlays) creates a ShadowRoot.
Pass criteria: At least 1 attachShadow call is present for UI elements injected into the host page. All injected UI components are encapsulated in Shadow DOM, preventing style conflicts with the host page.
Fail criteria: UI elements are appended directly to document.body or existing elements without Shadow DOM isolation.
Skip (N/A) when: Content script does not inject visible UI.
Detail on fail: "Injected UI is not isolated with Shadow DOM. Page styles may break your UI, or your styles may break the page."
Remediation: Use Shadow DOM in your content scripts to protect your extension's UI from the host page's CSS.
// src/content.js
const host = document.createElement('div');
const shadow = host.attachShadow({mode: 'closed'});
shadow.appendChild(myUIElement);
document.body.appendChild(host);