All 22 checks with why-it-matters prose, severity, and cross-references to related audits.
CWE-250 (Execution with Unnecessary Privileges) is the direct consequence of over-broad Chrome extension permissions. Every extra permission listed in `manifest.json` expands your attack surface: a supply-chain compromise of one dependency can exfiltrate all browsing history if `history` is listed, or silently install other extensions if `management` is present. Chrome's permission-warning system means excessive permissions also trigger alarming install dialogs that depress conversion rates and erode user trust. OWASP A01 (Broken Access Control) governs this: the extension should operate with the minimum privilege necessary. Unused permissions discovered during Chrome Web Store review will block publication.
Why this severity: Critical because a compromised extension with over-broad permissions — such as `tabs` or `management` — can silently exfiltrate browsing history or install malware, with no user-visible indication.
extension-permissions-security.permission-scope-validation.permissions-minimalSee full patternRequesting `<all_urls>` or `*://*/*` in `host_permissions` grants your extension read and write access to every page the user visits — every banking session, every health portal, every private message thread. Chrome's permission-warning system flags this with a maximally alarming install dialog ('Read and change all your data on all websites'), crushing install conversion. Per the Chrome Web Store policy on host permissions, extensions must request only the minimal host access needed. CWE-250 applies: any code executing with `<all_urls>` access runs at a privilege level that makes a single XSS or supply-chain vulnerability into a total browsing-history exfiltration event.
Why this severity: High because global host permissions expose all browsing data to the extension process, making any JavaScript compromise within the extension a full browsing-session exfiltration.
extension-permissions-security.permission-scope-validation.no-all-urlsSee full patternStatic host permissions show a scary install-time warning ('Read and change your data on specific websites') and persist even when the user hasn't triggered the extension. `activeTab`, by contrast, grants temporary access only to the tab that is active at the moment the user explicitly invokes the extension — no persistent grant, no install warning, and no access to background tabs. CWE-250 governs this: a static host permission is an execution privilege that persists indefinitely, while `activeTab` is just-in-time. Chrome's published permission guidelines strongly prefer `activeTab` for any user-gesture-driven workflow.
Why this severity: High because static host permissions persist beyond user intent, granting background access to page content even when the extension is idle — an unnecessary privilege escalation.
extension-permissions-security.permission-scope-validation.active-tab-prioritizedSee full patternRequesting every permission upfront means users see the full warning list before they have any reason to trust the extension, which reduces install rates and raises legitimate privacy concerns. CWE-250 applies: permissions that only support optional features run with unnecessary privilege during all other extension operations. Chrome's `optional_permissions` API lets you defer scary permission requests — `bookmarks`, `downloads`, `history` — until the user opts into the specific feature that needs them, which dramatically increases trust-to-request ratio and keeps your surface area small when those features are unused.
Why this severity: Low because the attack surface created by upfront optional permissions is real but modest — it exposes feature-specific APIs to the background context rather than blocking core functionality.
extension-permissions-security.permission-scope-validation.optional-permissionsSee full patternCWE-346 (Origin Validation Error) describes exactly this failure: a message listener that does not check `sender.id` will execute privileged extension logic when called by any other extension or web page that can reach the runtime. If `externally_connectable` is open, a malicious website can send crafted messages to trigger background actions — deleting data, making API calls, or exfiltrating stored tokens. CWE-20 (Improper Input Validation) compounds this when the message payload itself is trusted without validation. OWASP A01 (Broken Access Control) applies: the background script is a privileged context and its listeners are the access-control boundary.
Why this severity: High because an unvalidated message listener in the background script can be triggered by any extension or external web page, turning privileged background logic into a remotely callable attack surface.
extension-permissions-security.permission-scope-validation.message-sender-validationSee full patternCWE-79 (Cross-Site Scripting) in an extension context is substantially more dangerous than on a website: extension pages run with privileged access to `chrome.*` APIs, so an XSS that executes in an extension page can read storage, make API requests, or exfiltrate data from all tabs the extension accesses. CWE-693 (Protection Mechanism Failure) names the category. In Manifest V3, remote code execution is outright banned by Chrome policy; any `script-src` directive permitting remote URLs will cause CWS rejection. Wildcards in `script-src` (e.g., `https:`) completely defeat CSP. The Chrome MV3 CSP documentation makes this a hard requirement, not a recommendation.
Why this severity: Critical because a permissive `script-src` in an extension page allows script injection into a privileged context with direct access to Chrome APIs, turning any XSS into full extension compromise.
extension-permissions-security.content-security-policy.script-src-safeSee full patternCWE-95 (Eval Injection) and CWE-79 both apply here: `'unsafe-eval'` in an extension CSP enables `eval()`, `new Function()`, and `setTimeout` with string arguments, all of which can execute attacker-controlled strings as code. In an extension context, that code runs with `chrome.*` API access. OWASP A03 (Injection) covers this attack class. Chrome's own documentation states that `'unsafe-eval'` should never appear in extension CSP; MV3 bans it entirely. Even in MV2, its presence typically indicates AI-generated or copy-pasted code that hasn't been refactored for the privilege model extensions require.
Why this severity: Critical because `'unsafe-eval'` allows dynamic string execution in a privileged extension context, enabling any injected string to invoke `chrome.*` APIs directly.
extension-permissions-security.content-security-policy.no-unsafe-evalSee full patternCWE-693 (Protection Mechanism Failure) captures the gap: an extension that restricts `script-src` but omits `object-src` still allows `<object>`, `<embed>`, and `<applet>` tags to load arbitrary plugins. Although Flash is dead, the attack vector persists because `object-src` defaulting to `default-src` is exploitable when `default-src` is permissive. OWASP A05 (Security Misconfiguration) applies: a CSP that looks correct but has an unconstrained fallback is misconfigured. Chrome's own CSP documentation explicitly recommends `object-src 'none'` as part of the minimal safe CSP for extension pages.
Why this severity: High because a missing explicit `object-src` directive allows plugin-based content injection via `<object>` and `<embed>` tags, bypassing an otherwise hardened `script-src` policy.
extension-permissions-security.content-security-policy.object-src-noneSee full patternBase tag injection (CAPEC-86) is a real attack: if an attacker can inject `<base href="https://evil.com/">` into an extension page via DOM XSS, all relative URLs in that page — scripts, images, API calls — resolve to the attacker's server. CWE-16 (Configuration) names the failure: omitting `base-uri` from CSP leaves a bypass path for XSS that circumvents `script-src`. OWASP A05 (Security Misconfiguration) applies. Setting `base-uri 'none'` costs nothing and closes a class of attack that bypasses otherwise correct CSP configurations. Chrome extension security guidance lists this as a required directive for hardened CSPs.
Why this severity: Medium because base tag injection requires a prior XSS opportunity, but when that condition exists, it redirects all relative resource loads to an attacker-controlled origin.
extension-permissions-security.content-security-policy.base-uri-restrictedSee full patternCWE-693 and OWASP A05 apply: a permissive `style-src` directive (e.g., `style-src *` or `style-src https:`) allows any external stylesheet to be loaded into extension pages. While style injection is less immediately dangerous than script injection, CSS exfiltration attacks exist — attribute selectors can leak sensitive DOM content character by character. More practically, allowing external styles defeats the extension's origin isolation and can be used to fingerprint extension state via timing side-channels. Restricting `style-src` to `'self'` forces style bundling, which also improves offline reliability and eliminates dependency on third-party CDNs.
Why this severity: Medium because wildcard style sources enable CSS-based data exfiltration attacks and defeat origin isolation, though exploitation requires chaining with another injection opportunity.
extension-permissions-security.content-security-policy.style-src-safeSee full patternWithout CSP violation reporting, you have no signal when your extension's security policy is being actively exercised — either by legitimate-but-unexpected resource loads during development, or by an attacker probing injection paths in the wild. NIST SP 800-53 SI-7 (Software, Firmware, and Information Integrity) requires detective controls to surface policy violations. A `report-uri` or `report-to` endpoint gives you an event stream of blocked requests, which is the only way to distinguish a misconfigured CSP from an ongoing attack attempt. This is an observability gap, not a direct vulnerability — but the absence of signal means breaches go undetected longer.
Why this severity: Info because absence of violation reporting does not directly increase attack surface, but eliminates the detective control needed to identify active exploitation or CSP misconfiguration in production.
extension-permissions-security.content-security-policy.violation-reportingSee full patternCWE-79 (XSS) and CWE-653 (Insufficient Compartmentalization) both apply when content scripts run in the MAIN world. A content script in the MAIN world shares the JavaScript heap with the host page — the page's JavaScript can read and modify the extension's variables, and vice versa. A compromised or malicious page can tamper with the extension's logic directly, override its functions, or read any data it has loaded. OWASP A03 (Injection) governs this. Chrome's ISOLATED world is the default for a reason: it creates a separate JavaScript environment, preventing the host page from accessing or polluting the extension's execution context. The Chrome content script documentation makes this the required default.
Why this severity: High because running in the MAIN world removes the JavaScript heap boundary between the extension and the host page, allowing the page to directly manipulate extension state and bypass isolation.
extension-permissions-security.content-script-isolation.isolated-worldSee full patternA content script injecting into `<all_urls>` runs on every page the user visits — banking portals, health records, internal tools — whether or not the extension has any useful function there. CWE-250 governs this: the content script context executes with unnecessary privileges on irrelevant origins. Chrome's match pattern documentation and OWASP A01 (Broken Access Control) both call for the minimal set of origins. Broad injection also degrades browser performance (each injection is a separate script parse and execution per tab), increases memory usage, and creates a larger attack surface for page-to-extension message injection attacks.
Why this severity: Medium because over-broad match patterns inject the content script into sensitive origins (banking, health) where the extension has no purpose, compounding any content-script XSS into a cross-origin exposure.
extension-permissions-security.content-script-isolation.specific-matchesSee full patternCWE-79 (XSS) in a content script context is dangerous not just for the extension user but for the host page: a content script that reads text from the DOM and inserts it back via `innerHTML` without sanitization can be triggered by the host page itself injecting a payload. CWE-116 (Improper Encoding or Escaping) names the adjacent failure. OWASP A03 (Injection) applies. Content scripts occupy a trusted position relative to the host page — they can read storage, message the background script, and interact with `chrome.*` APIs — so an XSS here has a blast radius beyond what a typical page-level XSS would achieve.
Why this severity: High because unsanitized `innerHTML` in a content script creates an XSS vector in a trusted extension context that can access `chrome.*` APIs and user storage, extending the blast radius beyond the page.
extension-permissions-security.content-script-isolation.page-data-sanitizedSee full patternCWE-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.
Why this severity: 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.
extension-permissions-security.content-script-isolation.shadow-domSee full patternWhen a Chrome extension is updated or disabled while the user has a tab open, the content script context is invalidated but any DOM elements it injected remain. Without cleanup logic, updating the extension leaves orphaned buttons, sidebars, or overlays on long-lived pages — a support and reliability failure that manifests as 'ghost UI' that does nothing when clicked. ISO 25010 reliability requirements apply: a component that cannot clean up its own side effects on context invalidation is not reliably bounded. In enterprise environments where tabs stay open for days, uncleaned DOM from invalidated extension contexts accumulates and causes user-visible breakage.
Why this severity: Low because orphaned DOM elements are a reliability failure rather than a security vulnerability, but they directly surface to users as broken UI after every extension update.
extension-permissions-security.content-script-isolation.dom-cleanupSee full patternCWE-250 governs unused host permissions: an extension holding a host permission for a domain it never contacts has an unnecessarily wide privilege envelope. If the extension is compromised — via a malicious dependency, an XSS in extension pages, or a supply-chain attack — it can make credentialed requests to any domain in its `host_permissions` list, not just the domains it was designed for. Chrome Web Store review specifically checks for host permissions that aren't justified by the extension's functionality. OWASP A01 (Broken Access Control) applies: the least-privilege principle requires pruning grants that are no longer needed.
Why this severity: Medium because unused host permissions silently expand the blast radius of any extension compromise, allowing unauthorized cross-origin requests to domains that were never part of the extension's design.
extension-permissions-security.host-permissions-minimization.unused-removedSee full patternCWE-346 (Origin Validation Error) and CWE-284 (Improper Access Control) both apply to an `externally_connectable` configuration that uses wildcards. With `ids: ['*']` or `matches: ['*://*/*']`, any installed extension or any website can send messages directly to your extension's background script via `chrome.runtime.connect` or `chrome.runtime.sendMessage`. This turns your background script's message handlers into a public API callable by adversaries. OWASP A01 (Broken Access Control) governs this: `externally_connectable` is an explicit access grant and must enumerate specific callers. Chrome's documentation is explicit that wildcard `ids` and `matches` are dangerous defaults.
Why this severity: High because a wildcard `externally_connectable` configuration makes the extension's background script callable by any website or extension, converting privileged background logic into a publicly accessible attack surface.
extension-permissions-security.host-permissions-minimization.externally-connectable-restrictedSee full patternCWE-200 (Exposure of Sensitive Information) applies when `connect-src` is unrestricted: an XSS vulnerability in an extension page could exfiltrate user data, stored credentials, or browsing history to an arbitrary attacker-controlled server if `connect-src` allows `*`. OWASP A05 (Security Misconfiguration) governs this: a CSP that restricts scripts but not network connections provides incomplete protection. An explicit `connect-src` allowlist is also a trust signal to users and Chrome Web Store reviewers — it makes explicit which servers the extension communicates with, which is a requirement for extensions handling sensitive user data.
Why this severity: Low because exploiting an unrestricted `connect-src` requires a prior code execution vulnerability in the extension, but when that condition exists, the network exfiltration path is completely unblocked.
extension-permissions-security.host-permissions-minimization.connect-src-limitedSee full patternCWE-200 (Information Exposure) applies directly: resources listed in `web_accessible_resources` with `matches: ['<all_urls>']` are fetchable by any website on the internet. This enables extension fingerprinting — a site can probe for specific resource paths to detect which extensions a user has installed, bypassing privacy expectations. OWASP A01 (Broken Access Control) governs the broader failure: the resource exposure is an access grant, and that grant should be minimal. Chrome's `web_accessible_resources` MV3 API was specifically redesigned to require a `matches` array precisely to close the fingerprinting vector that the MV2 API left open.
Why this severity: Low because globally accessible web resources enable reliable extension fingerprinting by any website, leaking extension presence to third-party tracking and analytics without user awareness.
extension-permissions-security.host-permissions-minimization.web-accessible-scopedSee full patternA persistent MV2 background script runs continuously from browser launch to shutdown, consuming memory and CPU even when the extension is idle. ISO 25010 performance-efficiency requirements apply: a component that holds resources it does not need is inefficient by definition. Chrome's MV3 mandate migrates all extensions to service workers precisely to eliminate persistent background scripts. Beyond resource consumption, persistent background scripts accumulate state across long sessions, which creates subtle bugs when extension logic assumes a clean startup context. Chrome Web Store's MV3 timeline treats `persistent: true` in MV2 as a technical debt marker that blocks long-term store access.
Why this severity: Info because persistent background scripts are a performance and architectural concern rather than a direct security vulnerability, but they indicate non-compliance with Chrome's MV3 roadmap requirements.
extension-permissions-security.host-permissions-minimization.non-persistent-backgroundSee full patternChrome Web Store review requires permission justification documentation for extensions requesting sensitive permissions — undocumented permissions are a common cause of rejection and post-publication removal. NIST SP 800-53 AC-1 (Access Control Policy) requires that access grants be documented and justified to meet baseline governance requirements. Beyond compliance, permission documentation is a user trust mechanism: a `PERMISSIONS.md` file that explains why each permission is needed gives security-conscious users and IT administrators the information they need to make informed deployment decisions, particularly for enterprise extensions.
Why this severity: Info because absent permission documentation is a governance and review compliance gap rather than a direct vulnerability, but it routinely causes Chrome Web Store rejections for sensitive-permission extensions.
extension-permissions-security.host-permissions-minimization.permission-justificationSee full patternRun this audit in your AI coding tool (Claude Code, Cursor, Bolt, etc.) and submit results here for scoring and benchmarks.
Open Extension Permissions & Security Audit