Skip to main content

Manifest Permission Policy

Chrome Web Store reviews frequently reject extensions that request broad or privileged permissions upfront. The correct pattern is to declare sensitive permissions as optional_permissions and request them at runtime only when needed.

repo-manifest-lint is a CLI tool in @repo/tooling that runs as part of pnpm lint. It enforces this policy so you cannot accidentally ship a manifest that would be rejected in review.

Rules Enforced

  1. Privileged permissions (tabs, cookies, history, webRequest) must not appear in permissions. They must be in optional_permissions only.
  2. Host permissions must not be in host_permissions as required. Use optional_host_permissions instead.
  3. Broad patterns (<all_urls>, *://*/*, http://*/*, https://*/*) must not be required anywhere.

Adding Optional Permissions

Edit apps/extension/manifests/manifest.chrome.json (and manifest.firefox.json for Firefox):

{
"permissions": ["storage", "activeTab"],
"optional_permissions": ["tabs", "cookies"]
}

Then request them at runtime when needed:

const api = getExtensionApi();
const granted = await api.permissions?.request({ permissions: ['tabs'] });
if (granted) {
// Permission granted, proceed
}

Running the Linter

  • As part of lint: pnpm lint (includes manifest check)
  • Manifest only: pnpm lint:manifest-permissions

If the linter fails, it prints specific errors:

Manifest permission policy failed:

- manifest.chrome.json: move 'tabs' from permissions to optional_permissions.
- manifest.chrome.json: move required host_permissions 'https://*/*' to optional_host_permissions.

Fix the manifest and re-run. The build will fail in CI if the policy is violated.