Skip to main content

EXT-002 Overbroad extension permissions

Browser extension manifests declare what the extension is allowed to touch: hosts via host_permissions, browser APIs via permissions. An extension with <all_urls> reads every tab. An extension with the debugger permission drives the Chrome DevTools protocol on every page (full DOM rewrites, network interception, arbitrary JS evaluation). An extension with webRequestBlocking can modify or cancel any HTTP request the browser makes.

A reasonable extension picks the minimum surface it needs. An extension that piles them together (cookies + tabs + history + webRequest at once) has chosen broad reach over precision; a publisher compromise of that extension is a session-token incident for everywhere the host is signed in.

What Vulkro detects

Rule fires when an extension's manifest declares any of the following:

  • <all_urls> host permission (or its equivalents *://*/*, http://*/*, https://*/*) anywhere in host_permissions or permissions. Severity: High. Evidence weight: 0.9.
  • High-impact API permissions: debugger or webRequestBlocking. Either alone upgrades to High. Evidence weight: 0.9.
  • Broad API permission cluster: two or more of tabs, history, cookies, downloads, webNavigation, webRequest, <all_urls> declared together. Severity: Medium. Evidence weight: 0.6.

Confidence: High in every case (literal manifest read, rubric rule 2 invariant). Evidence signal: extension-overbroad-permissions, source Pattern.

VS Code-family editor extensions are skipped: the editor's extensions.json doesn't carry per-extension permissions on disk. The rule applies to extensions whose manifest the auditor can read (Chromium per-extension manifest.json, Firefox addon records).

Non-compliant manifest

{
"manifest_version": 3,
"name": "Productivity helper",
"version": "1.0.0",
"permissions": ["debugger", "tabs", "cookies", "history"],
"host_permissions": ["<all_urls>"]
}

The debugger permission alone is enough to fire (High); the <all_urls> host permission alone is also enough (High); the tabs + cookies + history cluster is also enough (Medium). The detector reports the most severe driver in the finding message.

Compliant manifest

{
"manifest_version": 3,
"name": "Productivity helper",
"version": "1.0.0",
"permissions": ["storage"],
"host_permissions": ["https://app.example.com/*"]
}

The extension only needs storage for its own data and reach to its own backend. Permissions are scoped to that.

Remediation

  1. Audit the extension's marketplace listing to confirm it genuinely needs the declared reach. If not, replace it with a narrower alternative or contact the publisher about a scoped permission set.
  2. If you author the extension, pin host_permissions to the specific hosts the workflow uses. Avoid <all_urls> unless the extension's purpose is genuinely cross-origin.
  3. Avoid the high-impact API set unless required. debugger is appropriate for devtools-class extensions; webRequestBlocking is appropriate for declarative-content blockers (and even then, prefer declarativeNetRequest in Manifest V3 where feasible).
  4. Treat extensions with <all_urls> or debugger as session- token-class risks: any publisher compromise of such an extension exfiltrates everything the host can see, the next time the user opens the browser.

See also

References