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
- Privileged permissions (
tabs,cookies,history,webRequest) must not appear inpermissions. They must be inoptional_permissionsonly. - Host permissions must not be in
host_permissionsas required. Useoptional_host_permissionsinstead. - 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.