Content scripts injected only on domains where strictly necessary
Why it matters
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.
Severity rationale
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.
Remediation
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.
Detection
-
ID:
content-scripts-scoped -
Severity:
high -
What to look for: Examine the
content_scriptsarray inmanifest.json. Check thematchespatterns 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_starthas 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_startinjection 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_startinjection used without technical justification for sites wheredocument_idlewould work. -
Skip (N/A) when: The extension has no content scripts (not present in manifest
content_scriptsarray, and no dynamicchrome.scripting.executeScriptinjection 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
activeTabpermission withchrome.scripting.executeScripttriggered by a button click rather than declarative content scripts.
External references
- iso-25010:2011 · performance-efficiency.resource-utilization
Taxons
History
- 2026-04-18·v1.0.0·Initial import from extension-ux-performance·automated