# Content scripts injected only on domains where strictly necessary

- **Pattern:** `ab-001375` (`extension-ux-performance.browser-ux.content-scripts-scoped`)
- **Severity:** high
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001375
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001375)

## 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`.

```json
{
  "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_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:

  ```json
  {
    "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.

## External references

- iso-25010 performance-efficiency.resource-utilization

Taxons: performance

HTML version: https://auditbuffet.com/patterns/ab-001375
