Content scripts declared with <all_urls> or *://*/* run on every page the user visits, including banking sites, personal email, and internal tooling — even when the extension only needs to operate on one or two specific domains. ISO 25010:2011 performance-efficiency.resource-utilisation identifies this as unnecessary resource consumption: the content script consumes memory and may execute initialization code on every single page load. Beyond performance, overly broad match patterns expand the attack surface: a content script running on banking sites that has a vulnerability can be exploited in that sensitive context.
High because content scripts running on all URLs consume memory on every page load and increase the exploitable surface area of the extension on sensitive sites.
Narrow matches in manifest.json to the minimum set of domains the extension actually needs. Use document_idle injection timing unless there is a specific technical requirement for document_start.
{
"content_scripts": [{
"matches": ["https://github.com/*"],
"js": ["content.js"],
"run_at": "document_idle"
}]
}
If the extension must support many user-chosen sites, request activeTab permission instead and inject via chrome.scripting.executeScript on button click — this eliminates the always-on content script entirely and limits injection to one tab at a time, only when the user explicitly invokes the extension.
ID: extension-ux-performance.browser-ux.content-scripts-scoped
Severity: high
What to look for: Examine the content_scripts array in manifest.json. Check the matches patterns for each content script. Look for overly broad patterns: "<all_urls>", "http://*/*", "https://*/*", or "*://*/*" when the extension only needs to function on specific domains. Compare the declared match patterns against what the extension's feature set actually requires. Check injection timing ("run_at": "document_start" vs. "document_idle") — document_start has higher performance cost and is only needed for very specific use cases. Count all instances found and enumerate each.
Pass criteria: Content script match patterns are as narrow as possible while still supporting the extension's declared functionality. If the extension only works on specific sites, match patterns target only those domains. document_start injection is only used where the extension genuinely needs to run before page load. At least 1 implementation must be confirmed.
Fail criteria: Content scripts match <all_urls> or equivalently broad patterns when the extension only targets a small set of sites. document_start injection used without technical justification for sites where document_idle would work.
Skip (N/A) when: The extension has no content scripts (not present in manifest content_scripts array, and no dynamic chrome.scripting.executeScript injection to broad patterns).
Detail on fail: Specify the overly broad pattern and the actual scope needed. Example: "Content scripts declared with matches '<all_urls>' but extension only processes GitHub pull request pages — scope should be narrowed to the target domain" or "run_at:'document_start' on all URLs with a script that only reads the DOM after load — document_idle would suffice and reduce performance cost."
Remediation: Narrow your match patterns to the minimum required scope:
{
"content_scripts": [
{
"matches": ["https://github.com/*"],
"js": ["content.js"],
"run_at": "document_idle"
}
]
}
If you need to inject on many sites but only under user action, consider using activeTab permission with chrome.scripting.executeScript triggered by a button click rather than declarative content scripts.